* The driver basically works. A number of people have used it with a range
* of devices.
*
- *The driver passes all usbtests 1-14.
+ * The driver passes all usbtests 1-14.
*
* Suspending/resuming of root hub via sysfs works. Remote wakeup works too.
* And suspending/resuming of platform device works too. Suspend/resume
struct isp116x_ep *ep;
struct urb *urb;
struct ptd *ptd;
- u16 toggle, dir, len;
+ u16 len;
for (ep = isp116x->atl_active; ep; ep = ep->active) {
+ u16 toggle = 0, dir = PTD_DIR_SETUP;
+
BUG_ON(list_empty(&ep->hep->urb_list));
urb = container_of(ep->hep->urb_list.next,
struct urb, urb_list);
dir = PTD_DIR_OUT;
break;
case USB_PID_SETUP:
- toggle = 0;
- dir = PTD_DIR_SETUP;
len = sizeof(struct usb_ctrlrequest);
ep->data = urb->setup_packet;
break;
? PTD_DIR_OUT : PTD_DIR_IN;
break;
default:
- /* To please gcc */
- toggle = dir = 0;
ERR("%s %d: ep->nextpid %d\n", __func__, __LINE__,
ep->nextpid);
- BUG_ON(1);
+ BUG();
}
ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle);
static int isp116x_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *hep, struct urb *urb,
- int mem_flags)
+ unsigned mem_flags)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
struct usb_device *udev = urb->dev;
}
/* avoid all allocations within spinlocks: request or endpoint */
if (!hep->hcpriv) {
- ep = kcalloc(1, sizeof *ep, (__force unsigned)mem_flags);
+ ep = kzalloc(sizeof *ep, mem_flags);
if (!ep)
return -ENOMEM;
}
break;
case GetHubStatus:
DBG("GetHubStatus\n");
- *(__le32 *) buf = cpu_to_le32(0);
+ *(__le32 *) buf = 0;
break;
case GetPortStatus:
DBG("GetPortStatus\n");
return ret;
}
-/*
- Reset. Tries to perform platform-specific hardware
- reset first; falls back to software reset.
-*/
static int isp116x_reset(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
u16 clkrdy = 0;
int ret = 0, timeout = 15 /* ms */ ;
- if (isp116x->board && isp116x->board->reset) {
- /* Hardware reset */
- isp116x->board->reset(hcd->self.controller, 1);
- msleep(10);
- if (isp116x->board->clock)
- isp116x->board->clock(hcd->self.controller, 1);
- msleep(1);
- isp116x->board->reset(hcd->self.controller, 0);
- } else
- ret = isp116x_sw_reset(isp116x);
-
+ ret = isp116x_sw_reset(isp116x);
if (ret)
return ret;
}
if (!clkrdy) {
ERR("Clock not ready after 20ms\n");
+ /* After sw_reset the clock won't report to be ready, if
+ H_WAKEUP pin is high. */
+ ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
ret = -ENODEV;
}
return ret;
isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
spin_unlock_irqrestore(&isp116x->lock, flags);
- /* Put the chip into reset state */
- if (isp116x->board && isp116x->board->reset)
- isp116x->board->reset(hcd->self.controller, 0);
- else
- isp116x_sw_reset(isp116x);
-
- /* Stop the clock */
- if (isp116x->board && isp116x->board->clock)
- isp116x->board->clock(hcd->self.controller, 0);
+ isp116x_sw_reset(isp116x);
}
/*
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
struct isp116x_platform_data *board = isp116x->board;
- struct usb_device *udev;
u32 val;
unsigned long flags;
if (board->sel15Kres)
val |= HCHWCFG_15KRSEL;
/* Remote wakeup won't work without working clock */
- if (board->clknotstop || board->remote_wakeup_enable)
+ if (board->remote_wakeup_enable)
val |= HCHWCFG_CLKNOTSTOP;
if (board->oc_enable)
val |= HCHWCFG_ANALOG_OC;
isp116x_write_reg16(isp116x, HCHWCFG, val);
/* ----- Root hub conf */
- val = 0;
- /* AN10003_1.pdf recommends NPS to be always 1 */
- if (board->no_power_switching)
- val |= RH_A_NPS;
- if (board->power_switching_mode)
- val |= RH_A_PSM;
- if (board->potpg)
- val |= (board->potpg << 24) & RH_A_POTPGT;
- else
- val |= (25 << 24) & RH_A_POTPGT;
+ val = (25 << 24) & RH_A_POTPGT;
+ /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
+ be always set. Yet, instead, we request individual port
+ power switching. */
+ val |= RH_A_PSM;
+ /* Report overcurrent per port */
+ val |= RH_A_OCPM;
isp116x_write_reg32(isp116x, HCRHDESCA, val);
isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
- spin_unlock_irqrestore(&isp116x->lock, flags);
-
- udev = usb_alloc_dev(NULL, &hcd->self, 0);
- if (!udev) {
- isp116x_stop(hcd);
- return -ENOMEM;
- }
- udev->speed = USB_SPEED_FULL;
hcd->state = HC_STATE_RUNNING;
- if (usb_hcd_register_root_hub(udev, hcd) != 0) {
- isp116x_stop(hcd);
- usb_put_dev(udev);
- return -ENODEV;
- }
-
- spin_lock_irqsave(&isp116x->lock, flags);
/* Set up interrupts */
isp116x->intenb = HCINT_MIE | HCINT_RHSC | HCINT_UE;
if (board->remote_wakeup_enable)
/* Go operational */
val = HCCONTROL_USB_OPER;
- /* Remote wakeup connected - NOT SUPPORTED */
- /* if (board->remote_wakeup_connected)
- val |= HCCONTROL_RWC; */
if (board->remote_wakeup_enable)
val |= HCCONTROL_RWE;
isp116x_write_reg32(isp116x, HCCONTROL, val);
static int __init_or_module isp116x_remove(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
- struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ struct isp116x *isp116x;
struct platform_device *pdev;
struct resource *res;
+ if(!hcd)
+ return 0;
+ isp116x = hcd_to_isp116x(hcd);
pdev = container_of(dev, struct platform_device, dev);
remove_debug_file(isp116x);
usb_remove_hcd(hcd);
ret = usb_suspend_device(hcd->self.root_hub, state);
if (!ret) {
dev->power.power_state = state;
- INFO("%s suspended\n", (char *)hcd_name);
+ INFO("%s suspended\n", hcd_name);
} else
- ERR("%s suspend failed\n", (char *)hcd_name);
+ ERR("%s suspend failed\n", hcd_name);
return ret;
}