All GPIOs of Exynos4412 have fixed addresses. To facilitate the operation of these GPIOs, the Linux kernel
Some GPIO macros are defined in gpio-exynos4.h, for example:
#define EXYNOS4_GPA0(_nr) (EXYNOS4_GPIO_A0_START + (_nr))
#define EXYNOS4_GPA1(_nr) (EXYNOS4_GPIO_A1_START + (_nr))
#define EXYNOS4_GPB(_nr) (EXYNOS4_GPIO_B_START + (_nr))
.....................................
#define EXYNOS4_GPY5(_nr) (EXYNOS4_GPIO_Y5_START + (_nr))
#define EXYNOS4_GPY6(_nr) (EXYNOS4_GPIO_Y6_START + (_nr))
#define EXYNOS4_GPZ(_nr) (EXYNOS4_GPIO_Z_START + (_nr))
These macros encapsulate the address of each GPIO. Its advantage is that it is convenient for us to use and
Based on the name of the macro, you can intuitively know which GPIO is being operated.
The GPIO driver in the Linux kernel is in the driver/gpio/gpio-exynos4.c file.
The GPIO driver initialization entry function in this file is exynos4_gpiolib_init, because this file is the same as
4210 GPIO is also supported, so some general GPIOs are initialized first (both 4412 and 4210
Some GPIO), the code is as follows:
chip = exynos4_gpio_common_4bit;
nr_chips = ARRAY_SIZE(exynos4_gpio_common_4bit);
for (i = 0; i < nr_chips; i++, chip++) {
if (chip->config == NULL)
chip->config = &gpio_cfg;
if (chip->base == NULL)
pr_err("No allocation of base address for [common gpio]");
}
samsung_gpiolib_add_4bit_chips(exynos4_gpio_common_4bit,
nr_chips);
The variable exynos4_gpio_common_4bit is an array that defines some common GPIOs, nr_chips
It is the number of primes in the exynos4_gpio_common_4bit array.
First, use a for loop to iterate over all pixels of exynos4_gpio_common_4bit, and for each pixel
config structure assignment:
if (chip->config == NULL)
chip->config = &gpio_cfg;
gpio_cfg is a structure of type s3c_gpio_cfg, which is defined as follows:
struct s3c_gpio_cfg {
unsigned int cfg_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);
};
From the above code we can see that this structure mainly contains some function pointers, get_pull is
Get the pull-up status of GPIO. set_pull is used to set GPIO pull-up or pull-down. set_config is used to set
Set the GPIO working mode, such as output/input/other functions. Let's take a look at gpio_cfg
The definition of variables is as follows:
static struct s3c_gpio_cfg gpio_cfg = {
.set_config = s3c_gpio_setcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_exynos4,
.get_pull = s3c_gpio_getpull_exynos4,
};
From the above code, we can see that the three function pointers of the gpio_cfg structure are assigned values.
The function definition is implemented in gpio-config.c, which is in the kernel source code.
In the arch/arm/plat-samsung directory, the function of these three functions is to configure the
Set the corresponding register of GPIO to realize the operation of GPIO.
Then we go back to gpio-exynos4.c and look at the following code to complete
After assigning the config structure of each element in exynos4_gpio_common_4bit, the function will be called next
samsung_gpiolib_add_4bit_chips(exynos4_gpio_common_4bit, nr_chips)
Register the GPIO structure to the system. The code is as follows:
void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
int nr_chips)
{
for (; nr_chips > 0; nr_chips--, chip++) {
samsung_gpiolib_add_4bit(chip);
s3c_gpiolib_add(chip);
}
}
The above code mainly consists of two functions: samsung_gpiolib_add_4bit(chip) and
s3c_gpiolib_add(chip), first let's look at the samsung_gpiolib_add_4bit(chip) function
Number of realizations:
void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = samsung_gpiolib_4bit_input;
chip->chip.direction_output = samsung_gpiolib_4bit_output;
chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
}
This function also assigns a value to a function pointer. direction_input sets GPIO to input mode.
direction_output sets GPIO as output.
The main function of the s3c_gpiolib_add(chip) function is to assign values to some function pointers, and then
The parameters of the corresponding GPIO are saved in the gpio_desc structure. gpio_desc is a structure in the kernel.
A global variable defined to save the information of each GPIO. At this point, the GPIO driver initialization is complete.
The other main function is to assign values to the function pointers in each GPIO structure.
Finally, save each GPIO structure information into the global variable gpio_desc.
Some common GPIO driver initialization has been completed above. Let's go back to gpio-exynos4.c.
The following is to initialize the CPU-specific GPIO according to the CPU model. The code is as follows:
/* Only 4210 GPIO part */
if (soc_is_exynos4210()) {
chip = exynos4210_gpio_4bit;
nr_chips = ARRAY_SIZE(exynos4210_gpio_4bit);
for (i = 0; i < nr_chips; i++, chip++) {
if (chip->config == NULL)
chip->config = &gpio_cfg;
if (chip->base == NULL)
pr_err("No allocation of base address [4210 gpio]");
}
samsung_gpiolib_add_4bit_chips(exynos4210_gpio_4bit,
nr_chips);
} else {
/* Only 4212/4412 GPIO part */
chip = exynos4212_gpio_4bit;
nr_chips = ARRAY_SIZE(exynos4212_gpio_4bit);
for (i = 0; i < nr_chips; i++, chip++) {
if (chip->config == NULL)
chip->config = &gpio_cfg;
if (chip->base == NULL)
pr_err("No allocation of base address [4212 gpio]");
}
samsung_gpiolib_add_4bit_chips(exynos4212_gpio_4bit,
nr_chips);
}
By looking at the above code, the initialization process is the same as the principle of initializing the general GPIO introduced earlier.
We will not go into detail here. After all GPIOs are initialized, other driver modules in the kernel
We can easily use the GPIO we registered in gpio_desc. The kernel provides several global
Functions to operate these GPIOs:
int gpio_request(unsigned gpio, const char *label)
void gpio_free(unsigned gpio)
int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
int gpio_direction_input(unsigned gpio)
int gpio_direction_output(unsigned gpio, int value)
The gpio_request function is used to request GPIO operations. According to the parameter gpio passed in, it will go to the global variable
Find the corresponding GPIO structure in gpio_desc and check whether the flag bit of desc is set
FLAG_REQUESTED, if set, it means that this GPIO is being used elsewhere, and the program returns -EBUSY
Error, if not set, set flags to FLAG_REQUESTED.
The gpio_free function is used to release the GPIO operation. According to the parameters passed in, the gpio_desc global variable
Find the corresponding GPIO structure and clear the FLAG_REQUESTED bit of the flag variable in desc.
The s3c_gpio_setpull function sets the pull-up or pull-down of the GPIO. The value range of the variable pull is as follows:
Define:
#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00)
#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01)
#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02)
S3C_GPIO_PULL_NONE is floating
S3C_GPIO_PULL_DOWN is pull-down
S3C_GPIO_PULL_UP is pull-up
The s3c_gpio_cfgpin function sets the GPIO function: input/output/other functions. The second parameter
The value range of config is as follows:
#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0))
#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))
S3C_GPIO_INPUT is input mode, S3C_GPIO_OUTPUT is output mode, S3C_GPIO_SFN(x)
It is other modes, such as interrupt mode, etc.
The gpio_direction_input function sets the GPIO to be input.
gpio_direction_output sets the GPIO output. The second parameter value can be 0 or 1. 0 represents
Output low level, 1 represents output high level.
Let's look at a few examples of GPIO operations:
if (gpio_request(EXYNOS4_GPX3(3), "MPU6050 INT"))
printk(KERN_WARNING "MPU6050 INT(GPX3.3) Port request error!!!n");
else{
s3c_gpio_setpull(EXYNOS4_GPX3(3), S3C_GPIO_PULL_NONE);
s3c_gpio_cfgpin(EXYNOS4_GPX3(3), S3C_GPIO_SFN(0));
gpio_direction_input(EXYNOS4_GPX3(3));
gpio_free(EXYNOS4_GPX3(3));
}
The above code sets the GPIO pin GPX3_3 to input mode and leaves it floating.
err = gpio_request_one(EXYNOS4_GPX0(0), GPIOF_IN, "mcp251x_INT");
if (err) {
printk(KERN_ERR "failed to request mcp251x_INTn");
return -1;
}
s3c_gpio_cfgpin(EXYNOS4_GPX0(0), S3C_GPIO_SFN(0xf));
s3c_gpio_setpull(EXYNOS4_GPX0(0), S3C_GPIO_PULL_NONE);
gpio_free(EXYNOS4_GPX0(0));
The above code sets the GPIO pin GPX0_0 to interrupt mode.
if(gpio_request(EXYNOS4_GPK1(0), "GPK1_0"))
{
printk(KERN_ERR "failed to request GPK1_0 for "
"USI controln");
return err;
}
gpio_direction_output(EXYNOS4_GPK1(0), 1);
s3c_gpio_cfgpin(EXYNOS4_GPK1(0), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPK1(0));
The above code sets the GPIO pin GPK1_0 to output mode and outputs a high level.
This is the end of the introduction to the GPIO driver of iTOP-4412. If you are interested, you can go to the kernel for details.
Take a look at the detailed implementation of the entire driver.
Previous article:Xunwei iTOP-4412 core board voltage adjustment
Next article:Exynos4412 Uboot usage and flashing
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- C51 uses macro definition to replace printf function
- Understanding the CAN bus from the bottom up
- [STM32WB55 Review] +USB Dongle Bricked
- STM32F429 USB_OTG_FS (PA11, PA12) read USB disk problem
- PoE and PoE+, an article to understand Power over Ethernet
- How to control trace impedance of PCB for signal integrity?
- Disassembling the USB wireless network card, the circuit scheme is very classic
- Low-cost MCU options
- 5G millimeter wave antenna
- Design of Switching Power Supply Using MSP430 Microcontroller