/* 向某个gpio设置值,0或1。如果向gpio写1,则向set_data寄存器相应的位置1,如果写0, 则向clr_data寄存器相应的位置1.__gpio_mask函数在gpio.h中定义,定义如下, static inline u32 __gpio_mask(unsigned gpio) { return 1 << (gpio % 32); } 因为71个引脚由3个结构体控制,第一个控制前32个gpio,第二个控制次32个gpio, 最后一个控制剩余的7个gpio,故__gpio_mask函数的作用是找到在其相应控制结构体里的偏移数, 比如gpio34,那么其由第二个结构体控制,在这个机构体里的偏移是3(从0开始算,就是第二位)。 使用这个函数之前,必须确认该gpio设置成输出模式。 */ /* * Assuming the pin is muxed as a gpio output, set its output value. */ void __gpio_set(unsigned gpio,int value) { struct gpio_controller *__iomem g = gpio2controller(gpio);
// 设置gpio的值
__raw_writel(__gpio_mask(gpio), value ?&g->set_data :&g->clr_data); } EXPORT_SYMBOL(__gpio_set);
/* 通过读取in_data寄存器相应该gpio的位来读取gpio的值。 使用这个函数之前,必须确认该gpio设置成输入模式,否则获得到值不可预料。 */ /* * Read the pin's value (works even if it's set up as output); * returns zero/nonzero. * * Note that changes are synched to the GPIO clock, so reading values back * right after you've set them may give old values. */ int __gpio_get(unsigned gpio) { struct gpio_controller *__iomem g = gpio2controller(gpio);
/* * board setup code *MUST* set PINMUX0 and PINMUX1 as * needed, and enable the GPIO clock. */ int gpio_direction_input(unsigned gpio) { struct gpio_controller *__iomem g = gpio2controller(gpio); u32 temp; u32 mask;
/* * We expect irqs will normally be set up as input pins, but they can also be * used as output pins ... which is convenient for testing. * * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have * a good way to hook those up ... * * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also * serve as EDMA event triggers. */
/* * NOTE: for suspend/resume, probably best to make a sysdev (and class) * with its suspend/resume calls hooking into the results of the set_wake() * calls ... so if no gpios are wakeup events the clock can be disabled, * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 * can be set appropriately for GPIOV33 pins. */ /* 注册gpio中断例程到内核中,并初始化了一些寄存器。 该函数将会被board_evm.c(其浅析已经发表)中的evm_init()函数调用。具体调用过程如下: start_kernel()-->setup_arch()-->init_machine = mdesc->init_machine (init_machine是个全局函数指针变量,其指向的就是已经注册到机器描述符里evm_init()); 调用函数指针init_machine()的例程是customize_machine(),其定义为 arch_initcall(customize_machine),所以,接下来的调用过程是: start_kernel()-->do_basic_setup()-->do_initcalls()-->customize_machine()--> init_machine()(也就是evm_init())-->davinci_gpio_irq_setup。 从上可以看出经历了两个过程,才调用davinci_gpio_irq_setup例程来初始化gpio中断。 */ int __init davinci_gpio_irq_setup(void) { unsigned gpio, irq, bank, banks; struct clk *clk;
/* * TI DaVinci GPIO Support * * Copyright (c) 2006 David Brownell * Copyright (c) 2007, MontaVista Software, Inc.
#ifndef __DAVINCI_GPIO_H #define __DAVINCI_GPIO_H
/* * basic gpio routines * * board-specific init should be done by arch/.../.../board-XXX.c (maybe * initializing banks together) rather than boot loaders; kexec() won't * go through boot loaders. * * the gpio clock will be turned on when gpios are used, and you may also * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are * used as gpios, not with other peripherals. * * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe * for later updates, code should write GPIO(N) or: * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53) * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70) * * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc * for now, that's != GPIO(N) */ #define GPIO(X)(X)/* 0 <= X <= 70 */ #define GPIOV18(X)(X)/* 1.8V i/o; 0 <= X <= 53 */ #define GPIOV33(X)((X)+54)/* 3.3V i/o; 0 <= X <= 17 */
/* The __gpio_to_controller() and __gpio_mask() functions inline to constants * with constant parameters; or in outlined code they execute at runtime. * * You'd access the controller directly when reading or writing more than * one gpio value at a time, and to support wired logic where the value * being driven by the cpu need not match the value read back. * * These are NOT part of the cross-platform GPIO interface */ staticinlinestruct gpio_controller *__iomem __gpio_to_controller(unsigned gpio) { void*__iomem ptr;
/* The get/set/clear functions will inline when called with constant * parameters, for low-overhead bitbanging. Illegal constant parameters * cause link-time errors. * * Otherwise, calls with variable parameters use outlined functions. */ externint __error_inval_gpio(void);
/* Returns zero or nonzero; works for gpios configured as inputs OR * as outputs. * * NOTE: changes in reported values are synchronized to the GPIO clock. * This is most easily seen after calling gpio_set_value() and then immediatly * gpio_get_value(), where the gpio_get_value() would return the old value * until the GPIO clock ticks and the new value gets latched. */ externint gpio_get_value(unsigned gpio); externvoid gpio_set_value(unsigned gpio,int value);
/* powerup default direction is IN */ externint gpio_direction_input(unsigned gpio); externint gpio_direction_output(unsigned gpio,int value);