Gpio driver Analysis of Uboot--a A10 chip based on full-log

Source: Internet
Author: User
Uboot's Gpio is quite simple, it is a three-layer structure. Respectively: 1, the top layer interface layer, which only defines a common interface, is not responsible for implementation, implementation is based on specific chip to achieve. 2, the middle interface implementation layer, with the specific board of the GPIO to achieve the top layer interface 3, the underlying specific chip GPIO implementation layer.
Now specific analysis: Top layer interface Layer
int gpio_request (unsigned gpio, const char *label); Request Gpio Resource int gpio_free (unsigned gpio); Release the requested GPIO resource int gpio_direction_input (unsigned gpio); Set GPIO to input mode int gpio_direction_output (unsigned gpio, int value); Set Gpio to output mode int gpio_get_value (unsigned gpio); Gets the value of the Gpio int gpio_set_value (unsigned gpio, int value);//Set Gpio value Description: Unsigned gpio is a logical number, although it has a certain relationship with the actual physical Gpio address, But not the actual physical Gpio address.
Intermediate interface Implementation layer: with a specific chip gpio to implement its top interface int gpio_request (unsigned gpio, const char *label) {return 0;} int gpio_free (unsigned gpio  {return 0;} int gpio_direction_input (unsigned gpio) {Sunxi_gpio_set_cfgpin (Gpio, sunxi_gpio_input); Return Sunxi_gpio_input (GPIO);  } int gpio_direction_output (unsigned gpio, int value) {Sunxi_gpio_set_cfgpin (Gpio, sunxi_gpio_output); Return Sunxi_gpio_output (Gpio, value); } int Gpio_get_value (unsigned gpio) {return sunxi_gpio_input (GPIO);} int Gpio_set_value (unsigned gpio, int value) {RE Turn sunxi_gpio_output (gpio, value); }
The implementation layer of the underlying specific chip Gpio: At the time of implementation, it used a small trick, which is to put the physical register of Gpio into the structure, so that the physical address operation into the data structure operation. The implementation is as follows: The sunxi_pio_base is cast to the sunxi_gpio_reg * pointer.  #define Sunxi_pio_base 0x01c20800 struct Sunxi_gpio {u32 cfg[4];  U32 dat;  U32 drv[2]; U32 pull[2]; };  struct Sunxi_gpio_int {u32 cfg[3];  U32 ctl;  U32 STA; U32 Deb; };  struct Sunxi_gpio_reg {struct Sunxi_gpio gpio_bank[9];  U8 RES[0XBC]; struct Sunxi_gpio_int gpio_int; };
our idea of implementing a specific chip's GPIO operation is: use logical notation unsigned gpio to manipulate related registers by Sunxi_pio_base cast to Sunxi_gpio_reg * pointer
but the logical symbol unsigned GPIO to operate the relevant register by sunxi_pio_base the pointer to the SUNXI_GPIO_REG * pointer, it is necessary to solve a problem, that is, how to find the specified register in the numerous registers, and the specified relevant bits are found on the register. that is, gpio---->bank------offset in >bank
This mapping relationship is related to the specific chip. Only the A10 chip is discussed here.
First look at the definition of the logical symbol GPIO: #define SUNXI_GPIO_A_NR #define SUNXI_GPIO_B_NR #define SUNXI_GPIO_C_NR #define SUNXI_GPIO_D_NR 3 2 #define SUNXI_GPIO_E_NR #define SUNXI_GPIO_F_NR #define SUNXI_GPIO_G_NR #define SUNXI_GPIO_H_NR #define SUNX I_GPIO_I_NR #define SUNXI_GPIO_NEXT (__gpio) \   ((__gpio# #_START) + (__gpio# #_NR) + 0) enum Sunxi_gpio_number {&NB Sp Sunxi_gpio_a_start = 0,  sunxi_gpio_b_start = Sunxi_gpio_next (sunxi_gpio_a),  sunxi_gpio_c_start = SUNXI_ Gpio_next (sunxi_gpio_b),  sunxi_gpio_d_start = Sunxi_gpio_next (sunxi_gpio_c),  sunxi_gpio_e_start = SUNXI_ Gpio_next (sunxi_gpio_d),  sunxi_gpio_f_start = Sunxi_gpio_next (sunxi_gpio_e),  sunxi_gpio_g_start = SUNXI_ Gpio_next (sunxi_gpio_f),  sunxi_gpio_h_start = Sunxi_gpio_next (sunxi_gpio_g),  sunxi_gpio_i_start = SUNXI_ Gpio_next (Sunxi_gpio_h),}; #define SUNXI_GPA (_NR) (Sunxi_gpio_a_start + (_NR)) #define SUNXI_GPB (_NR) (Sunxi_gpio_b_start + (_NR)) #define SUNXI_GPC (_NR) (Sunxi_gpio_c_start + (_NR)) #define SUNXI_GPD (_NR) (Sunxi_gpio_d_start + (_NR)) #define SUNXI_GPE (_NR) (Sunxi_gpio_e_start + (_NR)) #d Efine SUNXI_GPF (_NR) (Sunxi_gpio_f_start + (_NR)) #define SUNXI_GPG (_NR) (Sunxi_gpio_g_start + (_NR)) #define SUNXI_GPH (_ NR) (Sunxi_gpio_h_start + (_NR)) #define SUNXI_GPI (_NR) (Sunxi_gpio_i_start + (_NR))

From these definitions can be concluded: A to I these nine large set of Gpio is starting from 0, each 32-bit mark, (of course, basically each set of Gpio number is not complete, but in order to define the size of each group is 32), that is, the index of the X group of the nth Gpio is x*32+y
The logical index GPIO is cast as a pointer to the SUNXI_GPIO_REG * pointer by sunxi_pio_base, and the mapping to the specific register is as follows:
#define GPIO_BANK (PIN) (PIN) >> 5 #define GPIO_NUM (PIN) (PIN) & 0x1f) So the gpio specified by the write logic Gpio can be this: static int sunxi_  Gpio_output (u32 pin, u32 val) {u32 dat;  U32 Bank = Gpio_bank (PIN);  U32 num = Gpio_num (PIN); struct Sunxi_gpio *pio = & ((struct Sunxi_gpio_reg *) sunxi_pio_base)->gpio_bank[bank];//get the first place of multiple registers of the GPIO by group number index Address dat = READL (&pio->dat);  Read its input and output register if (val) dat |= 0x1 << num;  else dat &= ~ (0x1 << num); Writel (DAT, &pio->dat);//write its input input register return 0; }
#define GPIO_CFG_INDEX (PIN) ((PIN) & 0x1f) >> 3) #define GPIO_CFG_OFFSET (PIN) (((PIN) & 0x1f) & 0x7) & lt;< 2)
So the configuration logic gpio specifies that the GPIO can be this: int sunxi_gpio_set_cfgpin (u32 pin, u32 val) {u32 cfg;  U32 Bank = Gpio_bank (PIN); U32 index = Gpio_cfg_index (PIN); The subscript index for the configuration register u32 offset = Gpio_cfg_offset (PIN); Offset in config register struct Sunxi_gpio *pio = & ((struct Sunxi_gpio_reg *) sunxi_pio_base)->gpio_bank[bank]; Get the first address of multiple registers of the GPIO by the group number index CFG = READL (&pio->cfg[0] + index);  &pio->cfg[0] for the first address of multiple configuration registers for the group, the address of its configuration register is obtained through the index index CFG &= ~ (0xf << offset); CFG |= Val << offset; These two behaviors set the value of the configuration register Writel (CFG, &pio->cfg[0] + index); Writes the specified configuration register to return 0; #define GPIO_PULL_INDEX (PIN) ((PIN) & 0x1f) >> 4) #define GPIO_PULL_OFFSET (PIN) (((PIN) & 0x1f) & 0x f) << 1)
Pull settings and configuration registers, there is no more explanation.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.