分类: 嵌入式
2011-05-11 15:46:29
接着上篇的分析,首先追踪下源码:arch/arm/mach-mx27/mx27ads_gpio.c
gpio_sensor_active -> gpio_request_mux -> gpio_config_mux
gpio_config_mux用于完成相应pin需要模式的配置:
gpio_config_mux - just configure the mode of the gpio pin.
pin a pin number as defined in \b #iomux_pin_name_t
mode a module as define in \b #gpio_mux_mode_t;
* GPIO_MUX_PRIMARY set pin to work as primary function.
* GPIO_MUX_ALT set pin to work as alternate function.
* GPIO_MUX_GPIO set pin to work as output function based the data register
* GPIO_MUX_INPUT1 set pin to work as input function connected with A_OUT
* GPIO_MUX_INPUT2 set pin to work as input function connected with B_OUT
* GPIO_MUX_OUTPUT1 set pin to work as output function connected with A_IN
* GPIO_MUX_OUTPUT2 set pin to work as output function connected with B_IN
* GPIO_MUX_OUTPUT3 set pin to work as output function connected with C_IN
0 if successful, Non-zero otherwise
*/
int gpio_config_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode)
{
unsigned long lock_flags;
u32 gius_reg, gpr_reg;
struct mxc_gpio_port *port;
u32 index, gpio = IOMUX_TO_GPIO(pin);
port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]);
index = GPIO_TO_INDEX(gpio);
首先定义了一个端口结构体mxc_gpio_port,其中包含了一个端口所必须的信息:
struct mxc_gpio_port {
u32 num; /*!< gpio port number */
u32 base; /*!< gpio port base VA */
u16 irq; /*!< irq number to the core */
u16 virtual_irq_start; /*!< virtual irq start number */
};
通过IOMUX_TO_GPIO函数找到对应pin的GPIO索引。
再看port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]);
其中mxc_gpio_ports为gpio端口列表,如下:
struct mxc_gpio_port mxc_gpio_ports[GPIO_PORT_NUM] = {
{
.num = 0,
.base = IO_ADDRESS(GPIO_BASE_ADDR),
.irq = INT_GPIO,
.virtual_irq_start = MXC_GPIO_BASE,
},
{
.num = 1,
.base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x100,
.irq = INT_GPIO,
.virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN,
},
{
.num = 2,
.base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x200,
.irq = INT_GPIO,
.virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 2,
},
{
.num = 3,
.base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x300,
.irq = INT_GPIO,
.virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 3,
},
{
.num = 4,
.base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x400,
.irq = INT_GPIO,
.virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 4,
},
{
.num = 5,
.base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x500,
.irq = INT_GPIO,
.virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 5,
},
};
通过GPIO_TO_PORT找到对应pin的端口号,然后用端口列表找到对应端口的相应信息。
index = GPIO_TO_INDEX(gpio);
用于找到对应端口的引脚。这里有个个人理解,index为GPIO模块中对应端口中的引脚,而参数pin是mx27芯片所有管脚中的索引。
继续看源码:
pr_debug("%s: Configuring PORT %c, bit %d\n",__FUNCTION__, port->num + 'A', index);
spin_lock_irqsave(&gpio_mux_lock, lock_flags); //保存终端状态
gius_reg = __raw_readl(port->base + GPIO_GIUS);
gpr_reg = __raw_readl(port->base + GPIO_GPR);
这两句主要定位需要的寄存器。
继续源码:
switch (mode) {
case GPIO_MUX_PRIMARY:
gius_reg &= ~(1L << index);
gpr_reg &= ~(1L << index);
break;
case GPIO_MUX_ALT:
gius_reg &= ~(1L << index);
gpr_reg |= (1L << index);
break;
case GPIO_MUX_GPIO:
gius_reg |= (1L << index);
_gpio_set_ocr(port, index, GPIO_OUTPUT_DR);
break;
case GPIO_MUX_INPUT1:
gius_reg |= (1L << index);
_gpio_set_iconfa(port, index, GPIO_INPUT_GPIO);
break;
case GPIO_MUX_INPUT2:
gius_reg |= (1L << index);
_gpio_set_iconfb(port, index, GPIO_INPUT_GPIO);
break;
case GPIO_MUX_OUTPUT1:
gius_reg |= (1L << index);
_gpio_set_ocr(port, index, GPIO_OUTPUT_A);
break;
case GPIO_MUX_OUTPUT2:
gius_reg |= (1L << index);
_gpio_set_ocr(port, index, GPIO_OUTPUT_B);
break;
case GPIO_MUX_OUTPUT3:
gius_reg |= (1L << index);
_gpio_set_ocr(port, index, GPIO_OUTPUT_C);
break;
default:
spin_unlock_irqrestore(&gpio_mux_lock, lock_flags);
return -1;
}
以上根据传入的不同mode,进行设置。
__raw_writel(gius_reg, port->base + GPIO_GIUS);
__raw_writel(gpr_reg, port->base + GPIO_GPR); //写入寄存器
spin_unlock_irqrestore(&gpio_mux_lock, lock_flags); //恢复终端状态
return 0;
}
the reserved bits (unimplemented GPIO bits)