Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 298687
b: refs/heads/master
c: 0ee6d1e
h: refs/heads/master
i:
  298685: 43fd646
  298683: 25e8cae
  298679: 8aed373
  298671: c8aa1f9
  298655: 840608c
  298623: 64bbf91
v: v3
  • Loading branch information
Nicolas Ferre committed Apr 4, 2012
1 parent 55a3e60 commit aa18714
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aaf9f5fc67c18259760d6302e679dcb3e36709a7
refs/heads/master: 0ee6d1eeef7bf4e08aba37bf1da377b25e8d853a
13 changes: 7 additions & 6 deletions trunk/arch/arm/mach-at91/include/mach/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/* USB Host */
#define AT91_MAX_USBH_PORTS 3
struct at91_usbh_data {
u8 ports; /* number of ports on root hub */
int vbus_pin[2]; /* port power-control pin */
u8 vbus_pin_active_low[2];
int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
int overcurrent_pin[AT91_MAX_USBH_PORTS];
u8 ports; /* number of ports on root hub */
u8 overcurrent_supported;
int overcurrent_pin[2];
u8 overcurrent_status[2];
u8 overcurrent_changed[2];
u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
u8 overcurrent_status[AT91_MAX_USBH_PORTS];
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_ohci(struct at91_usbh_data *data);
Expand Down
66 changes: 36 additions & 30 deletions trunk/drivers/usb/host/ohci-at91.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#error "CONFIG_ARCH_AT91 must be defined."
#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 */
static struct clk *iclk, *fclk, *hclk;
static int clocked;
Expand Down Expand Up @@ -240,7 +244,7 @@ ohci_at91_start (struct usb_hcd *hcd)

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;

if (!gpio_is_valid(pdata->vbus_pin[port]))
Expand All @@ -252,7 +256,7 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int

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;

if (!gpio_is_valid(pdata->vbus_pin[port]))
Expand All @@ -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 port;

for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
at91_for_each_port(port) {
if (pdata->overcurrent_changed[port]) {
if (! length)
if (!length)
length = 1;
buf[0] |= 1 << (port + 1);
}
Expand All @@ -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",
hcd, typeReq, wValue, wIndex, buf, wLength);

wIndex--;

switch (typeReq) {
case SetPortFeature:
if (wValue == USB_PORT_FEAT_POWER) {
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;
}
break;
Expand All @@ -312,9 +322,9 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(hcd->self.controller,
"ClearPortFeature: C_OVER_CURRENT\n");

if (wIndex == 1 || wIndex == 2) {
pdata->overcurrent_changed[wIndex-1] = 0;
pdata->overcurrent_status[wIndex-1] = 0;
if (valid_port(wIndex)) {
pdata->overcurrent_changed[wIndex] = 0;
pdata->overcurrent_status[wIndex] = 0;
}

goto out;
Expand All @@ -323,25 +333,24 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(hcd->self.controller,
"ClearPortFeature: OVER_CURRENT\n");

if (wIndex == 1 || wIndex == 2) {
pdata->overcurrent_status[wIndex-1] = 0;
}
if (valid_port(wIndex))
pdata->overcurrent_status[wIndex] = 0;

goto out;

case USB_PORT_FEAT_POWER:
dev_dbg(hcd->self.controller,
"ClearPortFeature: POWER\n");

if (wIndex == 1 || wIndex == 2) {
ohci_at91_usb_set_power(pdata, wIndex - 1, 0);
if (valid_port(wIndex)) {
ohci_at91_usb_set_power(pdata, wIndex, 0);
return 0;
}
}
break;
}

ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
if (ret)
goto out;

Expand Down Expand Up @@ -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);

if (wIndex == 1 || wIndex == 2) {
if (! ohci_at91_usb_get_power(pdata, wIndex-1)) {
if (valid_port(wIndex)) {
if (!ohci_at91_usb_get_power(pdata, wIndex))
*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);
}

if (pdata->overcurrent_status[wIndex-1]) {
if (pdata->overcurrent_status[wIndex])
*data |= cpu_to_le32(RH_PS_POCI);
}
}
}

Expand Down Expand Up @@ -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
* 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) {
gpio = pdata->overcurrent_pin[port];
break;
}
}

if (port == ARRAY_SIZE(pdata->overcurrent_pin)) {
if (port == AT91_MAX_USBH_PORTS) {
dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
return IRQ_HANDLED;
}
Expand All @@ -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
on the corresponding port, and mark this port in
over-current. */
if (! val) {
if (!val) {
ohci_at91_usb_set_power(pdata, port, 0);
pdata->overcurrent_status[port] = 1;
pdata->overcurrent_changed[port] = 1;
Expand Down Expand Up @@ -514,15 +520,15 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
if (!of_property_read_u32(np, "num-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);
pdata->vbus_pin[i] = gpio;
if (!gpio_is_valid(gpio))
continue;
pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
}

for (i = 0; i < 2; i++)
at91_for_each_port(i)
pdata->overcurrent_pin[i] =
of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);

Expand Down Expand Up @@ -554,7 +560,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;

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]))
continue;
gpio = pdata->vbus_pin[i];
Expand All @@ -578,7 +584,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
ohci_at91_usb_set_power(pdata, i, 1);
}

for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
at91_for_each_port(i) {
if (!gpio_is_valid(pdata->overcurrent_pin[i]))
continue;
gpio = pdata->overcurrent_pin[i];
Expand Down Expand Up @@ -621,14 +627,14 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
int i;

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]))
continue;
ohci_at91_usb_set_power(pdata, i, 0);
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]))
continue;
free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);
Expand Down

0 comments on commit aa18714

Please sign in to comment.