How does the GPIO of the iTOP-4412 development board work?

Publisher:画意人生Latest update time:2021-12-03 Source: eefocusKeywords:iTOP-4412 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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. 


Keywords:iTOP-4412 Reference address:How does the GPIO of the iTOP-4412 development board work?

Previous article:Xunwei iTOP-4412 core board voltage adjustment
Next article:Exynos4412 Uboot usage and flashing

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号