Gpio Linux implementation model

Source: Internet
Author: User

Gpio is closely related to the hardware system. Linux provides a model for drivers to process gpio in a unified manner. Each card has its own gpio_chip control module: request, free, input, output, get, set, IRQ...

Then, register the control module to the kernel, and then change the global gpio array: gpio_desc [].

When a user requests gpio, it will find it in this array and call the corresponding gpio_chip processing function of this gpio.

Gpio implementation is a set of available gpio_chip. The driver transmits the global serial numbers of the corresponding gpio to request, dataout, dataIn, and free. Then, the specific implementation in gpio_chip is called.

Register read/write function: _ raw_writel () _ raw_writeb () _ raw_readl () _ raw_readb ()

Gpio is a set of controllable feet controlled by multiple registers at the same time. By setting the corresponding registers, you can set the corresponding statuses and functions of the gpio port.
Data status, input/output direction, resetting, and interruption (triggered by the edge). Generally, they are in a group (bank.

****************** **********************//
Registration Method:
1: struct gpio_chip: represents a gpio controller. All gpio sources are abstracted through this structure, so that other modules on the Board can use the same interface to call these gpio.
2: struct gpio_desc: indicates a gpio port, including the corresponding gpio_chip.
3: arch_nr_gpios: number of board-related gpio ports, that is, the global gpio array: static struct gpio_desc [arch_nr_gpios];
4: When registering gpio_chip, modify the gpio_desc field (chip, flags) in the global gpio Array Based on the chip data ).

*******************//
First, the gpio module in twl4030: When the twl4030 driver is registered, the i2c_client and platform_device corresponding to the gpio are generated in probe.
Twl4030: When the gpio driver is loaded (matching platform_device), the corresponding settings and gpio settings are performed first.
Then set the structure: gpio_chip: twl_gpiochip: gpio_twl4030_pulls, pio_twl4030_debounce,
Registered: ret = gpiochip_add (& twl_gpiochip); // Add it to the global gpio_desc array. Set the gpio fields corresponding to this gpio_chip in the global gpio_desc.

Setup: Status = pdata-> setup (& pdev-> Dev, pdata-> gpio_base, twl4030_gpio_max );
Setup (...) = "twl4030_mmc_init (MMC); // after adding gpio, test MMC and register it. Register MMC devices.

 

****************** //
Static int _ init _ omap_gpio_init (void)
Gpio_bank_count: Number of gpio groups.
The corresponding Interrupt Processing routine is also registered here:
Bank master interrupt handling: gpio_irq_handler
The sub-gpio in the bank is set to handle_simple_irq.

// Register the function, that is, the gpio field corresponding to the global gpio array of the chip device.
Int gpiochip_add (struct gpio_chip * chip)
{
For (ID = base; id <base + chip-> ngpio; Id ++ ){
Gpio_desc [ID]. Chip = chip; // set the chip of the corresponding member in the global gpio_desc as the registered chip.
Gpio_desc [ID]. Flags =! Chip-> direction_input? (1 <flag_is_out): 0; // and gpio direction.

}

 

//
"Common call method :"
Static int _ init wl1_x_vie_leakage_fix (void)
{
Int ret = 0;

Ret = gpio_request (wl1_x_bten_gpio, "wl1_x_bten ");
If (Ret <0 ){
Printk (kern_err "wlrjx_bten gpio _ % d request fail ",
Wl1_x_bten_gpio );
Goto fail;
}

Gpio_direction_output (wl1_x_bten_gpio, 1 );
Mdelay (10 );
Gpio_direction_output (wl1_x_bten_gpio, 0 );
Udelay (64 );

Gpio_free (wl1_x_bten_gpio );
Fail:
Return ret;
}

//********************//
I. Physical starting address of gpio: for Embedded programmers who want to control gpio, the physical address of gpio must be clarified. The basic physical address of gpio in stb02500soc is: 0x4006 0000. The space length is: 0x44. (Gpio_base = 0x4006 0000 Len = 0x44)

Ii. gpio registers:
Gpio has nine registers:
1. GPO: the GPO (32bit) register is used to set or clear the corresponding gpio pin value (high or low ). For specific control, you must first read the value of the gpio pin, and then use "or", "and" to set and clear the logic. Obviously, this operation is non-atomic, in a multi-task system, it is possible to have an accident. Programmers need to implement corresponding atomic operations on the software, which should be lagging behind in the I/O operations of the arm system ).
2. gptc: gptc (32bit) registers are used to set whether the corresponding gpio pin is output or input (this is better understood) the Program sets the corresponding bit to 1, and the corresponding gpio pin is the output. Otherwise, it is the input. (in this case, we also need to declare that the register should take effect and set the GPTS register ).
3. gpos: gpos (64bit) registers are used to control whether the corresponding pins of gpio are driven by GPO or alt_output_x (, 3) drives (for a simple understanding, ).
4. GPTS: The register function of GPTS (64bit) is hard to tell clearly. To put it simply, if you need to use GPO to drive gpio registers, you need to set the corresponding 2bit to 00 and select gptc as the output enabling Controller so that the gptc register can take effect.
5. the gpod: gpod (32bit) Register is relatively simple. If the corresponding position is set to 1, the corresponding gpio pin is in the open-circuit mode, which can adapt to the multi-voltage system, single-Input System with multiple outputs.
6. GPI: GPI (32bit) is the value of the corresponding gpio pin (high or low ).
7. gpis1: I have not studied it yet.
8. gpis2: I have not studied it yet.
9. gpis3: I have not studied it yet.
Note: The gpio0 corresponds to the bit0 of GPO, And the bit0 of GPO is actually the bit31 Of the 32-bit gpod (based on the arm system ).

