http://blog.chinaunix.NET/uid-20543672-id-3067021.html
在移植內核的時候,通常會遇到引腳複用(MUX)的配置問題。在現在的Linux內核中,對於TI的ARM芯片,早已經有了比較通用的MUX配置框架。這對於許多TI的芯片都是通用的,這次看AM335X的代碼順手寫一下分析,以備後用。
- TI的CPU芯片手冊有兩種:
- 一種是datasheet(DS:數據手冊),較小,只是大概介紹下芯片的結構;
- 另一種是Technical Reference Manual(TRM:技術參考手冊),較大,詳細介紹芯片的各部分功能原理和寄存器定義。
- 在開發過程中,這兩個手冊都需要參考,是互補的。
- mux.h
- mux.c
- mux33xx.h
- mux33xx.c
- board-am335xevm.c
-
- (還有一些用到了:arch/arm/plat-omap/include/plat/omap_hwmod.h)
-
/**
-
* struct mux_partition - 包含分區相關信息
-
* @name: 當前分區名
-
* @flags: 本分區的特定標誌
-
* @phys: 物理地址
-
* @size: 分區大小
-
* @base: ioremap 映射過的虛擬地址
-
* @muxmodes: 本分區mux節點鏈表頭
-
* @node: 分區鏈表頭
-
*/
-
struct omap_mux_partition {
-
const char *name;
-
u32 flags;
-
u32 phys;
-
u32 size;
-
void __iomem *base;
-
struct list_head muxmodes;
-
struct list_head node;
- };
-
/**
-
* struct omap_mux_entry - mux信息節點
-
* @mux: omap_mux結構體
-
* @node: 鏈表節點
-
*/
-
struct omap_mux_entry {
-
struct omap_mux mux;
-
struct list_head node;
- };
-
/**
-
* struct omap_mux - omap mux 寄存器偏移和值的數據
-
* @reg_offset: 從Control Module寄存器基地址算起的mux寄存器偏移
-
* @gpio: GPIO 編號
-
* @muxnames: 引腳可用的信號模式字符串指針數組
-
* @balls: 封裝中可用的引腳
-
*/
-
struct omap_mux {
-
u16 reg_offset;
-
u16 gpio;
-
#ifdef CONFIG_OMAP_MUX
-
char *muxnames[OMAP_MUX_NR_MODES];
-
#ifdef CONFIG_DEBUG_FS
-
char *balls[OMAP_MUX_NR_SIDES];
-
#endif
-
#endif
- };
-
#define _AM33XX_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7) \
-
{ \
-
.reg_offset = (AM33XX_CONTROL_PADCONF_##M0##_OFFSET), \
-
.gpio = (g), \
-
.muxnames = { m0, m1, m2, m3, m4, m5, m6, m7 }, \
- }
-
/**
-
* struct omap_board_mux - 初始化mux寄存器的數據
-
* @reg_offset: 從Control Module寄存器基地址算起的mux寄存器偏移
-
* @mux_value: 希望設置的mux寄存器值
-
*/
-
struct omap_board_mux {
-
u16 reg_offset;
-
u16 value;
- };
-
#ifdef CONFIG_OMAP_MUX
-
static struct omap_board_mux board_mux[] __initdata = {
-
AM33XX_MUX(I2C0_SDA, OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW |
-
AM33XX_INPUT_EN | AM33XX_PIN_OUTPUT),
-
AM33XX_MUX(I2C0_SCL, OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW |
-
AM33XX_INPUT_EN | AM33XX_PIN_OUTPUT),
-
{ .reg_offset = OMAP_MUX_TERMINATOR },
-
};
-
#else
-
#define board_mux NULL
- #endif
-
/* 如果引腳沒有定義爲輸入,拉動電阻將會被禁用
-
* 如果定義爲輸入,所提供的標誌位將確定拉動電阻的配置
-
*/
-
#define AM33XX_MUX(mode0, mux_value) \
-
{ \
-
.reg_offset = (AM33XX_CONTROL_PADCONF_##mode0##_OFFSET), \
-
.value = (((mux_value) & AM33XX_INPUT_EN) ? (mux_value)\
-
: ((mux_value) | AM33XX_PULL_DISA)), \
- }
-
/**
-
* omap_mux_init - MUX初始化的私有函數,請勿使用
-
* 由各板級特定的MUX初始化函數調用
-
*/
-
int omap_mux_init(const char *name, u32
flags,
-
u32 mux_pbase, u32 mux_size,
-
struct omap_mux *superset,
-
struct omap_mux *package_subset,
-
struct omap_board_mux *board_mux,
- struct omap_ball *package_balls);
-
/**
-
* am33xx_mux_init() - 用板級特定的設置來初始化MUX系統
-
* @board_mux: 板級特定的MUX配置表
-
*/
-
int __init am33xx_mux_init(struct omap_board_mux *board_subset)
-
{
-
return omap_mux_init("core", 0, AM33XX_CONTROL_PADCONF_MUX_PBASE,
-
AM33XX_CONTROL_PADCONF_MUX_SIZE, am33xx_muxmodes,
-
NULL, board_subset, NULL);
- }
-
/**
-
* omap_mux_init_signal - 根據信號名字符串初始化一個引腳的mux
-
* @muxname: mode0_name.signal_name的格式的Mux名稱
-
* @val: mux寄存器值
-
*/
-
int omap_mux_init_signal(const char *muxname, int val);
-
-
/**
-
* omap_mux_get() - 通過名字返回一個mux分區
-
* @name: mux分區名
-
*
-
*/
-
struct omap_mux_partition *omap_mux_get(const char *name);
-
-
/**
-
* omap_mux_read() - 讀取mux寄存器(通過分區結構體指針和寄存器偏移值)
-
* @partition: Mux分區
-
* @mux_offset: mux寄存器偏移
-
*
-
*/
-
u16 omap_mux_read(struct omap_mux_partition *p, u16 mux_offset);
-
-
/**
-
* omap_mux_write() - 寫mux寄存器(通過分區結構體指針和寄存器偏移值)
-
* @partition: Mux分區
-
* @val: 新的mux寄存器值
-
* @mux_offset: mux寄存器偏移
-
*
-
* 這個函數僅有在非GPIO信號的動態複用需要
-
*/
-
void omap_mux_write(struct omap_mux_partition *p, u16 val, u16
mux_offset);
-
-
/**
-
* omap_mux_write_array() - 寫mux寄存器陣列
-
* @partition: Mux分區
-
* @board_mux: mux寄存器陣列 (用MAP_MUX_TERMINATOR結尾)
-
*
-
* 這個函數僅有在非GPIO信號的動態複用需要
-
*/
-
void omap_mux_write_array(struct omap_mux_partition *p,
- struct omap_board_mux *board_mux);
-
/**
-
* omap_mux_init_gpio - 根據GPIO編號初始化一個信號引腳
-
* @gpio: GPIO編號
-
* @val: mux寄存器值
-
*/
-
int omap_mux_init_gpio(int gpio, int val);
-
-
/**
-
* omap_mux_get_gpio() - 根據GPIO編號獲取一個mux寄存器值
-
* @gpio: GPIO編號
-
*
-
*/
-
u16 omap_mux_get_gpio(int gpio);
-
-
/**
-
* omap_mux_set_gpio() - 根據GPIO編號設定一個mux寄存器值
-
* @val: 新的mux寄存器值
-
* @gpio: GPIO編號
-
*
-
*/
- void omap_mux_set_gpio(u16 val, int gpio);
-
/* 模塊引腳複用結構體 */
-
struct pinmux_config {
-
const char *string_name; /* 信號名格式化字符串,“模式0字符串.目標模式字符串“ */
-
int val; /* 其他mux寄存器可選配置值 */
-
};
-
-
/*
-
* @pin_mux - 單個模塊引腳複用結構體
-
* 其中定義了本模塊所有引腳複用細節.
-
*/
-
static void setup_pin_mux(struct pinmux_config *pin_mux)
-
{
-
int i;
-
-
for (i = 0; pin_mux->string_name != NULL; pin_mux++)
-
omap_mux_init_signal(pin_mux->string_name, pin_mux->val);
-
- }
-
static struct pinmux_config d_can_ia_pin_mux[] = {
-
{"uart0_rxd.d_can0_tx", OMAP_MUX_MODE2 | AM33XX_PULL_ENBL},
-
{"uart0_txd.d_can0_rx", OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP},
-
{NULL, 0},
-
};
-
-
......
-
static void d_can_init(int evm_id, int profile)
-
{
-
switch (evm_id) {
-
case IND_AUT_MTR_EVM:
-
if ((profile == PROFILE_0) || (profile == PROFILE_1)) {
-
setup_pin_mux(d_can_ia_pin_mux);
-
/* Instance Zero */
-
am33xx_d_can_init(0);
-
}
-
break;
-
case GEN_PURP_EVM:
-
if (profile == PROFILE_1) {
-
setup_pin_mux(d_can_gp_pin_mux);
-
/* Instance One */
-
am33xx_d_can_init(1);
-
}
-
break;
-
default:
-
break;
-
}
- }