由于公司的IP
camera使用的是mx27(19内核),设计到7113的移植,移植过程中出现了GPIO口配置错误。所以对其GPIO口和7113所使用GPIO口
进行了分析,刚开始对mx27对于GPIO口的使用,和内核中关于GPIO口的配置方法不是很熟悉,在论坛发帖也没人回,这里做个简单总结。
mx27的GPIO口一共有6个端口,每个端口有32个引脚。看源码:
#define MUX_IO_P 29
#define MUX_IO_I 24
#define _MX27_BUILD_PIN(gp,gi) (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I))
开始对于前两个宏的定义不是很理解,虽然内核注释中写明,一个用于索引GPIO的端口,一个用于在指定端口进行偏移,但是为什么一个是29一个是23,不解.
第三个宏就是找到指定的GPIO引脚。例如对于端口2的21引脚,如下索引:
#define _MX27_BUILD_PIN(1,21) ((1<<MUX_IO_P) | (21<<MUX_IO_I))
源码中定义了一个枚举完成对所有GPIO的功能索引:
typedef enum iomux_pins {
......
MX27_PIN_CSI_D0 = _MX27_BUILD_PIN(1, 10), MX27_PIN_CSI_D1 = _MX27_BUILD_PIN(1, 11), MX27_PIN_CSI_D2 = _MX27_BUILD_PIN(1, 12), MX27_PIN_CSI_D3 = _MX27_BUILD_PIN(1, 13), MX27_PIN_CSI_D4 = _MX27_BUILD_PIN(1, 14), MX27_PIN_CSI_MCLK = _MX27_BUILD_PIN(1, 15), MX27_PIN_CSI_PIXCLK = _MX27_BUILD_PIN(1, 16), MX27_PIN_CSI_D5 = _MX27_BUILD_PIN(1, 17), MX27_PIN_CSI_D6 = _MX27_BUILD_PIN(1, 18), MX27_PIN_CSI_D7 = _MX27_BUILD_PIN(1, 19), MX27_PIN_CSI_VSYNC = _MX27_BUILD_PIN(1, 20), MX27_PIN_CSI_HSYNC = _MX27_BUILD_PIN(1, 21),
........
}
只贴出了与摄像头功能匹配的部分。
MX27_PIN_CSI_D2 = _MX27_BUILD_PIN(1, 12), 是为了将port 2的pin 12定义为CSI_D2,查看第5章的Pin MUX Table:
Primary
Alternate GPIO
default
NVDD 11 Slow/Hyst CSI_D2 I UART6_CTS O PB12 PUEN LCDC_TEST8 PB12
可见需要将1,12设置为primary功能,与功能描述一致,可见理解是正确的。
为了将1,12(及portB的12端口)设置为primary功能可以用一下方法:
gpio_request_mux(MX27_PIN_CSI_D2, GPIO_MUX_PRIMARY);
gpio_request_mux的实现:
int gpio_request_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode) { int ret; ret = mxc_request_gpio(pin); if (ret == 0) { ret = gpio_config_mux(pin, mode); if (ret) { mxc_free_gpio(pin); } } return ret; }
函数中首先调用mxc_request_gpio来完成对对用pin的申请,只有在申请成功(返回为零时)才调用gpio_config_mux来完成对pin的功能配置。
mxc_request_gpio源码:
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); //得到gpio的端口号 index = GPIO_TO_INDEX(gpio); //得到gpio口在对应端口的索引号
return _request_gpio(port, index); }
具体功能的实现在_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; }
其中port结构体中的reserved_map存放着对应pin的状态,表明pin是否已经被占用。这里需要注意的是reserved_map为
1时表示该pin为保留管脚,不能被使用。如果未保留则申请成功返回零,同时设置reserved_map的值为1.也即当打印出如下信息时:
GPIO port %d (0-based), pin %d is already reserved! 表示该pin不可用。 struct 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 */ 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 */ spinlock_t lock; /*!< lock when operating on the port */ };
通过学习,解决了7113在19内核的移植问题。 |