Merge branch 'at91-fixes' of git://github.com/at91linux/linux-at91 into fixes

* 'at91-fixes' of git://github.com/at91linux/linux-at91:
  ARM: at91: dt: remove unit-address part for memory nodes
  ARM: at91: fix check of valid GPIO for SPI and USB
  USB: ehci-atmel: add needed of.h header file
  ARM: at91/NAND DT bindings: add comments
  ARM: at91/at91sam9x5.dtsi: fix NAND ale/cle in DT file
  USB: ohci-at91: trivial return code name change
  USB: ohci-at91: change maximum number of ports
  USB: ohci-at91: rework and fix initialization
  ARM: at91/dts: USB host vbus is active low
  ARM: at91/USB host: specify and handle properly vbus_pin_active_low
  USB: ohci-at91: fix vbus_pin_active_low handling
  ARM: at91/at91sam9x5: add clkdev entries for DMA controllers
This commit is contained in:
Olof Johansson 2012-04-05 10:43:06 -07:00
commit 8078342664
19 changed files with 137 additions and 104 deletions

View File

@ -27,13 +27,13 @@ nand0: nand@40000000,0 {
reg = <0x40000000 0x10000000 reg = <0x40000000 0x10000000
0xffffe800 0x200 0xffffe800 0x200
>; >;
atmel,nand-addr-offset = <21>; atmel,nand-addr-offset = <21>; /* ale */
atmel,nand-cmd-offset = <22>; atmel,nand-cmd-offset = <22>; /* cle */
nand-on-flash-bbt; nand-on-flash-bbt;
nand-ecc-mode = "soft"; nand-ecc-mode = "soft";
gpios = <&pioC 13 0 gpios = <&pioC 13 0 /* rdy */
&pioC 14 0 &pioC 14 0 /* nce */
0 0 /* cd */
>; >;
partition@0 { partition@0 {
... ...

View File

@ -35,7 +35,7 @@
}; };
}; };
memory@20000000 { memory {
reg = <0x20000000 0x08000000>; reg = <0x20000000 0x08000000>;
}; };

View File

@ -37,8 +37,8 @@
usb0: ohci@00600000 { usb0: ohci@00600000 {
status = "okay"; status = "okay";
num-ports = <2>; num-ports = <2>;
atmel,vbus-gpio = <&pioD 19 0 atmel,vbus-gpio = <&pioD 19 1
&pioD 20 0 &pioD 20 1
>; >;
}; };

View File

@ -36,7 +36,7 @@
}; };
}; };
memory@70000000 { memory {
reg = <0x70000000 0x10000000>; reg = <0x70000000 0x10000000>;
}; };

View File

@ -17,7 +17,7 @@
bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"; bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
}; };
memory@70000000 { memory {
reg = <0x70000000 0x4000000>; reg = <0x70000000 0x4000000>;
}; };
@ -73,8 +73,8 @@
usb0: ohci@00700000 { usb0: ohci@00700000 {
status = "okay"; status = "okay";
num-ports = <2>; num-ports = <2>;
atmel,vbus-gpio = <&pioD 1 0 atmel,vbus-gpio = <&pioD 1 1
&pioD 3 0>; &pioD 3 1>;
}; };
usb1: ehci@00800000 { usb1: ehci@00800000 {

View File

@ -34,7 +34,7 @@
}; };
}; };
memory@20000000 { memory {
reg = <0x20000000 0x10000000>; reg = <0x20000000 0x10000000>;
}; };
@ -201,8 +201,8 @@
>; >;
atmel,nand-addr-offset = <21>; atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>; atmel,nand-cmd-offset = <22>;
gpios = <&pioC 8 0 gpios = <&pioD 5 0
&pioC 14 0 &pioD 4 0
0 0
>; >;
status = "disabled"; status = "disabled";

View File

@ -8,7 +8,7 @@
*/ */
/ { / {
memory@20000000 { memory {
reg = <0x20000000 0x8000000>; reg = <0x20000000 0x8000000>;
}; };

View File

@ -16,7 +16,7 @@
bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs"; bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
}; };
memory@20000000 { memory {
reg = <0x20000000 0x4000000>; reg = <0x20000000 0x4000000>;
}; };

View File

@ -598,6 +598,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
else else
cs_pin = spi1_standard_cs[devices[i].chip_select]; cs_pin = spi1_standard_cs[devices[i].chip_select];
if (!gpio_is_valid(cs_pin))
continue;
if (devices[i].bus_num == 0) if (devices[i].bus_num == 0)
enable_spi0 = 1; enable_spi0 = 1;
else else