III:
For operating systems that do not support virtual memory and do not use the operating system to operate gpio to directly read and write the corresponding gpio register, but in operating systems such as Linux, you must write a driver for operating gpio, or use some workarounds to operate gpio.
Currently, I know two methods to operate gpio in Linux:
1. to write a driver, you must be familiar with the compiling methods and skills of the driver in Linux. In the driver, you can use the ioremap function to obtain the gpio physical base address pointer, use the ioctl command to read and write the gpio register and send the result back to the application layer.
2. Use the MMAP function at the application layer to obtain the virtual address pointer corresponding to the gpio physical base address at the application layer, and then use this pointer to read and write gpio registers.

Summary:
Although there are many gpio registers, it is very easy to use. The key is to understand the functions of each gpio pin and the features of each register. In fact, if you only want to implement simple I/O Input and Output Control (most single-chip microcomputer developers usually use it), you only need to be familiar with GPO, Gpi, and gptc.

Gpio is a general I/O protocol. During reading and writing, you need to set specific registers. In the standard description, gpio 0-12 is generally used, gpio 38-43 and so on, gpio and General registers read and write is very different, so it is two numbers control a state.

The General read/write sequence of gpio is:

1. First, set the gpio range to be operated;

2. Before reading/writing, set the gpio Selection Register to 1/0;

3. read/write registers (base address + offset ).

Static struct gpio_desc [arch_nr_gpios]; // global gpio_chip storage array

Static struct gpio_chip twl_gpiochip = {
. Label = "twl4030 ",
. Owner = this_module,
. Request = twl_request,
. Free = twl_free,
. Direction_input = twl_direction_in,
. Get = twl_get,
. Direction_output = twl_direction_out,
. Set = twl_set,
. To_irq = twl_to_irq,
. Can_sleep = 1,
};

/* Gpio_lock prevents conflicts during gpio_desc [] Table updates.
* While any gpio is requested, its gpio_chip is not removable;
* Each gpio's "requested" flag serves as a lock and refcount.
*/
Struct gpio_desc {
Struct gpio_chip * chip;
Unsigned long flags;
/* Flag symbols are bit numbers */
# Define flag_requested 0
# Define flag_is_out 1
# Define flag_reserved 2
# Define flag_export 3/* protected by sysfs_lock */
# Define flag_sysfs 4/* exported via/sys/class/gpio/control */

# Ifdef config_debug_fs
Const char * label;
# Endif
};

/**
* Struct gpio_chip-Abstract A gpio Controller
* @ 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
* Enabling module power and clock; may sleep
* @ Free: Optional hook for Chip-specific deactivation, such
* 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 co de
* Will be used when this is omitted, but custom co de 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 varous sources of gpios so
* They can all be accessed through a common programing interface.
* Example sources wocould be SOC controllers, FPGAs, multifunction
* Chips, dedicated gpio expanders, and so on.
*
* Each chip controls a number of signals, identified in method CILS
* By "offset" values in the range 0 .. (@ ngpio-1). When those signals
* Are referenced through cballs 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 );
Int base;
B2ngpio;
Unsigned can_sleep: 1;
Unsigned exported: 1;
};

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/cuiyan0214/archive/2010/05/04/5556262.aspx

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.