1、arch/arm/plat-s3c64xx/gpiolib.c文件中有如下:
arch_initcall(s3c64xx_gpiolib_init);这个应该实在系统初始化时调用。
static __init int s3c64xx_gpiolib_init(void)
{
s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
s3c64xx_gpiolib_add_4bit);
s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
s3c64xx_gpiolib_add_4bit2);
s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);
return 0;
}
这三的蓝色部分是什么呢?看下面的源码,应该知道其是个struct s3c_gpio_chip *chips结构体,在同一个文件中定义,现在原始的结构体:
/**
* struct s3c_gpio_chip - wrapper for specific implementation of gpio对具体GPIO的包装
* @chip: The chip structure to be exported via gpiolib. 芯片的结构,配置通过gpiolib向外输出
* @base: The base pointer to the gpio configuration registers.
* @config: special function and pull-resistor control information.
*
* This wrapper provides the necessary information for the Samsung
* specific gpios being registered with gpiolib.
*/
struct s3c_gpio_chip {
struct gpio_chip chip;
struct s3c_gpio_cfg*config;
void __iomem*base;
};
struct gpio_chip源码如下:
/**
* struct gpio_chip - abstract a GPIO controller 对GPIO控制器的抽象
* @label: for diagnostics为判断而设
* @dev: optional device providing the GPIOs
* @owner: helps prevent removal of modules exporting active GPIOs
* @request: optional hook for chip-specific activation, such as
*enabling module power and clock; may sleep
* @free: optional hook for chip-specific deactivation, such as
*disabling module power and clock; may sleep
* @direction_input: configures signal "offset" as input, or returns error
* @get: returns value for signal "offset"; for output signals this
*returns either the value actually sensed, or zero
* @direction_output: configures signal "offset" as output, or returns error
* @set: assigns output value for signal "offset"
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
*implementation may not sleep
* @dbg_show: optional routine to show contents in debugfs; default code
*will be used when this is omitted, but custom code can show extra
*state (such as pullup/pulldown configuration).
* @base: identifies the first GPIO number handled by this chip; or, if
*negative during registration, requests dynamic ID allocation.
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
*handled is (base + ngpio - 1).
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
*must while accessing GPIO expander chips over I2C or SPI
*
* A gpio_chip can help platforms abstract various sources of GPIOs so
* they can all be accessed through a common programing interface.
帮助具体平台抽象各种GPIO来源,是能用统一的接口操作
* Example sources would be SOC controllers, FPGAs, multifunction
* chips, dedicated GPIO expanders, and so on.
*
* Each chip controls a number of signals, identified in method calls
* by "offset" values in the range 0..(@ngpio - 1). When those signals
* are referenced through calls like gpio_get_value(gpio), the offset
* is calculated by subtracting @base from the gpio number.
*/
struct gpio_chip {
const char*label;
struct device*dev;
struct module*owner;
int(*request)(struct gpio_chip *chip,
unsigned offset);
void(*free)(struct gpio_chip *chip,
unsigned offset);
int(*direction_input)(struct gpio_chip *chip,
unsigned offset);
int(*get)(struct gpio_chip *chip,
unsigned offset);
int(*direction_output)(struct gpio_chip *chip,
unsigned offset, int value);
void(*set)(struct gpio_chip *chip,
unsigned offset, int value);
int(*to_irq)(struct gpio_chip *chip,
unsigned offset);
void(*dbg_show)(struct seq_file *s,
struct gpio_chip *chip);
intbase;
u16ngpio;
unsignedcan_sleep:1;
unsignedexported:1;
};
再看具体的实例:
static struct s3c_gpio_chipgpio_4bit[] = {与上面第一个相对应
{
.base= S3C64XX_GPA_BASE,
.config= &gpio_4bit_cfg_eint0111,
.chip= {
.base= S3C64XX_GPA(0),
.ngpio= S3C64XX_GPIO_A_NR,
.label= "GPA",
},
}, {
.base= S3C64XX_GPB_BASE,
.config= &gpio_4bit_cfg_eint0111,
.chip= {
.base= S3C64XX_GPB(0),
.ngpio= S3C64XX_GPIO_B_NR,
.label= "GPB",
},
}, {
.base= S3C64XX_GPC_BASE,
.config= &gpio_4bit_cfg_eint0111,
.chip= {
.base= S3C64XX_GPC(0),
.ngpio= S3C64XX_GPIO_C_NR,
.label= "GPC",
},
}, {
.base= S3C64XX_GPD_BASE,
.config= &gpio_4bit_cfg_eint0111,
.chip= {
.base= S3C64XX_GPD(0),
.ngpio= S3C64XX_GPIO_D_NR,
.label= "GPD",
},
}, {
.base= S3C64XX_GPE_BASE,
.config= &gpio_4bit_cfg_noint,
.chip= {
.base= S3C64XX_GPE(0),
.ngpio= S3C64XX_GPIO_E_NR,
.label= "GPE",
},
}, {
.base= S3C64XX_GPG_BASE,
.config= &gpio_4bit_cfg_eint0111,
.chip= {
.base= S3C64XX_GPG(0),
.ngpio= S3C64XX_GPIO_G_NR,
.label= "GPG",
},
}, {
.base= S3C64XX_GPM_BASE,
.config= &gpio_4bit_cfg_eint0011,
.chip= {
.base= S3C64XX_GPM(0),
.ngpio= S3C64XX_GPIO_M_NR,
.label= "GPM",
},
},
};
第二部分:
static struct s3c_gpio_chipgpio_4bit2[] = {与上面第二个相对应
{
.base= S3C64XX_GPH_BASE + 0x4,
.config= &gpio_4bit_cfg_eint0111,
.chip= {
.base= S3C64XX_GPH(0),
.ngpio= S3C64XX_GPIO_H_NR,
.label= "GPH",
},
}, {
.base= S3C64XX_GPK_BASE + 0x4,
.config= &gpio_4bit_cfg_noint,
.chip= {
.base= S3C64XX_GPK(0),
.ngpio= S3C64XX_GPIO_K_NR,
.label= "GPK",
},
}, {
.base= S3C64XX_GPL_BASE + 0x4,
.config= &gpio_4bit_cfg_eint0011,
.chip= {
.base= S3C64XX_GPL(0),
.ngpio= S3C64XX_GPIO_L_NR,
.label= "GPL",
},
},
};
第三部分:
static struct s3c_gpio_chipgpio_2bit[]= {与上面第三个相对应
{
.base= S3C64XX_GPF_BASE,
.config= &gpio_2bit_cfg_eint11,
.chip= {
.base= S3C64XX_GPF(0),
.ngpio= S3C64XX_GPIO_F_NR,
.label= "GPF",
},
}, {
.base= S3C64XX_GPI_BASE,
.config= &gpio_2bit_cfg_noint,
.chip= {
.base= S3C64XX_GPI(0),
.ngpio= S3C64XX_GPIO_I_NR,
.label= "GPI",
},
}, {
.base= S3C64XX_GPJ_BASE,
.config= &gpio_2bit_cfg_noint,
.chip= {
.base= S3C64XX_GPJ(0),
.ngpio= S3C64XX_GPIO_J_NR,
.label= "GPJ",
},
}, {
.base= S3C64XX_GPN_BASE,
.config= &gpio_2bit_cfg_eint10,
.chip= {
.base= S3C64XX_GPN(0),
.ngpio= S3C64XX_GPIO_N_NR,
.label= "GPN",
},
}, {
.base= S3C64XX_GPO_BASE,
.config= &gpio_2bit_cfg_eint11,
.chip= {
.base= S3C64XX_GPO(0),
.ngpio= S3C64XX_GPIO_O_NR,
.label= "GPO",
},
}, {
.base= S3C64XX_GPP_BASE,
.config= &gpio_2bit_cfg_eint11,
.chip= {
.base= S3C64XX_GPP(0),
.ngpio= S3C64XX_GPIO_P_NR,
.label= "GPP",
},
}, {
.base= S3C64XX_GPQ_BASE,
.config= &gpio_2bit_cfg_eint11,
.chip= {
.base= S3C64XX_GPQ(0),
.ngpio= S3C64XX_GPIO_Q_NR,
.label= "GPQ",
},
},
};
.config= &gpio_2bit_cfg_eint11类似的这些是什么呢?这涉及到上面的结构体
struct s3c_gpio_chip {
struct gpio_chip chip;
struct s3c_gpio_cfg*config;
void __iomem*base;
};
源码如下:注意看注释,讲的很明白。
/**
* struct s3c_gpio_cfg GPIO configuration
* @cfg_eint: Configuration setting when used for external interrupt source外部中断
* @get_pull: Read the current pull configuration for the GPIO
* @set_pull: Set the current pull configuraiton for the GPIO
* @set_config: Set the current configuration for the GPIO
* @get_config: Read the current configuration for the GPIO
*
* Each chip can have more than one type of GPIO bank available and some
* have different capabilites even when they have the same control register
* layouts. Provide an point to vector control routine and provide any
* per-bank configuration information that other systems such as the
* external interrupt code will need.
*/ 指向具体端口的函数调转表
struct s3c_gpio_cfg {
unsigned intcfg_eint;
s3c_gpio_pull_t(*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
s3c_gpio_pull_t pull);
unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
unsigned config);
};
那么上的这三个有什么不同呢?看下面这段就可知道了:
/* GPIO bank summary:
*
* BankGPIO端口GPIOs数目Style类型控制位数目SlpCon端口A 睡眠模式配置寄存ExtInt Group外部中断
* A8 4BitYes1
* B7 4BitYes1
* C8 4BitYes2
* D5 4BitYes3
* E5 4BitYesNone
* F16 2BitYes4 [1]
* G7 4BitYes5
* H10 4Bit[2]Yes6
* I16 2BitYesNone
* J12 2BitYesNone
* K16 4Bit[2]NoNone
* L15 4Bit[2] NoNone
* M6 4BitNoIRQ_EINT
* N16 2BitNoIRQ_EINT
* O16 2BitYes7
* P15 2BitYes8
* Q9 2BitYes9
*
* [1] BANKF pins 14,15 do not form part of the external interrupt sources
* [2] BANK has two control registers, GPxCON0 and GPxCON1
*/
对照下图应该明白了上面的
下面这个图对应gpio_4bit
下面这两个图对应gpio_4bit2,4为控制,2个控制寄存器
下面这两个图对应gpio_2bit,两位控制
注:体会一下,s3c_gpio_chip和gpio_chip两个结构体的不同指出。
Linux下s3c6410的GPIO操作(2)的链接