Odroid-XU4/3提供1个30针的双排扩展头“CON10”。下面是对这些扩展引脚的说明。在扩展报头的所有信号都只是PWRON信号1.8V。 如上图,扩展的引脚功能分别有ADC、UART、SPI、I2C、GPIO,每个gpio都会有相应的扩展号在内核中标识,所以对GPIO 的自定义设置都是通过它这个扩展号去标识。
对于GPIO驱动的开发在官网WIKI中只介绍了上图中扩展引脚和扩展号,经过笔者不断地搜素寻找,终于在它的内核里面找到相应的GPIO驱动。在ioboard-keyled.c中:
// GPIO Export Number define #define GPX2_5_EXPORT_NUM 29 #define GPX2_6_EXPORT_NUM 30 #define GPX1_6_EXPORT_NUM 22 #define GPX1_2_EXPORT_NUM 18 #define GPX2_7_EXPORT_NUM 31 #define GPX2_4_EXPORT_NUM 28 #define GPX1_3_EXPORT_NUM 19 #define GPB3_2_EXPORT_NUM 209 #define GPX2_0_EXPORT_NUM 24
以上是它对GPIO引脚扩展号的声明。
static struct {
int gpio_index; // Control Index
int gpio; // GPIO Number
char *name; // GPIO Name == sysfs attr name (must)
bool output; // 1 = Output, 0 = Input
int value; // Default Value(only for output)
int pud; // Pull up/down register setting : S3C_GPIO_PULL_DOWN, UP, NONE
} sControlGpios[] = {
{ IOBOARD_SW1, GPX2_5_EXPORT_NUM, "sw1", 0, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_SW2, GPX2_6_EXPORT_NUM, "sw2", 0, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_SW3, GPX1_6_EXPORT_NUM, "sw3", 0, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_SW4, GPX1_2_EXPORT_NUM, "sw4", 0, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_LED1, GPX2_7_EXPORT_NUM, "led1", 1, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_LED2, GPX2_4_EXPORT_NUM, "led2", 1, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_LED3, GPX1_3_EXPORT_NUM, "led3", 1, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_LED4, GPB3_2_EXPORT_NUM, "led4", 1, 0, S3C_GPIO_PULL_NONE },
{ IOBOARD_LED5, GPX2_0_EXPORT_NUM, "led5", 1, 1, S3C_GPIO_PULL_NONE },
};
这是GPIO的结构体声明gpio_index是一个枚举的标识,gpio是该GPIO对应的扩展号,name及是一个名字,output是对该引脚设置输入还是输出, value是设置输出的情况下的值,0还是1
此外该文件代码里的探测函数ioboard_keyled_probe对引脚作了相应的初始化设置,主体代码如下:
// Control GPIO Init
for (i = 0; i < ARRAY_SIZE(sControlGpios); i++) {
if(sControlGpios[i].gpio) {
if(gpio_request(sControlGpios[i].gpio, sControlGpios[i].name)) {
printk("%s : %s gpio reqest err!\n", __FUNCTION__, sControlGpios[i].name);
}
else {
if(sControlGpios[i].output) gpio_direction_output (sControlGpios[i].gpio, sControlGpios[i].value);
else gpio_direction_input (sControlGpios[i].gpio);
s3c_gpio_setpull (sControlGpios[i].gpio, sControlGpios[i].pud);
}
}
}
代码中还有设置gpio的函数,都很简单,就不做详细介绍,代码如下所示:
static ssize_t set_gpio (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned int val, i;
if(!(sscanf(buf, "%d\n", &val))) return -EINVAL;
for (i = 0; i < ARRAY_SIZE(sControlGpios); i++) {
if(sControlGpios[i].gpio) {
if(!strcmp(sControlGpios[i].name, attr->attr.name)) {
if(sControlGpios[i].output)
gpio_set_value(sControlGpios[i].gpio, ((val != 0) ? 1 : 0));
else
printk("This GPIO Configuration is INPUT!!\n");
return count;
}
}
}
printk("%s[%d] : undefined gpio!\n", __func__,__LINE__);
return count;
}
通过以上内核的代码,我们就可以模仿的写我们自己的GPIO驱动了,我们只需要知道我们所要设置的GPIO的扩展号即可,不需要对设备树等做什么更改。