From df666b9c510fd27fd3b1afd9ddfa1eaa62ce12b3 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 22 Feb 2006 21:23:35 +0000 Subject: [PATCH] [ARM] 3325/2: GPIO function to control multi-drive (open collector) capability Patch from Andrew Victor This patch adds the at91_set_multi_drive() function to enable/disable the multi-drive (open collector) pin capability on the AT91RM9200 processor. This is necessary to fix the UDC (USB Gadget) driver for the AT91RM9200 board as it will not allow the board reset line to be pulled low if the pullup is not driven as an open collector output as the boards are wired to the USB connector on both the DK/EK. This version of the patch updates it to 2.6.16-rc4. Orignal patch by Jeff Warren. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/devices.c | 4 +++- arch/arm/mach-at91rm9200/gpio.c | 17 +++++++++++++++++ include/asm-arm/arch-at91rm9200/gpio.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index 8df3e52456..57eedd5bea 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c @@ -100,8 +100,10 @@ void __init at91_add_device_udc(struct at91_udc_data *data) at91_set_gpio_input(data->vbus_pin, 0); at91_set_deglitch(data->vbus_pin, 1); } - if (data->pullup_pin) + if (data->pullup_pin) { at91_set_gpio_output(data->pullup_pin, 0); + at91_set_multi_drive(data->pullup_pin, 1); + } udc_data = *data; platform_device_register(&at91rm9200_udc_device); diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 2fd2ef583e..a9f718bf8b 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -159,6 +159,23 @@ int __init_or_module at91_set_deglitch(unsigned pin, int is_on) } EXPORT_SYMBOL(at91_set_deglitch); +/* + * enable/disable the multi-driver; This is only valid for output and + * allows the output pin to run as an open collector output. + */ +int __init_or_module at91_set_multi_drive(unsigned pin, int is_on) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR)); + return 0; +} +EXPORT_SYMBOL(at91_set_multi_drive); + /*--------------------------------------------------------------------------*/ diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h index 0f0a61e2f1..6176ab2dc4 100644 --- a/include/asm-arm/arch-at91rm9200/gpio.h +++ b/include/asm-arm/arch-at91rm9200/gpio.h @@ -183,6 +183,7 @@ extern int at91_set_B_periph(unsigned pin, int use_pullup); extern int at91_set_gpio_input(unsigned pin, int use_pullup); extern int at91_set_gpio_output(unsigned pin, int value); extern int at91_set_deglitch(unsigned pin, int is_on); +extern int at91_set_multi_drive(unsigned pin, int is_on); /* callable at any time */ extern int at91_set_gpio_value(unsigned pin, int value); -- 2.39.5