When writing the key driver, want to know how the kernel manages the GPIO, so began to trace the code, the middle of a few detours, is now recorded here.
Before I trace the code, I guess: first, this part of the code should be executed in the system set up stage, and second, the Gpio code should be in machine or platform or vendor related directories. It turns out that the 1th is correct, and the 2nd is fundamentally wrong, because the kernel relies on the abstraction of the Gpio to manage it, and this layer of abstraction gives specific machines the interface they need to implement, which is similar to other device-driven frameworks, and of course, Gpio is a device. ... ... Therefore, most of the code that manages Gpio is located in the drivers/gpio/directory.
OK, start the code, so where is the entry function for the s5pv210 Soc,gpio subsystem? In drivers/gpio/gpio-s5pv210.c, the implementation of the entry function is as follows:
The entry function does not have a few lines of code, but all of the following is going to start with it, so come on at 1.1, here's a list of what to describe:
1. The content of struct s3c_gpio_chip, as well as the important array s5pv210_gpio_4bit;
2. Member config and base in the above structure;
3. Analysis of Samsung_gpiolib_add_4bit_chips (), this part is relatively long.
The first part, the introduction of struct s3c_gpio_chip and the important array s5pv210_gpio_4bit
From an object-oriented point of view, S3c_gpio_chip is a subclass of Gpio_chip, but new properties and operations are added. Although its name is chip, a s3c_gpio_chip describes a Gpio bank, such as GPA0, GPA1, GPB, and so on, which is clearly reflected in the array s5pv210_gpio_4bit to be introduced.
The base member represents the starting virtual address of the current bank's control register, note that it is a virtual address.
The type of the config member is struct s3c_gpio_cfg, and the specific structure is:
1 structs3c_gpio_cfg {2UnsignedintCfg_eint;3 4s3c_gpio_pull_t (*get_pull) (structS3c_gpio_chip *chip, unsigned offs);5 int(*set_pull) (structS3c_gpio_chip *chip, unsigned offs,6 s3c_gpio_pull_t pull);7 8Unsigned (*get_config) (structS3c_gpio_chip *chip, unsigned offs);9 int(*set_config) (structS3c_gpio_chip *chip, unsigned offs,Ten unsigned config); One};
A visible config member is used to control and view the state of the pull-up resistor for a pin of the current bank, and to set and view the Multiplexing function on a pin as a new member of the subclass struct S3c_gpio_cfg. It is stated that the differences between these two functions on different machine and GPIO IP can not be ignored.
One of the most important members of Struct S3C_GPIO_CFG is its parent struct gpio_chip, which has a lot of content, but the members ' names basically understand the meaning:
1 structGpio_chip {2 Const Char*label;3 structDevice *Dev;4 structModule *owner;5 6 int(*request) (structGpio_chip *Chip,7 unsigned offset);8 void(* Free)(structGpio_chip *Chip,9 unsigned offset);Ten One int(*direction_input) (structGpio_chip *Chip, A unsigned offset); - int(*Get)(structGpio_chip *Chip, - unsigned offset); the int(*direction_output) (structGpio_chip *Chip, -Unsigned offset,intvalue); - int(*set_debounce) (structGpio_chip *Chip, - unsigned offset, unsigned debounce); + - void(*Set)(structGpio_chip *Chip, +Unsigned offset,intvalue); A at int(*TO_IRQ) (structGpio_chip *Chip, - unsigned offset); - - void(*dbg_show) (structSeq_file *S, - structGpio_chip *chip); - int Base; in U16 Ngpio; - Const Char*Const*names; toUnsigned can_sleep:1; +Unsigned exported:1; - the #ifDefined (Config_of_gpio) * /* $ * If config_of is enabled and then all GPIO controllers described in thePanax Notoginseng * Device tree automatically may has an of translation - */ the structDevice_node *Of_node; + intOf_gpio_n_cells; A int(*of_xlate) (structGpio_chip *GC,structDevice_node *NP, the Const void*gpio_spec, U32 *flags); + #endif -};
The function pointers in this struct, such as request free, are related to the implementation of the GPIO request, free, direction_input, direction_output, and other functions.
Then look at the array s5pv210_gpio_4bit, first of all, this name contains 4bit, meaning that each bank's Gpio control register, each 4bit control a gpio pin. This array is very long and we only take a look at the individual elements:
1 Static structS3c_gpio_chip s5pv210_gpio_4bit[] = {2 {3. Chip = {4.Base= S5pv210_gpa0 (0),5. Ngpio =S5pv210_gpio_a0_nr,6. Label ="GPA0",7 },8 }, {9. Chip = {Ten.Base= S5PV210_GPA1 (0), One. Ngpio =S5pv210_gpio_a1_nr, A. Label ="GPA1", - }, - }, { the. Chip = { -.Base= S5PV210_GPB (0), -. Ngpio =S5pv210_gpio_b_nr, -. Label ="GPB", + }, - }, + ... .... A { at.Base= (S5p_va_gpio +0xc40), -. config = &Gpio_cfg_noint, -. Irq_base = Irq_eint ( -), -. Chip = { -.Base= S5PV210_GPH2 (0), -. Ngpio =S5pv210_gpio_h2_nr, in. Label ="GPH2", -. TO_IRQ =Samsung_gpiolib_to_irq, to }, + }, { -.Base= (S5p_va_gpio +0XC60), the. config = &Gpio_cfg_noint, *. Irq_base = Irq_eint ( -), $. Chip = {Panax Notoginseng.Base= S5pv210_gph3 (0), -. Ngpio =S5pv210_gpio_h3_nr, the. Label ="GPH3", +. TO_IRQ =Samsung_gpiolib_to_irq, A }, the }, +};
This array describes some of the Gpio on the s5pv210, but compared to the data sheet, some of the Gpio does not appear here, but it is enough to say that this array describes the most available gpio in the system and initializes some information, For example, the current bank's first pin number, the number of all pins in the bank, and so on, these are macro definitions, the specific need to see mach-s5pv210 related header files, because of the macro involved too much, and no difficulty, here is not recorded.
In the second part, the config member and the base member of the struct s3c_gpio_chip are initialized.
This part of the processing in the S5pv210_gpiolib_init function, you can see that many elements of the S5pv210_gpio_4bit Config member is not initialized, that is, NULL, then you need to assign it to Gpio_cfg, This variable is in the current file and is defined as follows:
1 Static struct s3c_gpio_cfg gpio_cfg = {2 . Set_config = s3c_gpio_setcfg_s3c64xx_4bit ,3 . Set_pull = s3c_gpio_setpull_updown,4 . Get_pull = S3c_gpio_getpull_updown, 5 };
Let's take a look at these three functions, and the names should be able to know their functions.
#ifdef config_s3c_gpio_cfg_s3c64xxintS3c_gpio_setcfg_s3c64xx_4bit (structS3c_gpio_chip *chip, unsignedintOff, unsignedintCFG) { void__iomem *reg = chip->Base; unsignedintShift = (off &7) *4; U32 con; if(Off <8&& Chip->chip.ngpio >8) Reg-=4; if(s3c_gpio_is_cfg_special (CFG)) {cfg&=0xf; CFG<<=shift; } con=__raw_readl (REG); Con&= ~ (0xf<<shift); Con|=CFG; __raw_writel (Con, reg); return 0;}
The code logic is simple, gets the virtual address of the current bank's control register, calculates the starting bit in the control register based on offset, and then writes the CFG value to be set to the control register to complete the work. But here is a macro config_s3c_gpio_cfg_s3c64xx, see the relevant kconfig to know, once the s5p related platform is selected, then S3C_GPIO_CFG_S3C64XX this macro will definitely be defined.
S5PV210-based GPIO module code tracking and analysis in LInux-3.0.8