View File

@ -415,6 +415,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
else else
cs_pin = spi1_standard_cs[devices[i].chip_select]; cs_pin = spi1_standard_cs[devices[i].chip_select];
if (!gpio_is_valid(cs_pin))
continue;
if (devices[i].bus_num == 0) if (devices[i].bus_num == 0)
enable_spi0 = 1; enable_spi0 = 1;
else else

View File

@ -72,7 +72,8 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
/* Enable VBus control for UHP ports */ /* Enable VBus control for UHP ports */
for (i = 0; i < data->ports; i++) { for (i = 0; i < data->ports; i++) {
if (gpio_is_valid(data->vbus_pin[i])) if (gpio_is_valid(data->vbus_pin[i]))
at91_set_gpio_output(data->vbus_pin[i], 0); at91_set_gpio_output(data->vbus_pin[i],
data->vbus_pin_active_low[i]);
} }
/* Enable overcurrent notification */ /* Enable overcurrent notification */
@ -671,6 +672,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
else else
cs_pin = spi1_standard_cs[devices[i].chip_select]; cs_pin = spi1_standard_cs[devices[i].chip_select];
if (!gpio_is_valid(cs_pin))
continue;
if (devices[i].bus_num == 0) if (devices[i].bus_num == 0)
enable_spi0 = 1; enable_spi0 = 1;
else else

View File

@ -127,12 +127,13 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
/* Enable VBus control for UHP ports */ /* Enable VBus control for UHP ports */
for (i = 0; i < data->ports; i++) { for (i = 0; i < data->ports; i++) {
if (gpio_is_valid(data->vbus_pin[i])) if (gpio_is_valid(data->vbus_pin[i]))
at91_set_gpio_output(data->vbus_pin[i], 0); at91_set_gpio_output(data->vbus_pin[i],
data->vbus_pin_active_low[i]);
} }
/* Enable overcurrent notification */ /* Enable overcurrent notification */
for (i = 0; i < data->ports; i++) { for (i = 0; i < data->ports; i++) {
if (data->overcurrent_pin[i]) if (gpio_is_valid(data->overcurrent_pin[i]))
at91_set_gpio_input(data->overcurrent_pin[i], 1); at91_set_gpio_input(data->overcurrent_pin[i], 1);
} }
@ -188,7 +189,8 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
/* Enable VBus control for UHP ports */ /* Enable VBus control for UHP ports */
for (i = 0; i < data->ports; i++) { for (i = 0; i < data->ports; i++) {
if (gpio_is_valid(data->vbus_pin[i])) if (gpio_is_valid(data->vbus_pin[i]))
at91_set_gpio_output(data->vbus_pin[i], 0); at91_set_gpio_output(data->vbus_pin[i],
data->vbus_pin_active_low[i]);
} }
usbh_ehci_data = *data; usbh_ehci_data = *data;
@ -785,6 +787,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
else else
cs_pin = spi1_standard_cs[devices[i].chip_select]; cs_pin = spi1_standard_cs[devices[i].chip_select];
if (!gpio_is_valid(cs_pin))
continue;
if (devices[i].bus_num == 0) if (devices[i].bus_num == 0)
enable_spi0 = 1; enable_spi0 = 1;
else else

View File

@ -419,6 +419,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
else else
cs_pin = spi_standard_cs[devices[i].chip_select]; cs_pin = spi_standard_cs[devices[i].chip_select];
if (!gpio_is_valid(cs_pin))
continue;
/* enable chip-select pin */ /* enable chip-select pin */
at91_set_gpio_output(cs_pin, 1); at91_set_gpio_output(cs_pin, 1);

View File

@ -223,6 +223,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk), CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
CLKDEV_CON_ID("pioA", &pioAB_clk), CLKDEV_CON_ID("pioA", &pioAB_clk),
CLKDEV_CON_ID("pioB", &pioAB_clk), CLKDEV_CON_ID("pioB", &pioAB_clk),
CLKDEV_CON_ID("pioC", &pioCD_clk), CLKDEV_CON_ID("pioC", &pioCD_clk),

View File

@ -74,6 +74,7 @@ static void __init ek_init_early(void)
static struct at91_usbh_data __initdata ek_usbh_data = { static struct at91_usbh_data __initdata ek_usbh_data = {
.ports = 2, .ports = 2,
.vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 }, .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 },
.vbus_pin_active_low = {1, 1},
.overcurrent_pin= {-EINVAL, -EINVAL}, .overcurrent_pin= {-EINVAL, -EINVAL},
}; };

