全部博文(150)
分类: LINUX
2009-12-21 11:35:15
GPIO操作:
GPIO Read Mode
The programming sequence for reading input signals is as follows:
1. Configure IOMUX to select GPIO mode (via IOMUXC).
2. Configure the GPIO direction register (GDR) to input.
3. Read value from the data register or pad status register.
GPIO Write Mode
The programming sequence for driving output signals should be as follows:
1. Configure IOMUX to select GPIO mode (via IOMUXC).
2. Configure GPIO direction register (GDR) to output.
3. Write value to data register (DR).
Linux中的程序定义:
/*!
* various IOMUX functions
*/
typedef enum iomux_pin_config {
MUX_CONFIG_FUNC = 0, /*!< used as function */
MUX_CONFIG_ALT1, /*!< used as alternate function 1 */
MUX_CONFIG_ALT2, /*!< used as alternate function 2 */
MUX_CONFIG_ALT3, /*!< used as alternate function 3 */
MUX_CONFIG_ALT4, /*!< used as alternate function 4 */
MUX_CONFIG_ALT5, /*!< used as alternate function 5 */
MUX_CONFIG_ALT6, /*!< used as alternate function 6 */
MUX_CONFIG_ALT7, /*!< used as alternate function 7 */
MUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */
MUX_CONFIG_GPIO = MUX_CONFIG_ALT5, /*!< used as GPIO */
} iomux_pin_cfg_t;
/*!
* IOMUX register (base) addresses
*/
enum iomux_reg_addr {
IOMUXGPR0 = IO_ADDRESS(IOMUXC_BASE_ADDR), /*!< General p urpose 0 */
IOMUXGPR1 = IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x004, /*!< General purpose 1 */
IOMUXSW_MUX_CTL = IO_ADDRESS(IOMUXC_BASE_ADDR) + MUX_I_START, /*!< MUX control */
IOMUXSW_MUX_END = IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_END, /*!< last MUX control register */
IOMUXSW_PAD_CTL = IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START, /*!< Pad control */
IOMUXSW_PAD_END = IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_END, /*!< last Pad control register */
IOMUXSW_INPUT_CTL = IO_ADDRESS(IOMUXC_BASE_ADDR) + INPUT_CTL_START, /*!< input select register */
IOMUXSW_INPUT_END = IO_ADDRESS(IOMUXC_BASE_ADDR) + INPUT_CTL_END, /*!< last input select register */
};
[arch/arm/plat-mxc/gpio.c]
extern struct mxc_gpio_port mxc_gpio_ports[];
struct gpio_port {
u32 num; /*!< gpio port number */
u32 base; /*!< gpio port base VA */
#ifdef MXC_GPIO_SPLIT_IRQ_2
u16 irq_0_15, irq_16_31;
#else
u16 irq; /*!< irq number to the core */
#endif
u16 virtual_irq_start; /*!< virtual irq start number */
u32 reserved_map; /*!< keep track of which pins are in use */
u32 irq_is_level_map; /*!< if a pin's irq is level sensitive. default is edge */
u32 suspend_wakeup;
u32 saved_wakeup;
spinlock_t lock; /*!< lock when operating on the port */
};
/*!
* Number of GPIO port as defined in the IC Spec
*/
#define GPIO_PORT_NUM 3
static struct gpio_port gpio_port[GPIO_PORT_NUM];
[arch/arm/mach-mx35/devices.c]
struct mxc_gpio_port mxc_gpio_ports[GPIO_PORT_NUM] = {
{
.num = 0,
.base = IO_ADDRESS(GPIO1_BASE_ADDR), //#define GPIO1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000) [include/asm-
arm/arch-mxc/mx35.h]
.irq = MXC_INT_GPIO1, //#define MXC_INT_GPIO1 52//[include/asm-arm/arch-mxc/mx35.h]
.virtual_irq_start = MXC_GPIO_INT_BASE, //#define MXC_GPIO_INT_BASE (MXC_MAX_INT_LINES) //64
},
{
.num = 1,
.base = IO_ADDRESS(GPIO2_BASE_ADDR),
.irq = MXC_INT_GPIO2,
.virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN,
},
{
.num = 2,
.base = IO_ADDRESS(GPIO3_BASE_ADDR),
.irq = MXC_INT_GPIO3,
.virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 2,
},
};
/*!
* This function initializes the GPIO hardware and disables all the
* interrupts. It registers functions for core interrupt handling code,
* for irq-chip based architectures for each interrupt source.
*/
static int __init _mxc_gpio_init(void)
{
int i;
struct gpio_port *port;
printk(KERN_INFO "MXC GPIO hardware\n");
for (i = 0; i < GPIO_PORT_NUM; i++) {
int j, gpio_count = GPIO_NUM_PIN;
port = &gpio_port[i];
port->base = mxc_gpio_ports[i].base;
port->num = mxc_gpio_ports[i].num;
#ifdef MXC_GPIO_SPLIT_IRQ_2
port->irq_0_15 = mxc_gpio_ports[i].irq_0_15;
port->irq_16_31 = mxc_gpio_ports[i].irq_16_31;
#else
port->irq = mxc_gpio_ports[i].irq;
#endif
port->virtual_irq_start = mxc_gpio_ports[i].virtual_irq_start;
port->reserved_map = 0;
spin_lock_init(&port->lock);
/* disable the interrupt and clear the status */
__raw_writel(0, port->base + GPIO_IMR);
__raw_writel(0xFFFFFFFF, port->base + GPIO_ISR);
for (j = port->virtual_irq_start;
j < port->virtual_irq_start + gpio_count; j++) {
set_irq_chip(j, &gpio_irq_chip);
set_irq_handler(j, handle_edge_irq);
set_irq_flags(j, IRQF_VALID);
}
#ifndef MXC_MUX_GPIO_INTERRUPTS
#ifdef MXC_GPIO_SPLIT_IRQ_2
set_irq_chained_handler(port->irq_0_15, mxc_gpio_irq_handler);
set_irq_data(port->irq_0_15, port);
set_irq_chained_handler(port->irq_16_31, mxc_gpio_irq_handler);
set_irq_data(port->irq_16_31, port);
#else
set_irq_chained_handler(port->irq, mxc_gpio_irq_handler);
set_irq_data(port->irq, port);
#endif
#endif
}
#ifdef MXC_MUX_GPIO_INTERRUPTS
set_irq_chained_handler(port->irq, mxc_gpio_mux_irq_handler);
set_irq_data(mxc_gpio_ports[0].irq, gpio_port);
#endif
return 0;
}
可以看出GPIO的设定形式如下:
* -------------------------------------------------------------------
* 31-29 | 28 - 24 |23 - 21| 20 - 10| 9 - 0
* -------------------------------------------------------------------
* IO_P | IO_I | RSVD | PAD_I | MUX_I
* -------------------------------------------------------------------
在MX35平台上,其中IO_PORT代表的是3组GPIO之一,IO_I是GPIO Index(0~31), PAD_I与MUX_I跟IC_SPEC中的IOMUXC_SW_PAD_CTL_PAD_*与
int mxc_request_gpio(iomux_pin_name_t pin)
{
struct gpio_port *port;
u32 index, gpio = IOMUX_TO_GPIO(pin);
if (check_gpio(gpio) < 0)
return -EINVAL;
port = get_gpio_port(gpio);
index = GPIO_TO_INDEX(gpio);
return _request_gpio(port, index);
}
_request_gpio的工作主要是检查相应的GPIO是否有在使用,若已经被占用(port->reserved_map & (1 << index)),就返回Error信息; 否则就标志占用:port->reserved_map |= (1 << index);
mxc_free_gpio做的事情跟mxc_request_gpio相反