* This file contains the implementation of the HCD. In Linux, the HCD
* implements the hc_driver API.
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
static int dwc_otg_hcd_suspend(struct usb_hcd *hcd)
{
-#if 1
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (hcd);
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
hprt0_data_t hprt0;
pcgcctl_data_t pcgcctl;
- //dwc_debug(1);
if(core_if->op_state == B_PERIPHERAL)
{
- printk("%s, usb device mode\n", __func__);
+ DWC_PRINT("%s, usb device mode\n", __func__);
return 0;
}
hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- //partial power-down
- if(!hprt0.b.prtsusp)
+ DWC_PRINT("%s suspend, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ if(hprt0.b.prtconnsts) // usb device connected
{
- //hprt0.d32 = 0;
- hprt0.b.prtsusp = 1;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ //partial power-down
+ if(!hprt0.b.prtsusp)
+ {
+ //hprt0.d32 = 0;
+ hprt0.b.prtsusp = 1;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ }
+ udelay(10);
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ if(!hprt0.b.prtsusp)
+ {
+ //hprt0.d32 = 0;
+ hprt0.b.prtsusp = 1;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ }
+ mdelay(5);
+ pcgcctl.d32 = dwc_read_reg32(core_if->pcgcctl);
+ pcgcctl.b.pwrclmp = 1;//power clamp
+ dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
+ udelay(1);
+ //pcgcctl.b.rstpdwnmodule = 1;//reset PDM
+ pcgcctl.b.stoppclk = 1;//stop phy clk
+ dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
}
- udelay(10);
- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- if(!hprt0.b.prtsusp)
+ else //no device connect
{
- //hprt0.d32 = 0;
- hprt0.b.prtsusp = 1;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ if (core_if->hcd_cb && core_if->hcd_cb->suspend) {
+ core_if->hcd_cb->suspend( core_if->hcd_cb->p, 0);
+ }
}
- mdelay(5);
-#if 1
- pcgcctl.d32 = dwc_read_reg32(core_if->pcgcctl);
- pcgcctl.b.pwrclmp = 1;//power clamp
- dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
- udelay(1);
- //pcgcctl.b.rstpdwnmodule = 1;//reset PDM
- pcgcctl.b.stoppclk = 1;//stop phy clk
- dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
-#endif
-#endif
+ udelay(3);
+ #ifndef CONFIG_DWC_REMOTE_WAKEUP
+ clk_disable(core_if->otg_dev->phyclk);
+ clk_disable(core_if->otg_dev->ahbclk);
+ #endif
//power off
return 0;
}
static int dwc_otg_hcd_resume(struct usb_hcd *hcd)
{
-#if 1
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (hcd);
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
hprt0_data_t hprt0;
if(core_if->op_state == B_PERIPHERAL)
{
- printk("%s, usb device mode\n", __func__);
+ DWC_PRINT("%s, usb device mode\n", __func__);
return 0;
}
-#if 1
+ #ifndef CONFIG_DWC_REMOTE_WAKEUP
+ clk_enable(core_if->otg_dev->phyclk);
+ clk_enable(core_if->otg_dev->ahbclk);
+ #endif
//partial power-down
//power on
pcgcctl.d32 = dwc_read_reg32(core_if->pcgcctl);;
pcgcctl.b.pwrclmp = 0;//power clamp
dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
udelay(2);
-#endif
- //dwc_debug(3);
- //dwc_debug(1);
+
gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk);
gintmsk.b.portintr = 0;
dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
-
+
hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- hprt0.b.prtpwr = 1;
- hprt0.b.prtres = 1;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
- mdelay(20);
- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- //hprt0.d32 = 0;
- hprt0.b.prtpwr = 1;
- hprt0.b.prtres = 0;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
- hprt0.d32 = 0;
- hprt0.b.prtpwr = 1;
- hprt0.b.prtena = 0;
- hprt0.b.prtconndet = 1;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
-
- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
-
+ DWC_PRINT("%s resume, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ if(hprt0.b.prtconnsts)
+ {
+ //hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ //DWC_PRINT("%s, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ hprt0.b.prtpwr = 1;
+ hprt0.b.prtres = 1;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ mdelay(20);
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ //DWC_PRINT("%s, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ //hprt0.d32 = 0;
+ hprt0.b.prtpwr = 1;
+ hprt0.b.prtres = 0;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ hprt0.d32 = 0;
+ hprt0.b.prtpwr = 1;
+ hprt0.b.prtena = 0;
+ hprt0.b.prtconndet = 1;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+
+ //hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ //DWC_PRINT("%s, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+
+ mdelay(10);
+ }
+ else
+ {
+ if (core_if->hcd_cb && core_if->hcd_cb->suspend) {
+ core_if->hcd_cb->suspend( core_if->hcd_cb->p, 1);
+ }
+ }
gintmsk.b.portintr = 1;
dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
- mdelay(10);
-#endif
+
return 0;
}
//.hub_resume =
};
-#ifdef CONFIG_RK2818_HOST11
-static const struct hc_driver rk28_host11_hc_driver = {
+#ifdef CONFIG_USB11_HOST
+static const struct hc_driver host11_hc_driver = {
+
+ .description = "host11_hcd",
+ .product_desc = "DWC OTG Controller",
+ .hcd_priv_size = sizeof(dwc_otg_hcd_t),
+
+ .irq = dwc_otg_hcd_irq,
+
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ //.reset =
+ .start = dwc_otg_hcd_start,
+ //.suspend =
+ //.resume =
+
+ /* yk@rk 20100625
+ * core/hcd.c call hcd->driver->bus_suspend
+ * otherwise system can not be suspended
+ */
+#ifdef CONFIG_PM
+ .bus_suspend = dwc_otg_hcd_suspend,
+ .bus_resume = dwc_otg_hcd_resume,
+#endif
+ .stop = dwc_otg_hcd_stop,
+
+ .urb_enqueue = dwc_otg_hcd_urb_enqueue,
+ .urb_dequeue = dwc_otg_hcd_urb_dequeue,
+ .endpoint_disable = dwc_otg_hcd_endpoint_disable,
+
+ .get_frame_number = dwc_otg_hcd_get_frame_number,
+
+ .hub_status_data = dwc_otg_hcd_hub_status_data,
+ .hub_control = dwc_otg_hcd_hub_control,
+ //.hub_suspend =
+ //.hub_resume =
+};
+#endif
+#ifdef CONFIG_USB20_HOST
+static const struct hc_driver host20_hc_driver = {
- .description = "rk28_host11_hcd",
+ .description = "host20_hcd",
.product_desc = "DWC OTG Controller",
.hcd_priv_size = sizeof(dwc_otg_hcd_t),
* Work queue function for starting the HCD when A-Cable is connected.
* The dwc_otg_hcd_start() must be called in a process context.
*/
-// cmy
static void hcd_start_func(struct work_struct *work)
{
dwc_otg_hcd_t *dwc_otg_hcd = container_of(work, dwc_otg_hcd_t, start_work);
dwc_otg_qh_t *qh;
struct list_head *qtd_item;
dwc_otg_qtd_t *qtd;
+ struct urb *urb;
+ struct usb_host_endpoint *ep;
list_for_each(qh_item, _qh_list) {
qh = list_entry(qh_item, dwc_otg_qh_t, qh_list_entry);
qtd_item = qh->qtd_list.next) {
qtd = list_entry(qtd_item, dwc_otg_qtd_t, qtd_list_entry);
if (qtd->urb != NULL) {
+ urb = qtd->urb;
+ ep = qtd->urb->ep;
+ // 20110415 yk
+ // urb will be re entry to ep->urb_list if use ETIMEOUT
dwc_otg_hcd_complete_urb(_hcd, qtd->urb,
- -ETIMEDOUT);
+ -ETIMEDOUT);//ESHUTDOWN
+
+ //if(!list_empty(&ep->urb_list))
+ DWC_PRINT("%s: urb %p, device %d, ep %d %s, status=%d\n",
+ __func__, urb, usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "IN" : "OUT", urb->unlinked);
+
+ if (!urb->unlinked)
+ urb->unlinked = -ESHUTDOWN;
+
}
dwc_otg_hcd_qtd_remove_and_free(qtd);
}
static int32_t dwc_otg_hcd_disconnect_cb( void *_p )
{
gintsts_data_t intr;
- dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_p);
+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_p);
- //DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p);
+ //DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p);
- /*
- * Set status flags for the hub driver.
- */
- printk("dwc_otg_hcd_disconnect_cb");
- dwc_otg_hcd->flags.b.port_connect_status_change = 1;
+ /*
+ * Set status flags for the hub driver.
+ */
+ dwc_otg_hcd->flags.b.port_connect_status_change = 1;
dwc_otg_hcd->flags.b.port_connect_status = 0;
- /*
- * Shutdown any transfers in process by clearing the Tx FIFO Empty
- * interrupt mask and status bits and disabling subsequent host
- * channel interrupts.
- */
- intr.d32 = 0;
- intr.b.nptxfempty = 1;
- intr.b.ptxfempty = 1;
+ /*
+ * Shutdown any transfers in process by clearing the Tx FIFO Empty
+ * interrupt mask and status bits and disabling subsequent host
+ * channel interrupts.
+ */
+ intr.d32 = 0;
+ intr.b.nptxfempty = 1;
+ intr.b.ptxfempty = 1;
intr.b.hcintr = 1;
- dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintmsk, intr.d32, 0);
- dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintsts, intr.d32, 0);
+ dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintmsk, intr.d32, 0);
+ dwc_modify_reg32 (&dwc_otg_hcd->core_if->core_global_regs->gintsts, intr.d32, 0);
del_timers(dwc_otg_hcd);
}
}
- /* A disconnect will end the session so the B-Device is no
- * longer a B-host. */
- ((struct usb_hcd *)_p)->self.is_b_host = 0;
- return 1;
+ /* A disconnect will end the session so the B-Device is no
+ * longer a B-host. */
+ ((struct usb_hcd *)_p)->self.is_b_host = 0;
+ return 1;
}
/**
return 1;
}
+/*
+ * suspend: 0 usb phy enable
+ * 1 usb phy suspend
+ */
+static int32_t dwc_otg_phy_suspend_cb( void *_p, int suspend)
+{
+ unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+
+ if(suspend) {
+ *otg_phy_con1 |= (0x01<<2);
+ *otg_phy_con1 |= (0x01<<3); // exit suspend.
+ *otg_phy_con1 &= ~(0x01<<2);
+
+ DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
+ }
+ else
+ {
+ *otg_phy_con1 |= (0x01<<2);
+ *otg_phy_con1 &= ~(0x01<<3); // enter suspend.
+ DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
+ }
+
+ return suspend;
+}
+
/**
* HCD Callback structure for handling mode switching.
*/
.stop = dwc_otg_hcd_stop_cb,
.disconnect = dwc_otg_hcd_disconnect_cb,
.session_start = dwc_otg_hcd_session_start_cb,
+ .suspend = dwc_otg_phy_suspend_cb,
.p = 0,//hcd
};
dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t*)data;
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
hprt0_data_t hprt0;
-
+
DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
hprt0.d32 = dwc_otg_read_hprt0 (core_if);
/* Set device flags indicating whether the HCD supports DMA. */
static u64 usb_dmamask = 0xffffffffUL;
if (otg_dev->core_if->dma_enable) {
-// DWC_PRINT("Using DMA mode\n");
dev->dma_mask = &usb_dmamask;
dev->coherent_dma_mask = ~0;
} else {
-// DWC_PRINT("Using Slave mode\n");
dev->dma_mask = (void *)0;
dev->coherent_dma_mask = 0;
}
#endif
- printk("dwc_otg_hcd_init everest\n");
// g_dbg_lvl = 0xff;
- DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n");
-
/*
* Allocate memory for the base HCD plus the DWC OTG HCD.
* Initialize the base HCD.
dwc_otg_hcd->core_if = otg_dev->core_if;
otg_dev->hcd = dwc_otg_hcd;
+
+#ifdef CONFIG_USB20_OTG_EN
+ dwc_otg_hcd->host_enabled = 1;
+#else
+ dwc_otg_hcd->host_enabled = 0;
+#endif
/* Register the HCD CIL Callbacks */
dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if,
DWC_ERROR("%s: status_buf allocation failed\n", __func__);
goto error3;
}
-
- DWC_PRINT("%s end,everest\n",__func__);
+
// DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, bus=%s, usbbus=%d\n",
// dev->bus_id, hcd->self.busnum);
usb_put_hcd(hcd);
error1:
- printk("dwc_otg_hcd_init error,everest\n");
+ DWC_PRINT("dwc_otg_hcd_init error,everest\n");
return retval;
}
-#ifdef CONFIG_RK2818_HOST11
-static dwc_otg_cil_callbacks_t rk28_host11_cil_callbacks = {
+#ifdef CONFIG_USB11_HOST
+/*
+ * suspend: 0 usb phy enable
+ * 1 usb phy suspend
+ */
+static int32_t host11_phy_suspend_cb( void *_p, int suspend)
+{
+ unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+
+ if(suspend) {
+ *otg_phy_con1 &= ~(0x01<<28);
+ DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
+ }
+ else
+ {
+ *otg_phy_con1 |= (0x01<<28);
+ DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
+ }
+
+ return suspend;
+}
+static dwc_otg_cil_callbacks_t host11_cil_callbacks = {
.start = dwc_otg_hcd_start_cb,
.stop = dwc_otg_hcd_stop_cb,
.disconnect = dwc_otg_hcd_disconnect_cb,
.session_start = dwc_otg_hcd_session_start_cb,
+ .suspend = host11_phy_suspend_cb,
.p = 0,//hcd
};
-static struct tasklet_struct rk28_host11_reset_tasklet = {
+static struct tasklet_struct host11_reset_tasklet = {
.next = NULL,
.state = 0,
.count = ATOMIC_INIT(0),
.data = 0,
};
-int __devinit rk28_host11_hcd_init(struct device *dev)
+int __devinit host11_hcd_init(struct device *dev)
{
struct usb_hcd *hcd = NULL;
dwc_otg_hcd_t *dwc_otg_hcd = NULL;
dev->coherent_dma_mask = 0;
}
#endif
- printk("%s everest\n",__func__);
// g_dbg_lvl = 0xff;
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n");
* Allocate memory for the base HCD plus the DWC OTG HCD.
* Initialize the base HCD.
*/
- hcd = usb_create_hcd(&rk28_host11_hc_driver, dev, dev_name(dev));
+ hcd = usb_create_hcd(&host11_hc_driver, dev, dev_name(dev));
if (hcd == NULL) {
retval = -ENOMEM;
goto error1;
dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
dwc_otg_hcd->core_if = otg_dev->core_if;
otg_dev->hcd = dwc_otg_hcd;
+
+#ifdef CONFIG_USB11_HOST_EN
+ dwc_otg_hcd->host_enabled = 1;
+#else
+ dwc_otg_hcd->host_enabled = 0;
+#endif
spin_lock_init(&dwc_otg_hcd->global_lock);
/* Register the HCD CIL Callbacks */
dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if,
- &rk28_host11_cil_callbacks, hcd);
+ &host11_cil_callbacks, hcd);
/* Initialize the non-periodic schedule. */
INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_inactive);
init_timer( &dwc_otg_hcd->conn_timer );
/* Initialize reset tasklet. */
- rk28_host11_reset_tasklet.data = (unsigned long) dwc_otg_hcd;
- dwc_otg_hcd->reset_tasklet = &rk28_host11_reset_tasklet;
+ host11_reset_tasklet.data = (unsigned long) dwc_otg_hcd;
+ dwc_otg_hcd->reset_tasklet = &host11_reset_tasklet;
/*
* Finish generic HCD initialization and start the HCD. This function
* allocates the DMA buffer pool, registers the USB bus, requests the
goto error3;
}
- DWC_PRINT("%s end,everest\n",__func__);
// DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, bus=%s, usbbus=%d\n",
// dev->bus_id, hcd->self.busnum);
usb_put_hcd(hcd);
error1:
- printk("dwc_otg_hcd_init error,everest\n");
+ DWC_PRINT("dwc_otg_hcd_init error,everest\n");
+ return retval;
+}
+#endif
+#ifdef CONFIG_USB20_HOST
+
+/*
+ * suspend: 0 usb phy enable
+ * 1 usb phy suspend
+ */
+static int32_t host20_phy_suspend_cb( void *_p, int suspend)
+{
+ unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+ uint32_t regval;
+
+ regval = *otg_phy_con1;
+
+ if(suspend) {
+ regval |= (0x01<<14); // exit suspend.
+ regval &= ~(0x01<<13);
+
+ DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
+ }
+ else
+ {
+ regval &= ~(0x01<<14); // exit suspend.
+ regval |= (0x01<<13); // software control
+ DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
+ }
+ *otg_phy_con1 = regval;
+
+ return suspend;
+}
+
+static dwc_otg_cil_callbacks_t host20_cil_callbacks = {
+ .start = dwc_otg_hcd_start_cb,
+ .stop = dwc_otg_hcd_stop_cb,
+ .disconnect = dwc_otg_hcd_disconnect_cb,
+ .session_start = dwc_otg_hcd_session_start_cb,
+ .suspend = host20_phy_suspend_cb,
+ .p = 0,//hcd
+};
+
+static struct tasklet_struct host20_reset_tasklet = {
+ .next = NULL,
+ .state = 0,
+ .count = ATOMIC_INIT(0),
+ .func = reset_tasklet_func,
+ .data = 0,
+};
+
+int __devinit host20_hcd_init(struct device *dev)
+{
+ struct usb_hcd *hcd = NULL;
+ dwc_otg_hcd_t *dwc_otg_hcd = NULL;
+ dwc_otg_device_t *otg_dev = dev->platform_data;
+
+ int num_channels;
+ int i;
+ dwc_hc_t *channel;
+
+ int retval = 0;
+#if 1 //kaiker .these code must execute before usb_create_hcd
+ /* Set device flags indicating whether the HCD supports DMA. */
+ static u64 usb_dmamask = 0xffffffffUL;
+ if (otg_dev->core_if->dma_enable) {
+// DWC_PRINT("Using DMA mode\n");
+ dev->dma_mask = &usb_dmamask;
+ dev->coherent_dma_mask = ~0;
+ } else {
+// DWC_PRINT("Using Slave mode\n");
+ dev->dma_mask = (void *)0;
+ dev->coherent_dma_mask = 0;
+ }
+#endif
+// g_dbg_lvl = 0xff;
+
+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n");
+
+ /*
+ * Allocate memory for the base HCD plus the DWC OTG HCD.
+ * Initialize the base HCD.
+ */
+ hcd = usb_create_hcd(&host20_hc_driver, dev, dev_name(dev));
+ if (hcd == NULL) {
+ retval = -ENOMEM;
+ goto error1;
+ }
+ hcd->regs = otg_dev->base;
+ hcd->self.otg_port = 1;
+
+ /* Initialize the DWC OTG HCD. */
+ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
+ dwc_otg_hcd->core_if = otg_dev->core_if;
+ otg_dev->hcd = dwc_otg_hcd;
+
+#ifdef CONFIG_USB20_HOST_EN
+ dwc_otg_hcd->host_enabled = 1;
+#else
+ dwc_otg_hcd->host_enabled = 0;
+#endif
+
+ spin_lock_init(&dwc_otg_hcd->global_lock);
+
+
+ /* Register the HCD CIL Callbacks */
+ dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if,
+ &host20_cil_callbacks, hcd);
+
+ /* Initialize the non-periodic schedule. */
+ INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_inactive);
+ INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_active);
+
+ /* Initialize the periodic schedule. */
+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_inactive);
+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_ready);
+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_assigned);
+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_queued);
+
+ /*
+ * Create a host channel descriptor for each host channel implemented
+ * in the controller. Initialize the channel descriptor array.
+ */
+ INIT_LIST_HEAD(&dwc_otg_hcd->free_hc_list);
+ num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
+ for (i = 0; i < num_channels; i++) {
+ channel = kmalloc(sizeof(dwc_hc_t), GFP_KERNEL);
+ if (channel == NULL) {
+ retval = -ENOMEM;
+ DWC_ERROR("%s: host channel allocation failed\n", __func__);
+ goto error2;
+ }
+ memset(channel, 0, sizeof(dwc_hc_t));
+ channel->hc_num = i;
+ dwc_otg_hcd->hc_ptr_array[i] = channel;
+#ifdef DEBUG
+ init_timer(&dwc_otg_hcd->core_if->hc_xfer_timer[i]);
+#endif
+
+ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, channel);
+ }
+
+ /* Initialize the Connection timeout timer. */
+ init_timer( &dwc_otg_hcd->conn_timer );
+
+ /* Initialize reset tasklet. */
+ host20_reset_tasklet.data = (unsigned long) dwc_otg_hcd;
+ dwc_otg_hcd->reset_tasklet = &host20_reset_tasklet;
+ /*
+ * Finish generic HCD initialization and start the HCD. This function
+ * allocates the DMA buffer pool, registers the USB bus, requests the
+ * IRQ line, and calls dwc_otg_hcd_start method.
+ */
+ retval = usb_add_hcd(hcd, platform_get_irq(to_platform_device(dev), 0),
+ IRQF_SHARED);
+ if (retval < 0) {
+ DWC_ERROR("usb_add_hcd fail,everest\n");
+ goto error2;
+ }
+ /*
+ * Allocate space for storing data on status transactions. Normally no
+ * data is sent, but this space acts as a bit bucket. This must be
+ * done after usb_add_hcd since that function allocates the DMA buffer
+ * pool.
+ */
+ if (otg_dev->core_if->dma_enable) {
+ dwc_otg_hcd->status_buf =
+ dma_alloc_coherent(dev,
+ DWC_OTG_HCD_STATUS_BUF_SIZE,
+ &dwc_otg_hcd->status_buf_dma,
+ GFP_KERNEL | GFP_DMA);
+ } else {
+ dwc_otg_hcd->status_buf = kmalloc(DWC_OTG_HCD_STATUS_BUF_SIZE,
+ GFP_KERNEL);
+ }
+ if (dwc_otg_hcd->status_buf == NULL) {
+ retval = -ENOMEM;
+ DWC_ERROR("%s: status_buf allocation failed\n", __func__);
+ goto error3;
+ }
+
+
+ return 0;
+
+ /* Error conditions */
+ error3:
+ usb_remove_hcd(hcd);
+ error2:
+ dwc_otg_hcd_free(hcd);
+ usb_put_hcd(hcd);
+
+ error1:
+ DWC_PRINT("dwc_otg_hcd_init error,everest\n");
return retval;
}
#endif
+
/**
* Removes the HCD.
* Frees memory and resources associated with the HCD and deregisters the bus.
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
unsigned long flags;
- struct usb_device *udev;
struct usb_bus *bus;
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
-#if 0
- unsigned int regvalue;
- printk("__________________________________________________________________\n");
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gotgctl);
- printk("gotgctl is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gotgint);
- printk("gotgint is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gahbcfg);
- printk("gahbcfg is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gusbcfg);
- printk("gusbcfg is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grstctl);
- printk("grstctl is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts);
- printk("gintsts is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk);
- printk("gintmsk is %08x\n",regvalue);
- regvalue = dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->gotgctl);
- printk("gotgctl is %08x\n",regvalue);
- printk("__________________________________________________________________\n");
-#endif
- DWC_PRINT("dwc_otg_hcd_start! everest\n");
+
bus = hcd_to_bus(_hcd);
_hcd->state = HC_STATE_RUNNING;
usb_hcd_resume_root_hub(_hcd);
}
else {
+ /*
+ * no use
+ * yk@rk 2010121
+ struct usb_device *udev;6
udev = usb_alloc_dev(NULL, bus, 0);
udev->speed = USB_SPEED_HIGH;
if (!udev) {
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Error udev alloc\n");
return -ENODEV;
}
-
+ */
/* Not needed - VJ
if ((retval = usb_hcd_register_root_hub(udev, _hcd)) != 0) {
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Error registering %d\n", retval);
}
/* Initialize the bus state. If the core is in Device Mode
* HALT the USB bus and return. */
- if (dwc_otg_is_device_mode (core_if)) {
- printk("dwc_otg_hcd_start controller in device mode,everest\n");
+ if (!dwc_otg_hcd->host_enabled || dwc_otg_is_device_mode (core_if)) {
+ DWC_PRINT("dwc_otg_hcd_start controller in device mode,everest\n");
//_hcd->state = HC_STATE_HALT;
goto out;
}
#ifdef DEBUG
static void dump_urb_info(struct urb *_urb, char* _fn_name)
{
- DWC_PRINT("%s, urb %p,%x\n", _fn_name, _urb,_urb);
DWC_PRINT(" Device address: %d\n", usb_pipedevice(_urb->pipe));
DWC_PRINT(" Endpoint: %d, %s\n", usb_pipeendpoint(_urb->pipe),
(usb_pipein(_urb->pipe) ? "IN" : "OUT"));
dwc_otg_hcd_t * dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);
dwc_otg_qtd_t * qtd;
unsigned long flags;
-
+#if 0
retval = usb_hcd_link_urb_to_ep(_hcd, _urb);
if (retval)
{
- printk("%s, usb_hcd_link_urb_to_ep error\n", __func__);
+ DWC_PRINT("%s, usb_hcd_link_urb_to_ep error\n", __func__);
return retval;
}
+#endif
spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
#if 1
/*
dwc_otg_qtd_t * urb_qtd;
dwc_otg_qh_t * qh;
struct usb_host_endpoint *_ep = _urb->ep;//dwc_urb_to_endpoint(_urb);
- int retval;
+ //int retval;
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
urb_qtd = (dwc_otg_qtd_t *) _urb->hcpriv;
if(_ep==NULL)
{
- printk("%s=====================================================\n",__func__);
- printk("urb->ep is null\n");
+ DWC_PRINT("%s=====================================================\n",__func__);
+ DWC_PRINT("urb->ep is null\n");
return -1;
}
qh = (dwc_otg_qh_t *) _ep->hcpriv;
spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
+ #if 0
retval = usb_hcd_check_unlink_urb(_hcd, _urb, _status);
if (retval) {
spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
return retval;
}
-
+ #endif
+ if(urb_qtd == NULL)
+ {
+ DWC_PRINT("%s,urb_qtd is null\n",__func__);
+ goto urb_qtd_null;
+ //return -1;
+ }
dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);
#ifdef DEBUG
dwc_otg_hcd_qh_remove(dwc_otg_hcd, qh);
}
#endif
+
+urb_qtd_null:
spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
_urb->hcpriv = NULL;
- usb_hcd_unlink_urb_from_ep(_hcd, _urb);
+ //usb_hcd_unlink_urb_from_ep(_hcd, _urb);
/* Higher layer software sets URB status. */
usb_hcd_giveback_urb(_hcd, _urb, _status);
if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
port_status |= (1 << USB_PORT_FEAT_POWER);
if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
- port_status |= (1 << USB_PORT_FEAT_HIGHSPEED);
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
- port_status |= (1 << USB_PORT_FEAT_LOWSPEED);
+ port_status |= USB_PORT_STAT_LOW_SPEED;
if (hprt0.b.prttstctl)
port_status |= (1 << USB_PORT_FEAT_TEST);
hprt0.b.prtrst = 1;
dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
}
+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
- MDELAY (60);
+ // kever @rk 20110712
+ // can not use mdelay(60) while irq disable
+ //MDELAY (60);
+ msleep(60);
+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
hprt0.b.prtrst = 0;
dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
break;
if (urb->dev->speed == USB_SPEED_LOW) {
hc->speed = DWC_OTG_EP_SPEED_LOW;
+ /*
+ * yk@rk 20101216 fix bandwidth check error when full/low speed
+ * device connected.
+ */
+ _hcd->core_if->core_params->speed = DWC_SPEED_PARAM_FULL;
} else if (urb->dev->speed == USB_SPEED_FULL) {
hc->speed = DWC_OTG_EP_SPEED_FULL;
+ /*
+ * yk@rk 20101216 fix bandwidth check error when full/low speed
+ * device connected. warning: only support 1 device at root hub.
+ */
+ _hcd->core_if->core_params->speed = DWC_SPEED_PARAM_FULL;
} else {
hc->speed = DWC_OTG_EP_SPEED_HIGH;
}
* periodic assigned schedule.
*/
qh_ptr = qh_ptr->next;
- list_move(&qh->qh_list_entry, &_hcd->periodic_sched_assigned);
+ list_move_tail(&qh->qh_list_entry, &_hcd->periodic_sched_assigned);
ret_val = DWC_OTG_TRANSACTION_PERIODIC;
}
num_channels - _hcd->periodic_channels) &&
*/
!list_empty(&_hcd->free_hc_list)) {
-
- if((num_channels > 2)&&(_hcd->non_periodic_channels >=
- num_channels - _hcd->periodic_channels))
- break;
qh = list_entry(qh_ptr, dwc_otg_qh_t, qh_list_entry);
assign_and_init_hc(_hcd, qh);
* non-periodic active schedule.
*/
qh_ptr = qh_ptr->next;
- list_move(&qh->qh_list_entry, &_hcd->non_periodic_sched_active);
+ list_move_tail(&qh->qh_list_entry, &_hcd->non_periodic_sched_active);
if (ret_val == DWC_OTG_TRANSACTION_NONE) {
ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
* Move the QH from the periodic assigned schedule to
* the periodic queued schedule.
*/
- list_move(&qh->qh_list_entry, &_hcd->periodic_sched_queued);
+ list_move_tail(&qh->qh_list_entry, &_hcd->periodic_sched_queued);
/* done queuing high bandwidth */
_hcd->core_if->queuing_high_bandwidth = 0;
_urb->hcpriv = NULL;
- usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(_hcd), _urb);
+ //usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(_hcd), _urb);
spin_unlock(&_hcd->lock);
usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(_hcd), _urb, _status);
spin_lock(&_hcd->lock);
}
-
+void dwc_otg_clear_halt(struct urb *_urb)
+{
+ struct dwc_otg_qh *_qh;
+ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(_urb);
+ if((ep)&&(ep->hcpriv))
+ {
+ _qh = (dwc_otg_qh_t *) ep->hcpriv;
+ _qh->data_toggle = 0;
+ }
+}
/*
* Returns the Queue Head for an URB.
*/