View File

@ -71,6 +71,7 @@ static void __init ek_init_early(void)
static struct at91_usbh_data __initdata ek_usbh_hs_data = { static struct at91_usbh_data __initdata ek_usbh_hs_data = {
.ports = 2, .ports = 2,
.vbus_pin = {AT91_PIN_PD1, AT91_PIN_PD3}, .vbus_pin = {AT91_PIN_PD1, AT91_PIN_PD3},
.vbus_pin_active_low = {1, 1},
.overcurrent_pin= {-EINVAL, -EINVAL}, .overcurrent_pin= {-EINVAL, -EINVAL},
}; };

View File

@ -86,14 +86,15 @@ extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *d
extern void __init at91_add_device_eth(struct macb_platform_data *data); extern void __init at91_add_device_eth(struct macb_platform_data *data);
/* USB Host */ /* USB Host */
#define AT91_MAX_USBH_PORTS 3
struct at91_usbh_data { struct at91_usbh_data {
u8 ports; /* number of ports on root hub */ int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
int vbus_pin[2]; /* port power-control pin */ int overcurrent_pin[AT91_MAX_USBH_PORTS];
u8 vbus_pin_active_low[2]; u8 ports; /* number of ports on root hub */
u8 overcurrent_supported; u8 overcurrent_supported;
int overcurrent_pin[2]; u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
u8 overcurrent_status[2]; u8 overcurrent_status[AT91_MAX_USBH_PORTS];
u8 overcurrent_changed[2]; u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
}; };
extern void __init at91_add_device_usbh(struct at91_usbh_data *data); extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data); extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);

View File

@ -13,6 +13,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
/* interface and function clocks */ /* interface and function clocks */

View File

