问题
im working with a AT91SAM9G25 board which has 4 PIO controller managing up to 32 programmable I/O lines. Each pin is configurable as either a general-purpose I/O line only or as an I/O line multiplexed up to two peripheral I/Os. So, for example, according with the documentation (SAM9G25, page 14), signal PC0 can be multiplexed such a general purpose I/O line or as the ISI_D0 line of the VIDEO_ATMEL_ISI (ISI of Image Sensor Interface).
╔════════════╦════════════╦════════════╦════════════╦════════════╗
║ Primary ║ Alternates ║ PeripA ║ PeripB ║ PeripC ║
╠════════════╬════════════╬════════════╬════════════╬════════════╣
║ Signal/Dir ║ Signal/Dir ║ Signal/Dir ║ Signal/Dir ║ Signal/Dir ║
║ --------- ║ --------- ║ --------- ║ --------- ║ --------- ║
║ PC0 / I/O ║ ║ ║ ISI_D0 / I ║ ║
╚════════════╩════════════╩════════════╩════════════╩════════════╝
The reset state of all GPIO lines is with direction IN and Pullup enabled. when i use GPIOLIB via sysfs i read a "1" value as INPUT in several GPIOs due to pullup. Is this a normal safe state of GPIO (INPUT with Pullup resistor) at reset in several boards when they can be multiplexed with other Peripherals?. I dont see how i can disable the pullup via userspace with GPIOLIB. So for example, i see that when kernel is booting it checks if the Image Sensor Peripheral is enabled at kernel or as a module and if so it sets the PC0 to Peripheral B. This is in the kernel sources at /arch/arm/mach-at91/at91sam9x5_devices.c
#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
....
at91_set_B_periph(AT91_PIN_PC0, 0); /* ISI_D0 */
...
#endif
Then if i dont enable ISI support in kernel i can use the PC0 signal as GPIO line. This is the /sys/kernel/debug/gpio:
# cat /sys/kernel/debug/gpio
GPIOs 32-63, A:
GPIOs 64-95, B:
[atmel_usba_udc] GPIOB16: [gpio] set
[d1] GPIOB18: [gpio] clear
GPIOs 96-127, C:
GPIOs 128-159, D:
[ohci_vbus] GPIOD19: [gpio] clear
[ohci_vbus] GPIOD20: [gpio] clear
[d2] GPIOD21: [gpio] set
And this is /sys/kernel/debug/at91_gpio
# cat /sys/kernel/debug/at91_gpio
Pin PIOA PIOB PIOC PIOD
0: A A GPIO:1 A
1: A A GPIO:1 A
2: GPIO:1 A GPIO:1 A
3: GPIO:1 A GPIO:1 A
4: GPIO:1 A GPIO:1 GPIO:1
5: GPIO:1 A GPIO:1 GPIO:1
6: GPIO:1 A GPIO:1 A
7: B A GPIO:1 A
8: GPIO:1 GPIO:1 GPIO:1 A
9: A A GPIO:1 A
10: A A GPIO:1 A
11: A GPIO:1 GPIO:1 A
12: A GPIO:1 GPIO:1 A
13: A GPIO:1 GPIO:1 A
14: A GPIO:1 GPIO:1 GPIO:1
15: GPIO:1 GPIO:1 GPIO:1 A
16: GPIO:1 GPIO:1 GPIO:0 A
17: GPIO:1 GPIO:1 GPIO:1 A
18: GPIO:1 GPIO:1 GPIO:1 A
19: GPIO:1 A GPIO:1 GPIO:0
20: GPIO:1 A GPIO:0 GPIO:0
21: GPIO:1 A GPIO:0 GPIO:1
22: GPIO:1 A GPIO:1 A
23: GPIO:1 A GPIO:1 A
24: GPIO:1 A GPIO:1 A
25: GPIO:1 A GPIO:1 A
26: GPIO:1 A GPIO:1 A
27: GPIO:0 A GPIO:1 A
28: GPIO:1 A GPIO:0 A
29: GPIO:1 A GPIO:0 A
30: GPIO:1 A GPIO:1 A
31: GPIO:1 A GPIO:1 A
The above output show that PIOA0 is multiplexed to Peripheral A (TXD0 UART Line), and for example PIOC20 is cleared, but the documentation says that all GPIO lines at reset state are INPUTS with pullup and i dont find where kernel or u-boot disable the pullup of this GPIO (maybe GPIOs keep their state if none touch his registers?)
But he main question is, how can i clear the pullup register of the GPIO lines? I find in kernel sources that /arch/arm/mach-at91/at91sam9x5_devices.c uses this function implemented in linux-2.6.39/arch/arm/mach-at91/gpio.c .
/*
* enable/disable the pull-down.
* If pull-up already enabled while calling the function, we disable it.
*/
int __init_or_module at91_set_pulldown(unsigned pin, int is_on)
{
void __iomem *pio = pin_to_controller(pin);
unsigned mask = pin_to_mask(pin);
if (!pio || !cpu_has_pio3())
return -EINVAL;
/* Disable pull-up anyway */
__raw_writel(mask, pio + PIO_PUDR);
__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
return 0;
}
EXPORT_SYMBOL(at91_set_pulldown);
Header arch/arm/mach-at91/include/mach/gpio.h
#ifndef __ASSEMBLY__
/* setup setup routines, called from board init or driver probe() */
.....
extern int __init_or_module at91_set_pulldown(unsigned pin, int is_on);
.....
#endif /* __ASSEMBLY__ */
How can use this functions with my toolchain, or should i make a kernel module?
Thanks
PD: Sorry for any mistakes in my english, i know i need to improve it.
回答1:
Maybe you can just leave the pullup alone. I've used GPIO on OMAP SoCs, at lowest level there are similar pin mux options, but it wasn't necessary to worry about pullups. Usually whatever is driving it can sink enough current (this is EE/circuit viewpoint, don't worry if you are unfamiliar). Floating input could be random and troublesome; pulled up high should be OK.
I would not think you should need to make a kernel module. I'd suggest you experiment using existing user mode interfaces. Your kernel should already have low-level drivers hooked in to provide access through sysfs. Refer to sysfs, omap gpio. I don't think I've seen pullup options in sysfs. If you get something working and need to call it from C code, then you can look for APIs, or just use system().
回答2:
On newer kernels using device tree you can control it by recompiling the devicetree "blob" and do not need to change the kernel or write a kernel driver.
http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
But it would be really sweet if pinctrl had a user space interface like the gpio so the complete solution in controlling pin's was user space controlled.
来源:https://stackoverflow.com/questions/15411746/enable-pullup-gpio