mx27的GPIO控制时, 比如设置输入输出方向函数:
/*!
* Exported function to set a GPIO pin's direction
* @param pin a name defined by \b iomux_pin_name_t
* @param is_input 1 (or non-zero) for input; 0 for output
*/
void mxc_set_gpio_direction(iomux_pin_name_t pin, int is_input)
{
struct gpio_port *port;
u32 gpio = IOMUX_TO_GPIO(pin);
if (check_gpio(gpio) < 0)
return;
port = get_gpio_port(gpio);
spin_lock(&port->lock);
_set_gpio_direction(port, GPIO_TO_INDEX(gpio), is_input);
spin_unlock(&port->lock);
}
/*
* Set a GPIO pin's direction
* @param port pointer to a gpio_port
* @param index gpio pin index value (0~31)
* @param is_input 0 for output; non-zero for input
*/
static void _set_gpio_direction(struct gpio_port *port, u32 index, int is_input)
{
u32 reg = port->base + GPIO_GDIR;
u32 l;
l = __raw_readl(reg);
if (is_input)
l &= ~(1 << index);
else
l |= 1 << index;
__raw_writel(l, reg);
}
这里就用到了一个自旋锁,因为mx27系统的gpio控制寄存器,都是好多个pin共享的, 所以操作时,尤其是写时,需要避免竞争,要加个自旋锁。
除了方向控制寄存器,还有写数据寄存器:
/*!
* Exported function to set a GPIO pin's data output
* @param pin a name defined by \b iomux_pin_name_t
* @param data value to be set (only 0 or 1 is valid)
*/
void mxc_set_gpio_dataout(iomux_pin_name_t pin, u32 data)
{
struct gpio_port *port;
u32 gpio = IOMUX_TO_GPIO(pin);
if (check_gpio(gpio) < 0)
return;
port = get_gpio_port(gpio);
spin_lock(&port->lock);
_set_gpio_dataout(port, GPIO_TO_INDEX(gpio), (data == 0) ? 0 : 1);
spin_unlock(&port->lock);
}
/*
* Set a GPIO pin's data output
* @param port pointer to a gpio_port
* @param index gpio pin index value (0~31)
* @param data value to be set (only 0 or 1 is valid)
*/
static void _set_gpio_dataout(struct gpio_port *port, u32 index, u32 data)
{
u32 reg = port->base + GPIO_DR;
u32 l = 0;
l = (__raw_readl(reg) & (~(1 << index))) | (data << index);
__raw_writel(l, reg);
}
还有request gpio:
static inline int _request_gpio(struct gpio_port *port, u32 index)
{
spin_lock(&port->lock);
if (port->reserved_map & (1 << index)) {
printk(KERN_ERR
"GPIO port %d (0-based), pin %d is already reserved!\n",
port->num, index);
dump_stack();
spin_unlock(&port->lock);
return -1;
}
port->reserved_map |= (1 << index);
spin_unlock(&port->lock);
return 0;
}
/*!
* Request ownership for a GPIO pin. The caller has to check the return value
* of this function to make sure it returns 0 before make use of that pin.
* @param pin a name defined by \b iomux_pin_name_t
* @return 0 if successful; Non-zero otherwise
*/
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);
}