@ -27,6 +27,10 @@
#error "CONFIG_ARCH_AT91 must be defined." #error "CONFIG_ARCH_AT91 must be defined."
#endif #endif
#define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS)
#define at91_for_each_port(index) \
for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
/* interface and function clocks; sometimes also an AHB clock */ /* interface and function clocks; sometimes also an AHB clock */
static struct clk *iclk, *fclk, *hclk; static struct clk *iclk, *fclk, *hclk;
static int clocked; static int clocked;
@ -240,26 +244,26 @@ ohci_at91_start (struct usb_hcd *hcd)
static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
{ {
if (port < 0 || port >= 2) if (!valid_port(port))
return; return;
if (!gpio_is_valid(pdata->vbus_pin[port])) if (!gpio_is_valid(pdata->vbus_pin[port]))
return; return;
gpio_set_value(pdata->vbus_pin[port], gpio_set_value(pdata->vbus_pin[port],
!pdata->vbus_pin_active_low[port] ^ enable); pdata->vbus_pin_active_low[port] ^ enable);
} }
static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
{ {
if (port < 0 || port >= 2) if (!valid_port(port))
return -EINVAL; return -EINVAL;
if (!gpio_is_valid(pdata->vbus_pin[port])) if (!gpio_is_valid(pdata->vbus_pin[port]))
return -EINVAL; return -EINVAL;
return gpio_get_value(pdata->vbus_pin[port]) ^ return gpio_get_value(pdata->vbus_pin[port]) ^
!pdata->vbus_pin_active_low[port]; pdata->vbus_pin_active_low[port];
} }
/* /*
@ -271,9 +275,9 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
int length = ohci_hub_status_data(hcd, buf); int length = ohci_hub_status_data(hcd, buf);
int port; int port;
for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { at91_for_each_port(port) {
if (pdata->overcurrent_changed[port]) { if (pdata->overcurrent_changed[port]) {
if (! length) if (!length)
length = 1; length = 1;
buf[0] |= 1 << (port + 1); buf[0] |= 1 << (port + 1);
} }
@ -297,11 +301,17 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
"ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
hcd, typeReq, wValue, wIndex, buf, wLength); hcd, typeReq, wValue, wIndex, buf, wLength);
wIndex--;
switch (typeReq) { switch (typeReq) {
case SetPortFeature: case SetPortFeature:
if (wValue == USB_PORT_FEAT_POWER) { if (wValue == USB_PORT_FEAT_POWER) {
dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
ohci_at91_usb_set_power(pdata, wIndex - 1, 1); if (valid_port(wIndex)) {
ohci_at91_usb_set_power(pdata, wIndex, 1);
ret = 0;
}
goto out; goto out;
} }
break; break;
@ -312,9 +322,9 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(hcd->self.controller, dev_dbg(hcd->self.controller,
"ClearPortFeature: C_OVER_CURRENT\n"); "ClearPortFeature: C_OVER_CURRENT\n");
if (wIndex == 1 || wIndex == 2) { if (valid_port(wIndex)) {
pdata->overcurrent_changed[wIndex-1] = 0; pdata->overcurrent_changed[wIndex] = 0;
pdata->overcurrent_status[wIndex-1] = 0; pdata->overcurrent_status[wIndex] = 0;
} }
goto out; goto out;
@ -323,9 +333,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(hcd->self.controller, dev_dbg(hcd->self.controller,
"ClearPortFeature: OVER_CURRENT\n"); "ClearPortFeature: OVER_CURRENT\n");
if (wIndex == 1 || wIndex == 2) { if (valid_port(wIndex))
pdata->overcurrent_status[wIndex-1] = 0; pdata->overcurrent_status[wIndex] = 0;
}
goto out; goto out;
@ -333,15 +342,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(hcd->self.controller, dev_dbg(hcd->self.controller,
"ClearPortFeature: POWER\n"); "ClearPortFeature: POWER\n");
if (wIndex == 1 || wIndex == 2) { if (valid_port(wIndex)) {
ohci_at91_usb_set_power(pdata, wIndex - 1, 0); ohci_at91_usb_set_power(pdata, wIndex, 0);
return 0; return 0;
} }
} }
break; break;
} }
ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
if (ret) if (ret)
goto out; goto out;
@ -377,18 +386,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
if (wIndex == 1 || wIndex == 2) { if (valid_port(wIndex)) {
if (! ohci_at91_usb_get_power(pdata, wIndex-1)) { if (!ohci_at91_usb_get_power(pdata, wIndex))
*data &= ~cpu_to_le32(RH_PS_PPS); *data &= ~cpu_to_le32(RH_PS_PPS);
}
if (pdata->overcurrent_changed[wIndex-1]) { if (pdata->overcurrent_changed[wIndex])
*data |= cpu_to_le32(RH_PS_OCIC); *data |= cpu_to_le32(RH_PS_OCIC);
}
if (pdata->overcurrent_status[wIndex-1]) { if (pdata->overcurrent_status[wIndex])
*data |= cpu_to_le32(RH_PS_POCI); *data |= cpu_to_le32(RH_PS_POCI);
}
} }
} }
@ -450,14 +456,14 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
/* From the GPIO notifying the over-current situation, find /* From the GPIO notifying the over-current situation, find
* out the corresponding port */ * out the corresponding port */
for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { at91_for_each_port(port) {
if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
gpio = pdata->overcurrent_pin[port]; gpio = pdata->overcurrent_pin[port];
break; break;
} }
} }
if (port == ARRAY_SIZE(pdata->overcurrent_pin)) { if (port == AT91_MAX_USBH_PORTS) {
dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -467,7 +473,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
/* When notified of an over-current situation, disable power /* When notified of an over-current situation, disable power
on the corresponding port, and mark this port in on the corresponding port, and mark this port in
over-current. */ over-current. */
if (! val) { if (!val) {
ohci_at91_usb_set_power(pdata, port, 0); ohci_at91_usb_set_power(pdata, port, 0);
pdata->overcurrent_status[port] = 1; pdata->overcurrent_status[port] = 1;
pdata->overcurrent_changed[port] = 1; pdata->overcurrent_changed[port] = 1;
@ -492,7 +498,7 @@ static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
static int __devinit ohci_at91_of_init(struct platform_device *pdev) static int __devinit ohci_at91_of_init(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
int i, ret, gpio; int i, gpio;
enum of_gpio_flags flags; enum of_gpio_flags flags;
struct at91_usbh_data *pdata; struct at91_usbh_data *pdata;
u32 ports; u32 ports;
@ -514,48 +520,17 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
if (!of_property_read_u32(np, "num-ports", &ports)) if (!of_property_read_u32(np, "num-ports", &ports))
pdata->ports = ports; pdata->ports = ports;
for (i = 0; i < 2; i++) { at91_for_each_port(i) {
gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags); gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
pdata->vbus_pin[i] = gpio; pdata->vbus_pin[i] = gpio;
if (!gpio_is_valid(gpio)) if (!gpio_is_valid(gpio))
continue; continue;
pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
ret = gpio_request(gpio, "ohci_vbus");
if (ret) {
dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio);
continue;
}
ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1);
if (ret)
dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d",
!(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio);
} }
for (i = 0; i < 2; i++) { at91_for_each_port(i)
gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); pdata->overcurrent_pin[i] =
pdata->overcurrent_pin[i] = gpio; of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
if (!gpio_is_valid(gpio))
continue;
ret = gpio_request(gpio, "ohci_overcurrent");
if (ret) {
dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio);
continue;
}
ret = gpio_direction_input(gpio);
if (ret) {
dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio);
continue;
}
ret = request_irq(gpio_to_irq(gpio),
ohci_hcd_at91_overcurrent_irq,
IRQF_SHARED, "ohci_overcurrent", pdev);
if (ret) {
gpio_free(gpio);
dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
}
}
pdev->dev.platform_data = pdata; pdev->dev.platform_data = pdata;
@ -574,35 +549,69 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
{ {
struct at91_usbh_data *pdata; struct at91_usbh_data *pdata;
int i; int i;
int gpio;
int ret;
i = ohci_at91_of_init(pdev); ret = ohci_at91_of_init(pdev);
if (ret)
if (i) return ret;
return i;
pdata = pdev->dev.platform_data; pdata = pdev->dev.platform_data;
if (pdata) { if (pdata) {
for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { at91_for_each_port(i) {
if (!gpio_is_valid(pdata->vbus_pin[i])) if (!gpio_is_valid(pdata->vbus_pin[i]))
continue; continue;
gpio_request(pdata->vbus_pin[i], "ohci_vbus"); gpio = pdata->vbus_pin[i];
ret = gpio_request(gpio, "ohci_vbus");
if (ret) {
dev_err(&pdev->dev,
"can't request vbus gpio %d\n", gpio);
continue;
}
ret = gpio_direction_output(gpio,
!pdata->vbus_pin_active_low[i]);
if (ret) {
dev_err(&pdev->dev,
"can't put vbus gpio %d as output %d\n",
gpio, !pdata->vbus_pin_active_low[i]);
gpio_free(gpio);
continue;
}
ohci_at91_usb_set_power(pdata, i, 1); ohci_at91_usb_set_power(pdata, i, 1);
} }
for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { at91_for_each_port(i) {
int ret;
if (!gpio_is_valid(pdata->overcurrent_pin[i])) if (!gpio_is_valid(pdata->overcurrent_pin[i]))
continue; continue;
gpio_request(pdata->overcurrent_pin[i], "ohci_overcurrent"); gpio = pdata->overcurrent_pin[i];
ret = request_irq(gpio_to_irq(pdata->overcurrent_pin[i]), ret = gpio_request(gpio, "ohci_overcurrent");
if (ret) {
dev_err(&pdev->dev,
"can't request overcurrent gpio %d\n",
gpio);
continue;
}
ret = gpio_direction_input(gpio);
if (ret) {
dev_err(&pdev->dev,
"can't configure overcurrent gpio %d as input\n",
gpio);
gpio_free(gpio);
continue;
}
ret = request_irq(gpio_to_irq(gpio),
ohci_hcd_at91_overcurrent_irq, ohci_hcd_at91_overcurrent_irq,
IRQF_SHARED, "ohci_overcurrent", pdev); IRQF_SHARED, "ohci_overcurrent", pdev);
if (ret) { if (ret) {
gpio_free(pdata->overcurrent_pin[i]); gpio_free(gpio);
dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n"); dev_err(&pdev->dev,
"can't get gpio IRQ for overcurrent\n");
} }
} }
} }
@ -617,14 +626,14 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
int i; int i;
if (pdata) { if (pdata) {
for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { at91_for_each_port(i) {
if (!gpio_is_valid(pdata->vbus_pin[i])) if (!gpio_is_valid(pdata->vbus_pin[i]))
continue; continue;
ohci_at91_usb_set_power(pdata, i, 0); ohci_at91_usb_set_power(pdata, i, 0);
gpio_free(pdata->vbus_pin[i]); gpio_free(pdata->vbus_pin[i]);
} }
for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { at91_for_each_port(i) {
if (!gpio_is_valid(pdata->overcurrent_pin[i])) if (!gpio_is_valid(pdata->overcurrent_pin[i]))
continue; continue;
free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);