From 1b0bbff0075a8b08a010d2c9fa0616a6375967c6 Mon Sep 17 00:00:00 2001 From: Matt Evans Date: Tue, 29 Mar 2011 13:40:46 +1100 Subject: [PATCH] --- yaml --- r: 248788 b: refs/heads/master c: 28ccd2962c66556d7037b2d9f1c11cdcd3b805d5 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/usb/Makefile | 1 - trunk/drivers/usb/gadget/fsl_udc_core.c | 411 +----- trunk/drivers/usb/gadget/fsl_usb2_udc.h | 6 - trunk/drivers/usb/gadget/s3c-hsotg.c | 226 ++-- trunk/drivers/usb/host/ehci-fsl.c | 219 ---- trunk/drivers/usb/host/ehci-fsl.h | 4 - trunk/drivers/usb/host/ehci-hub.c | 8 - trunk/drivers/usb/host/ehci.h | 4 - trunk/drivers/usb/host/isp1760-hcd.c | 1582 ++++++++++++----------- trunk/drivers/usb/host/isp1760-hcd.h | 78 +- trunk/drivers/usb/host/xhci-dbg.c | 51 +- trunk/drivers/usb/host/xhci-hub.c | 18 +- trunk/drivers/usb/host/xhci-mem.c | 122 +- trunk/drivers/usb/host/xhci-ring.c | 267 ++-- trunk/drivers/usb/host/xhci.c | 109 +- trunk/drivers/usb/host/xhci.h | 134 +- trunk/drivers/usb/misc/usbtest.c | 5 - trunk/drivers/usb/otg/Kconfig | 8 - trunk/drivers/usb/otg/Makefile | 2 - trunk/drivers/usb/otg/fsl_otg.c | 1169 ----------------- trunk/drivers/usb/otg/fsl_otg.h | 406 ------ trunk/drivers/usb/otg/isp1301_omap.c | 26 +- trunk/drivers/usb/otg/langwell_otg.c | 40 +- trunk/drivers/usb/otg/otg.c | 35 - trunk/drivers/usb/otg/otg_fsm.c | 349 ----- trunk/drivers/usb/otg/otg_fsm.h | 154 --- trunk/include/linux/fsl_devices.h | 16 - trunk/include/linux/usb/otg.h | 1 - 29 files changed, 1475 insertions(+), 3978 deletions(-) delete mode 100644 trunk/drivers/usb/otg/fsl_otg.c delete mode 100644 trunk/drivers/usb/otg/fsl_otg.h delete mode 100644 trunk/drivers/usb/otg/otg_fsm.c delete mode 100644 trunk/drivers/usb/otg/otg_fsm.h diff --git a/[refs] b/[refs] index b85d3f01b24e..fe3cf5b44a48 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 71a9f9d268a5c2b0a80ae606cf8e502f3410a5df +refs/heads/master: 28ccd2962c66556d7037b2d9f1c11cdcd3b805d5 diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index 30ddf8dc4f72..9bc8aeb3c96f 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_IMX21_HCD) += host/ -obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/trunk/drivers/usb/gadget/fsl_udc_core.c b/trunk/drivers/usb/gadget/fsl_udc_core.c index 999eafe89653..07499c1cdcc4 100644 --- a/trunk/drivers/usb/gadget/fsl_udc_core.c +++ b/trunk/drivers/usb/gadget/fsl_udc_core.c @@ -6,7 +6,7 @@ * * Description: * Freescale high-speed USB SOC DR module device controller driver. - * This can be found on MPC8349E/MPC8313E/MPC5121E cpus. + * This can be found on MPC8349E/MPC8313E cpus. * The driver is previously named as mpc_udc. Based on bare board * code from Dave Liu and Shlomi Gridish. * @@ -45,7 +45,6 @@ #include #include #include -#include #include "fsl_usb2_udc.h" @@ -78,64 +77,12 @@ fsl_ep0_desc = { static void fsl_ep_fifo_flush(struct usb_ep *_ep); #ifdef CONFIG_PPC32 -/* - * On some SoCs, the USB controller registers can be big or little endian, - * depending on the version of the chip. In order to be able to run the - * same kernel binary on 2 different versions of an SoC, the BE/LE decision - * must be made at run time. _fsl_readl and fsl_writel are pointers to the - * BE or LE readl() and writel() functions, and fsl_readl() and fsl_writel() - * call through those pointers. Platform code for SoCs that have BE USB - * registers should set pdata->big_endian_mmio flag. - * - * This also applies to controller-to-cpu accessors for the USB descriptors, - * since their endianness is also SoC dependant. Platform code for SoCs that - * have BE USB descriptors should set pdata->big_endian_desc flag. - */ -static u32 _fsl_readl_be(const unsigned __iomem *p) -{ - return in_be32(p); -} - -static u32 _fsl_readl_le(const unsigned __iomem *p) -{ - return in_le32(p); -} - -static void _fsl_writel_be(u32 v, unsigned __iomem *p) -{ - out_be32(p, v); -} - -static void _fsl_writel_le(u32 v, unsigned __iomem *p) -{ - out_le32(p, v); -} - -static u32 (*_fsl_readl)(const unsigned __iomem *p); -static void (*_fsl_writel)(u32 v, unsigned __iomem *p); - -#define fsl_readl(p) (*_fsl_readl)((p)) -#define fsl_writel(v, p) (*_fsl_writel)((v), (p)) - -static inline u32 cpu_to_hc32(const u32 x) -{ - return udc_controller->pdata->big_endian_desc - ? (__force u32)cpu_to_be32(x) - : (__force u32)cpu_to_le32(x); -} - -static inline u32 hc32_to_cpu(const u32 x) -{ - return udc_controller->pdata->big_endian_desc - ? be32_to_cpu((__force __be32)x) - : le32_to_cpu((__force __le32)x); -} -#else /* !CONFIG_PPC32 */ +#define fsl_readl(addr) in_le32(addr) +#define fsl_writel(val32, addr) out_le32(addr, val32) +#else #define fsl_readl(addr) readl(addr) #define fsl_writel(val32, addr) writel(val32, addr) -#define cpu_to_hc32(x) cpu_to_le32(x) -#define hc32_to_cpu(x) le32_to_cpu(x) -#endif /* CONFIG_PPC32 */ +#endif /******************************************************************** * Internal Used Function @@ -279,12 +226,9 @@ static int dr_controller_setup(struct fsl_udc *udc) /* Set the controller as device mode */ tmp = fsl_readl(&dr_regs->usbmode); - tmp &= ~USB_MODE_CTRL_MODE_MASK; /* clear mode bits */ tmp |= USB_MODE_CTRL_MODE_DEVICE; /* Disable Setup Lockout */ tmp |= USB_MODE_SETUP_LOCK_OFF; - if (udc->pdata->es) - tmp |= USB_MODE_ES; fsl_writel(tmp, &dr_regs->usbmode); /* Clear the setup status */ @@ -300,24 +244,20 @@ static int dr_controller_setup(struct fsl_udc *udc) /* Config control enable i/o output, cpu endian register */ #ifndef CONFIG_ARCH_MXC - if (udc->pdata->have_sysif_regs) { - ctrl = __raw_readl(&usb_sys_regs->control); - ctrl |= USB_CTRL_IOENB; - __raw_writel(ctrl, &usb_sys_regs->control); - } + ctrl = __raw_readl(&usb_sys_regs->control); + ctrl |= USB_CTRL_IOENB; + __raw_writel(ctrl, &usb_sys_regs->control); #endif #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) /* Turn on cache snooping hardware, since some PowerPC platforms * wholly rely on hardware to deal with cache coherent. */ - if (udc->pdata->have_sysif_regs) { - /* Setup Snooping for all the 4GB space */ - tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */ - __raw_writel(tmp, &usb_sys_regs->snoop1); - tmp |= 0x80000000; /* starts from 0x8000000, size 2G */ - __raw_writel(tmp, &usb_sys_regs->snoop2); - } + /* Setup Snooping for all the 4GB space */ + tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */ + __raw_writel(tmp, &usb_sys_regs->snoop1); + tmp |= 0x80000000; /* starts from 0x8000000, size 2G */ + __raw_writel(tmp, &usb_sys_regs->snoop2); #endif return 0; @@ -353,19 +293,6 @@ static void dr_controller_stop(struct fsl_udc *udc) { unsigned int tmp; - pr_debug("%s\n", __func__); - - /* if we're in OTG mode, and the Host is currently using the port, - * stop now and don't rip the controller out from under the - * ehci driver - */ - if (udc->gadget.is_otg) { - if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) { - pr_debug("udc: Leaving early\n"); - return; - } - } - /* disable all INTR */ fsl_writel(0, &dr_regs->usbintr); @@ -482,7 +409,7 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num, if (zlt) tmp |= EP_QUEUE_HEAD_ZLT_SEL; - p_QH->max_pkt_length = cpu_to_hc32(tmp); + p_QH->max_pkt_length = cpu_to_le32(tmp); p_QH->next_dtd_ptr = 1; p_QH->size_ioc_int_sts = 0; } @@ -689,7 +616,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) struct fsl_req *lastreq; lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); lastreq->tail->next_td_ptr = - cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); + cpu_to_le32(req->head->td_dma & DTD_ADDR_MASK); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) goto out; @@ -714,10 +641,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) /* Write dQH next pointer and terminate bit to 0 */ temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; - dQH->next_dtd_ptr = cpu_to_hc32(temp); + dQH->next_dtd_ptr = cpu_to_le32(temp); /* Clear active and halt bit */ - temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE + temp = cpu_to_le32(~(EP_QUEUE_HEAD_STATUS_ACTIVE | EP_QUEUE_HEAD_STATUS_HALT)); dQH->size_ioc_int_sts &= temp; @@ -755,17 +682,17 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, dtd->td_dma = *dma; /* Clear reserved field */ - swap_temp = hc32_to_cpu(dtd->size_ioc_sts); + swap_temp = cpu_to_le32(dtd->size_ioc_sts); swap_temp &= ~DTD_RESERVED_FIELDS; - dtd->size_ioc_sts = cpu_to_hc32(swap_temp); + dtd->size_ioc_sts = cpu_to_le32(swap_temp); /* Init all of buffer page pointers */ swap_temp = (u32) (req->req.dma + req->req.actual); - dtd->buff_ptr0 = cpu_to_hc32(swap_temp); - dtd->buff_ptr1 = cpu_to_hc32(swap_temp + 0x1000); - dtd->buff_ptr2 = cpu_to_hc32(swap_temp + 0x2000); - dtd->buff_ptr3 = cpu_to_hc32(swap_temp + 0x3000); - dtd->buff_ptr4 = cpu_to_hc32(swap_temp + 0x4000); + dtd->buff_ptr0 = cpu_to_le32(swap_temp); + dtd->buff_ptr1 = cpu_to_le32(swap_temp + 0x1000); + dtd->buff_ptr2 = cpu_to_le32(swap_temp + 0x2000); + dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000); + dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000); req->req.actual += *length; @@ -789,7 +716,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, if (*is_last && !req->req.no_interrupt) swap_temp |= DTD_IOC; - dtd->size_ioc_sts = cpu_to_hc32(swap_temp); + dtd->size_ioc_sts = cpu_to_le32(swap_temp); mb(); @@ -816,7 +743,7 @@ static int fsl_req_to_dtd(struct fsl_req *req) is_first = 0; req->head = dtd; } else { - last_dtd->next_td_ptr = cpu_to_hc32(dma); + last_dtd->next_td_ptr = cpu_to_le32(dma); last_dtd->next_td_virt = dtd; } last_dtd = dtd; @@ -824,7 +751,7 @@ static int fsl_req_to_dtd(struct fsl_req *req) req->dtd_count++; } while (!is_last); - dtd->next_td_ptr = cpu_to_hc32(DTD_NEXT_TERMINATE); + dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE); req->tail = dtd; @@ -1035,36 +962,6 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value) return status; } -static int fsl_ep_fifo_status(struct usb_ep *_ep) -{ - struct fsl_ep *ep; - struct fsl_udc *udc; - int size = 0; - u32 bitmask; - struct ep_queue_head *d_qh; - - ep = container_of(_ep, struct fsl_ep, ep); - if (!_ep || (!ep->desc && ep_index(ep) != 0)) - return -ENODEV; - - udc = (struct fsl_udc *)ep->udc; - - if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) - return -ESHUTDOWN; - - d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)]; - - bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) : - (1 << (ep_index(ep))); - - if (fsl_readl(&dr_regs->endptstatus) & bitmask) - size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE) - >> DTD_LENGTH_BIT_POS; - - pr_debug("%s %u\n", __func__, size); - return size; -} - static void fsl_ep_fifo_flush(struct usb_ep *_ep) { struct fsl_ep *ep; @@ -1117,7 +1014,6 @@ static struct usb_ep_ops fsl_ep_ops = { .dequeue = fsl_ep_dequeue, .set_halt = fsl_ep_set_halt, - .fifo_status = fsl_ep_fifo_status, .fifo_flush = fsl_ep_fifo_flush, /* flush fifo */ }; @@ -1332,10 +1228,6 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req = udc->status_req; /* Fill in the reqest structure */ *((u16 *) req->req.buf) = cpu_to_le16(tmp); - - /* flush cache for the req buffer */ - flush_dcache_range((u32)req->req.buf, (u32)req->req.buf + 8); - req->ep = ep; req->req.length = 2; req->req.status = -EINPROGRESS; @@ -1388,7 +1280,6 @@ static void setup_received_irq(struct fsl_udc *udc, /* Status phase from udc */ { int rc = -EOPNOTSUPP; - u16 ptc = 0; if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { @@ -1410,19 +1301,17 @@ static void setup_received_irq(struct fsl_udc *udc, | USB_TYPE_STANDARD)) { /* Note: The driver has not include OTG support yet. * This will be set when OTG support is added */ - if (wValue == USB_DEVICE_TEST_MODE) - ptc = wIndex >> 8; - else if (gadget_is_otg(&udc->gadget)) { - if (setup->bRequest == - USB_DEVICE_B_HNP_ENABLE) - udc->gadget.b_hnp_enable = 1; - else if (setup->bRequest == - USB_DEVICE_A_HNP_SUPPORT) - udc->gadget.a_hnp_support = 1; - else if (setup->bRequest == - USB_DEVICE_A_ALT_HNP_SUPPORT) - udc->gadget.a_alt_hnp_support = 1; - } + if (!gadget_is_otg(&udc->gadget)) + break; + else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) + udc->gadget.b_hnp_enable = 1; + else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) + udc->gadget.a_hnp_support = 1; + else if (setup->bRequest == + USB_DEVICE_A_ALT_HNP_SUPPORT) + udc->gadget.a_alt_hnp_support = 1; + else + break; rc = 0; } else break; @@ -1431,15 +1320,6 @@ static void setup_received_irq(struct fsl_udc *udc, if (ep0_prime_status(udc, EP_DIR_IN)) ep0stall(udc); } - if (ptc) { - u32 tmp; - - mdelay(10); - tmp = fsl_readl(&dr_regs->portsc1) | (ptc << 16); - fsl_writel(tmp, &dr_regs->portsc1); - printk(KERN_INFO "udc: switch to test mode %d.\n", ptc); - } - return; } @@ -1514,7 +1394,6 @@ static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr) { u32 temp; struct ep_queue_head *qh; - struct fsl_usb2_platform_data *pdata = udc->pdata; qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT]; @@ -1529,16 +1408,7 @@ static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr) fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd); /* Copy the setup packet to local buffer */ - if (pdata->le_setup_buf) { - u32 *p = (u32 *)buffer_ptr; - u32 *s = (u32 *)qh->setup_buffer; - - /* Convert little endian setup buffer to CPU endian */ - *p++ = le32_to_cpu(*s++); - *p = le32_to_cpu(*s); - } else { - memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8); - } + memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8); } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW)); /* Clear Setup Tripwire */ @@ -1562,19 +1432,19 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, actual = curr_req->req.length; for (j = 0; j < curr_req->dtd_count; j++) { - remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts) + remaining_length = (le32_to_cpu(curr_td->size_ioc_sts) & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS; actual -= remaining_length; - errors = hc32_to_cpu(curr_td->size_ioc_sts); - if (errors & DTD_ERROR_MASK) { + if ((errors = le32_to_cpu(curr_td->size_ioc_sts) & + DTD_ERROR_MASK)) { if (errors & DTD_STATUS_HALTED) { ERR("dTD error %08x QH=%d\n", errors, pipe); /* Clear the errors and Halt condition */ - tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts); + tmp = le32_to_cpu(curr_qh->size_ioc_int_sts); tmp &= ~errors; - curr_qh->size_ioc_int_sts = cpu_to_hc32(tmp); + curr_qh->size_ioc_int_sts = cpu_to_le32(tmp); status = -EPIPE; /* FIXME: continue with next queued TD? */ @@ -1592,7 +1462,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, ERR("Unknown error has occurred (0x%x)!\n", errors); - } else if (hc32_to_cpu(curr_td->size_ioc_sts) + } else if (le32_to_cpu(curr_td->size_ioc_sts) & DTD_STATUS_ACTIVE) { VDBG("Request not complete"); status = REQ_UNCOMPLETE; @@ -1681,9 +1551,6 @@ static void port_change_irq(struct fsl_udc *udc) { u32 speed; - if (udc->bus_reset) - udc->bus_reset = 0; - /* Bus resetting is finished */ if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { /* Get the speed */ @@ -1791,8 +1658,6 @@ static void reset_irq(struct fsl_udc *udc) if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) { VDBG("Bus reset"); - /* Bus is reseting */ - udc->bus_reset = 1; /* Reset all the queues, include XD, dTD, EP queue * head and TR Queue */ reset_queues(udc); @@ -1870,7 +1735,6 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc) /* Reset Received */ if (irq_src & USB_STS_RESET) { - VDBG("reset int"); reset_irq(udc); status = IRQ_HANDLED; } @@ -1928,30 +1792,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, goto out; } - if (udc_controller->transceiver) { - /* Suspend the controller until OTG enable it */ - udc_controller->stopped = 1; - printk(KERN_INFO "Suspend udc for OTG auto detect\n"); - - /* connect to bus through transceiver */ - if (udc_controller->transceiver) { - retval = otg_set_peripheral(udc_controller->transceiver, - &udc_controller->gadget); - if (retval < 0) { - ERR("can't bind to transceiver\n"); - driver->unbind(&udc_controller->gadget); - udc_controller->gadget.dev.driver = 0; - udc_controller->driver = 0; - return retval; - } - } - } else { - /* Enable DR IRQ reg and set USBCMD reg Run bit */ - dr_controller_run(udc_controller); - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; - } + /* Enable DR IRQ reg and Set usbcmd reg Run bit */ + dr_controller_run(udc_controller); + udc_controller->usb_state = USB_STATE_ATTACHED; + udc_controller->ep0_state = WAIT_FOR_SETUP; + udc_controller->ep0_dir = 0; printk(KERN_INFO "%s: bind to driver %s\n", udc_controller->gadget.name, driver->driver.name); @@ -2199,18 +2044,16 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, next += t; #ifndef CONFIG_ARCH_MXC - if (udc->pdata->have_sysif_regs) { - tmp_reg = usb_sys_regs->snoop1; - t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg); - size -= t; - next += t; + tmp_reg = usb_sys_regs->snoop1; + t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg); + size -= t; + next += t; - tmp_reg = usb_sys_regs->control; - t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n", - tmp_reg); - size -= t; - next += t; - } + tmp_reg = usb_sys_regs->control; + t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n", + tmp_reg); + size -= t; + next += t; #endif /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */ @@ -2390,7 +2233,6 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index, */ static int __init fsl_udc_probe(struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata; struct resource *res; int ret = -ENODEV; unsigned int i; @@ -2407,35 +2249,20 @@ static int __init fsl_udc_probe(struct platform_device *pdev) return -ENOMEM; } - pdata = pdev->dev.platform_data; - udc_controller->pdata = pdata; spin_lock_init(&udc_controller->lock); udc_controller->stopped = 1; -#ifdef CONFIG_USB_OTG - if (pdata->operating_mode == FSL_USB2_DR_OTG) { - udc_controller->transceiver = otg_get_transceiver(); - if (!udc_controller->transceiver) { - ERR("Can't find OTG driver!\n"); - ret = -ENODEV; - goto err_kfree; - } - } -#endif - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENXIO; goto err_kfree; } - if (pdata->operating_mode == FSL_USB2_DR_DEVICE) { - if (!request_mem_region(res->start, res->end - res->start + 1, - driver_name)) { - ERR("request mem region for %s failed\n", pdev->name); - ret = -EBUSY; - goto err_kfree; - } + if (!request_mem_region(res->start, res->end - res->start + 1, + driver_name)) { + ERR("request mem region for %s failed\n", pdev->name); + ret = -EBUSY; + goto err_kfree; } dr_regs = ioremap(res->start, resource_size(res)); @@ -2444,29 +2271,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) goto err_release_mem_region; } - pdata->regs = (void *)dr_regs; - - /* - * do platform specific init: check the clock, grab/config pins, etc. - */ - if (pdata->init && pdata->init(pdev)) { - ret = -ENODEV; - goto err_iounmap_noclk; - } - - /* Set accessors only after pdata->init() ! */ - if (pdata->big_endian_mmio) { - _fsl_readl = _fsl_readl_be; - _fsl_writel = _fsl_writel_be; - } else { - _fsl_readl = _fsl_readl_le; - _fsl_writel = _fsl_writel_le; - } - #ifndef CONFIG_ARCH_MXC - if (pdata->have_sysif_regs) - usb_sys_regs = (struct usb_sys_interface *) - ((u32)dr_regs + USB_DR_SYS_OFFSET); + usb_sys_regs = (struct usb_sys_interface *) + ((u32)dr_regs + USB_DR_SYS_OFFSET); #endif /* Initialize USB clocks */ @@ -2506,11 +2313,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) goto err_free_irq; } - if (!udc_controller->transceiver) { - /* initialize usb hw reg except for regs for EP, - * leave usbintr reg untouched */ - dr_controller_setup(udc_controller); - } + /* initialize usb hw reg except for regs for EP, + * leave usbintr reg untouched */ + dr_controller_setup(udc_controller); fsl_udc_clk_finalize(pdev); @@ -2530,9 +2335,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) if (ret < 0) goto err_free_irq; - if (udc_controller->transceiver) - udc_controller->gadget.is_otg = 1; - /* setup QH and epctrl for ep0 */ ep0_setup(udc_controller); @@ -2571,14 +2373,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev) err_free_irq: free_irq(udc_controller->irq, udc_controller); err_iounmap: - if (pdata->exit) - pdata->exit(pdev); fsl_udc_clk_release(); err_iounmap_noclk: iounmap(dr_regs); err_release_mem_region: - if (pdata->operating_mode == FSL_USB2_DR_DEVICE) - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, res->end - res->start + 1); err_kfree: kfree(udc_controller); udc_controller = NULL; @@ -2591,7 +2390,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) static int __exit fsl_udc_remove(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; DECLARE_COMPLETION(done); @@ -2612,20 +2410,12 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) dma_pool_destroy(udc_controller->td_pool); free_irq(udc_controller->irq, udc_controller); iounmap(dr_regs); - if (pdata->operating_mode == FSL_USB2_DR_DEVICE) - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, res->end - res->start + 1); device_unregister(&udc_controller->gadget.dev); /* free udc --wait for the release() finished */ wait_for_completion(&done); - /* - * do platform specific un-initialization: - * release iomux pins, etc. - */ - if (pdata->exit) - pdata->exit(pdev); - return 0; } @@ -2656,62 +2446,6 @@ static int fsl_udc_resume(struct platform_device *pdev) return 0; } -static int fsl_udc_otg_suspend(struct device *dev, pm_message_t state) -{ - struct fsl_udc *udc = udc_controller; - u32 mode, usbcmd; - - mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK; - - pr_debug("%s(): mode 0x%x stopped %d\n", __func__, mode, udc->stopped); - - /* - * If the controller is already stopped, then this must be a - * PM suspend. Remember this fact, so that we will leave the - * controller stopped at PM resume time. - */ - if (udc->stopped) { - pr_debug("gadget already stopped, leaving early\n"); - udc->already_stopped = 1; - return 0; - } - - if (mode != USB_MODE_CTRL_MODE_DEVICE) { - pr_debug("gadget not in device mode, leaving early\n"); - return 0; - } - - /* stop the controller */ - usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP; - fsl_writel(usbcmd, &dr_regs->usbcmd); - - udc->stopped = 1; - - pr_info("USB Gadget suspended\n"); - - return 0; -} - -static int fsl_udc_otg_resume(struct device *dev) -{ - pr_debug("%s(): stopped %d already_stopped %d\n", __func__, - udc_controller->stopped, udc_controller->already_stopped); - - /* - * If the controller was stopped at suspend time, then - * don't resume it now. - */ - if (udc_controller->already_stopped) { - udc_controller->already_stopped = 0; - pr_debug("gadget was already stopped, leaving early\n"); - return 0; - } - - pr_info("USB Gadget resume\n"); - - return fsl_udc_resume(NULL); -} - /*------------------------------------------------------------------------- Register entry point for the peripheral controller driver --------------------------------------------------------------------------*/ @@ -2724,9 +2458,6 @@ static struct platform_driver udc_driver = { .driver = { .name = (char *)driver_name, .owner = THIS_MODULE, - /* udc suspend/resume called from OTG driver */ - .suspend = fsl_udc_otg_suspend, - .resume = fsl_udc_otg_resume, }, }; diff --git a/trunk/drivers/usb/gadget/fsl_usb2_udc.h b/trunk/drivers/usb/gadget/fsl_usb2_udc.h index 1d51be83fda8..e88cce5c2c0d 100644 --- a/trunk/drivers/usb/gadget/fsl_usb2_udc.h +++ b/trunk/drivers/usb/gadget/fsl_usb2_udc.h @@ -275,9 +275,7 @@ struct usb_sys_interface { #define USB_MODE_CTRL_MODE_IDLE 0x00000000 #define USB_MODE_CTRL_MODE_DEVICE 0x00000002 #define USB_MODE_CTRL_MODE_HOST 0x00000003 -#define USB_MODE_CTRL_MODE_MASK 0x00000003 #define USB_MODE_CTRL_MODE_RSV 0x00000001 -#define USB_MODE_ES 0x00000004 /* Endian Select */ #define USB_MODE_SETUP_LOCK_OFF 0x00000008 #define USB_MODE_STREAM_DISABLE 0x00000010 /* Endpoint Flush Register */ @@ -463,7 +461,6 @@ struct fsl_ep { struct fsl_udc { struct usb_gadget gadget; struct usb_gadget_driver *driver; - struct fsl_usb2_platform_data *pdata; struct completion *done; /* to make sure release() is done */ struct fsl_ep *eps; unsigned int max_ep; @@ -476,8 +473,6 @@ struct fsl_udc { unsigned vbus_active:1; unsigned stopped:1; unsigned remote_wakeup:1; - unsigned already_stopped:1; - unsigned big_endian_desc:1; struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */ struct fsl_req *status_req; /* ep0 status request */ @@ -488,7 +483,6 @@ struct fsl_udc { dma_addr_t ep_qh_dma; /* dma address of QH */ u32 max_pipes; /* Device max pipes */ - u32 bus_reset; /* Device is bus resetting */ u32 resume_state; /* USB state to resume */ u32 usb_state; /* USB current state */ u32 ep0_state; /* Endpoint zero state */ diff --git a/trunk/drivers/usb/gadget/s3c-hsotg.c b/trunk/drivers/usb/gadget/s3c-hsotg.c index baf96ce16b6a..0912679de99a 100644 --- a/trunk/drivers/usb/gadget/s3c-hsotg.c +++ b/trunk/drivers/usb/gadget/s3c-hsotg.c @@ -1,7 +1,4 @@ /* linux/drivers/usb/gadget/s3c-hsotg.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics @@ -682,14 +679,6 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, __func__, readl(hsotg->regs + epctrl_reg), index, hs_ep->dir_in ? "in" : "out"); - /* If endpoint is stalled, we will restart request later */ - ctrl = readl(hsotg->regs + epctrl_reg); - - if (ctrl & S3C_DxEPCTL_Stall) { - dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); - return; - } - length = ureq->length - ureq->actual; if (0) @@ -742,6 +731,18 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, /* write size / packets */ writel(epsize, hsotg->regs + epsize_reg); + ctrl = readl(hsotg->regs + epctrl_reg); + + if (ctrl & S3C_DxEPCTL_Stall) { + dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); + + /* not sure what we can do here, if it is EP0 then we should + * get this cleared once the endpoint has transmitted the + * STALL packet, otherwise it needs to be cleared by the + * host. + */ + } + if (using_dma(hsotg)) { unsigned int dma_reg; @@ -1046,20 +1047,6 @@ static int s3c_hsotg_process_req_status(struct s3c_hsotg *hsotg, static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); -/** - * get_ep_head - return the first request on the endpoint - * @hs_ep: The controller endpoint to get - * - * Get the first request on the endpoint. - */ -static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) -{ - if (list_empty(&hs_ep->queue)) - return NULL; - - return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); -} - /** * s3c_hsotg_process_req_featire - process request {SET,CLEAR}_FEATURE * @hsotg: The device state @@ -1068,12 +1055,8 @@ static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, struct usb_ctrlrequest *ctrl) { - struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; - struct s3c_hsotg_req *hs_req; - bool restart; bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); struct s3c_hsotg_ep *ep; - int ret; dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", __func__, set ? "SET" : "CLEAR"); @@ -1089,36 +1072,6 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, switch (le16_to_cpu(ctrl->wValue)) { case USB_ENDPOINT_HALT: s3c_hsotg_ep_sethalt(&ep->ep, set); - - ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); - if (ret) { - dev_err(hsotg->dev, - "%s: failed to send reply\n", __func__); - return ret; - } - - if (!set) { - /* - * If we have request in progress, - * then complete it - */ - if (ep->req) { - hs_req = ep->req; - ep->req = NULL; - list_del_init(&hs_req->queue); - hs_req->req.complete(&ep->ep, - &hs_req->req); - } - - /* If we have pending request, then start it */ - restart = !list_empty(&ep->queue); - if (restart) { - hs_req = get_ep_head(ep); - s3c_hsotg_start_req(hsotg, ep, - hs_req, false); - } - } - break; default: @@ -1195,6 +1148,14 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); } + if (ret > 0) { + if (!ep0->dir_in) { + /* need to generate zlp in reply or take data */ + /* todo - deal with any data we might be sent? */ + ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); + } + } + /* the request is either unhandlable, or is not formatted correctly * so respond with a STALL for the status stage to indicate failure. */ @@ -1285,6 +1246,20 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) } } +/** + * get_ep_head - return the first request on the endpoint + * @hs_ep: The controller endpoint to get + * + * Get the first request on the endpoint. +*/ +static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) +{ + if (list_empty(&hs_ep->queue)) + return NULL; + + return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); +} + /** * s3c_hsotg_complete_request - complete a request given to us * @hsotg: The device state. @@ -1708,37 +1683,6 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, dev_err(hsotg->dev, "ep%d: bad mps of %d\n", ep, mps); } -/** - * s3c_hsotg_txfifo_flush - flush Tx FIFO - * @hsotg: The driver state - * @idx: The index for the endpoint (0..15) - */ -static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) -{ - int timeout; - int val; - - writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh, - hsotg->regs + S3C_GRSTCTL); - - /* wait until the fifo is flushed */ - timeout = 100; - - while (1) { - val = readl(hsotg->regs + S3C_GRSTCTL); - - if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0) - break; - - if (--timeout == 0) { - dev_err(hsotg->dev, - "%s: timeout flushing fifo (GRSTCTL=%08x)\n", - __func__, val); - } - - udelay(1); - } -} /** * s3c_hsotg_trytx - check to see if anything needs transmitting @@ -1831,12 +1775,10 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); u32 ints; + u32 clear = 0; ints = readl(hsotg->regs + epint_reg); - /* Clear endpoint interrupts */ - writel(ints, hsotg->regs + epint_reg); - dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", __func__, idx, dir_in ? "in" : "out", ints); @@ -1859,28 +1801,19 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, s3c_hsotg_handle_outdone(hsotg, idx, false); } + + clear |= S3C_DxEPINT_XferCompl; } if (ints & S3C_DxEPINT_EPDisbld) { dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); - - if (dir_in) { - int epctl = readl(hsotg->regs + epctl_reg); - - s3c_hsotg_txfifo_flush(hsotg, idx); - - if ((epctl & S3C_DxEPCTL_Stall) && - (epctl & S3C_DxEPCTL_EPType_Bulk)) { - int dctl = readl(hsotg->regs + S3C_DCTL); - - dctl |= S3C_DCTL_CGNPInNAK; - writel(dctl, hsotg->regs + S3C_DCTL); - } - } + clear |= S3C_DxEPINT_EPDisbld; } - if (ints & S3C_DxEPINT_AHBErr) + if (ints & S3C_DxEPINT_AHBErr) { dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); + clear |= S3C_DxEPINT_AHBErr; + } if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); @@ -1896,10 +1829,14 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, else s3c_hsotg_handle_outdone(hsotg, 0, true); } + + clear |= S3C_DxEPINT_Setup; } - if (ints & S3C_DxEPINT_Back2BackSetup) + if (ints & S3C_DxEPINT_Back2BackSetup) { dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); + clear |= S3C_DxEPINT_Back2BackSetup; + } if (dir_in) { /* not sure if this is important, but we'll clear it anyway @@ -1907,12 +1844,14 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", __func__, idx); + clear |= S3C_DIEPMSK_INTknTXFEmpMsk; } /* this probably means something bad is happening */ if (ints & S3C_DIEPMSK_INTknEPMisMsk) { dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", __func__, idx); + clear |= S3C_DIEPMSK_INTknEPMisMsk; } /* FIFO has space or is empty (see GAHBCFG) */ @@ -1921,8 +1860,11 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); s3c_hsotg_trytx(hsotg, hs_ep); + clear |= S3C_DIEPMSK_TxFIFOEmpty; } } + + writel(clear, hsotg->regs + epint_reg); } /** @@ -2114,6 +2056,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); writel(otgint, hsotg->regs + S3C_GOTGINT); + writel(S3C_GINTSTS_OTGInt, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_DisconnInt) { @@ -2129,9 +2072,8 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) } if (gintsts & S3C_GINTSTS_EnumDone) { - writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); - s3c_hsotg_irq_enumdone(hsotg); + writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_ConIDStsChng) { @@ -2159,6 +2101,10 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) if (daint_in & 1) s3c_hsotg_epint(hsotg, ep, 1); } + + writel(daint, hsotg->regs + S3C_DAINT); + writel(gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt), + hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_USBRst) { @@ -2166,8 +2112,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", readl(hsotg->regs + S3C_GNPTXSTS)); - writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); - kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); /* it seems after a reset we can end up with a situation @@ -2179,6 +2123,8 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) s3c_hsotg_init_fifo(hsotg); s3c_hsotg_enqueue_setup(hsotg); + + writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); } /* check both FIFOs */ @@ -2192,6 +2138,8 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, false); + + writel(S3C_GINTSTS_NPTxFEmp, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_PTxFEmp) { @@ -2201,6 +2149,8 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, true); + + writel(S3C_GINTSTS_PTxFEmp, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_RxFLvl) { @@ -2209,6 +2159,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) * set. */ s3c_hsotg_handle_rx(hsotg); + writel(S3C_GINTSTS_RxFLvl, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_ModeMis) { @@ -2242,17 +2193,19 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) if (gintsts & S3C_GINTSTS_GOUTNakEff) { dev_info(hsotg->dev, "GOUTNakEff triggered\n"); - writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); - s3c_hsotg_dump(hsotg); + + writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); + writel(S3C_GINTSTS_GOUTNakEff, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_GINNakEff) { dev_info(hsotg->dev, "GINNakEff triggered\n"); - writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); - s3c_hsotg_dump(hsotg); + + writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); + writel(S3C_GINTSTS_GINNakEff, hsotg->regs + S3C_GINTSTS); } /* if we've had fifo events, we should try and go around the @@ -2450,6 +2403,11 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); + if (hs_req == hs_ep->req) { + dev_dbg(hs->dev, "%s: already in progress\n", __func__); + return -EINPROGRESS; + } + spin_lock_irqsave(&hs_ep->lock, flags); if (!on_list(hs_ep, hs_req)) { @@ -2471,7 +2429,6 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) unsigned long irqflags; u32 epreg; u32 epctl; - u32 xfertype; dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); @@ -2482,17 +2439,10 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) epreg = S3C_DIEPCTL(index); epctl = readl(hs->regs + epreg); - if (value) { - epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK; - if (epctl & S3C_DxEPCTL_EPEna) - epctl |= S3C_DxEPCTL_EPDis; - } else { + if (value) + epctl |= S3C_DxEPCTL_Stall; + else epctl &= ~S3C_DxEPCTL_Stall; - xfertype = epctl & S3C_DxEPCTL_EPType_MASK; - if (xfertype == S3C_DxEPCTL_EPType_Bulk || - xfertype == S3C_DxEPCTL_EPType_Intterupt) - epctl |= S3C_DxEPCTL_SetD0PID; - } writel(epctl, hs->regs + epreg); @@ -2501,13 +2451,8 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) if (value) epctl |= S3C_DxEPCTL_Stall; - else { + else epctl &= ~S3C_DxEPCTL_Stall; - xfertype = epctl & S3C_DxEPCTL_EPType_MASK; - if (xfertype == S3C_DxEPCTL_EPType_Bulk || - xfertype == S3C_DxEPCTL_EPType_Intterupt) - epctl |= S3C_DxEPCTL_SetD0PID; - } writel(epctl, hs->regs + epreg); @@ -2546,9 +2491,9 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) timeout = 1000; do { grstctl = readl(hsotg->regs + S3C_GRSTCTL); - } while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); + } while (!(grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); - if (grstctl & S3C_GRSTCTL_CSftRst) { + if (!(grstctl & S3C_GRSTCTL_CSftRst)) { dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); return -EINVAL; } @@ -2565,6 +2510,9 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) return -ETIMEDOUT; } + if (grstctl & S3C_GRSTCTL_CSftRst) + continue; + if (!(grstctl & S3C_GRSTCTL_AHBIdle)) continue; @@ -2640,12 +2588,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); - /* Clear any pending OTG interrupts */ - writel(0xffffffff, hsotg->regs + S3C_GOTGINT); - - /* Clear any pending interrupts */ - writel(0xffffffff, hsotg->regs + S3C_GINTSTS); - writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | diff --git a/trunk/drivers/usb/host/ehci-fsl.c b/trunk/drivers/usb/host/ehci-fsl.c index 623732a312dd..5c761df7fa83 100644 --- a/trunk/drivers/usb/host/ehci-fsl.c +++ b/trunk/drivers/usb/host/ehci-fsl.c @@ -117,9 +117,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, pdata->regs = hcd->regs; - if (pdata->power_budget) - hcd->power_budget = pdata->power_budget; - /* * do platform specific init: check the clock, grab/config pins, etc. */ @@ -137,30 +134,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; - -#ifdef CONFIG_USB_OTG - if (pdata->operating_mode == FSL_USB2_DR_OTG) { - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - ehci->transceiver = otg_get_transceiver(); - dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n", - hcd, ehci, ehci->transceiver); - - if (ehci->transceiver) { - retval = otg_set_host(ehci->transceiver, - &ehci_to_hcd(ehci)->self); - if (retval) { - if (ehci->transceiver) - put_device(ehci->transceiver->dev); - goto err4; - } - } else { - dev_err(&pdev->dev, "can't find transceiver\n"); - retval = -ENODEV; - goto err4; - } - } -#endif return retval; err4: @@ -191,12 +164,6 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (ehci->transceiver) { - otg_set_host(ehci->transceiver, NULL); - put_device(ehci->transceiver->dev); - } usb_remove_hcd(hcd); @@ -361,149 +328,6 @@ struct ehci_fsl { #ifdef CONFIG_PM -#ifdef CONFIG_PPC_MPC512x -static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct fsl_usb2_platform_data *pdata = dev->platform_data; - u32 tmp; - -#ifdef DEBUG - u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); - mode &= USBMODE_CM_MASK; - tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ - - dev_dbg(dev, "suspend=%d already_suspended=%d " - "mode=%d usbcmd %08x\n", pdata->suspended, - pdata->already_suspended, mode, tmp); -#endif - - /* - * If the controller is already suspended, then this must be a - * PM suspend. Remember this fact, so that we will leave the - * controller suspended at PM resume time. - */ - if (pdata->suspended) { - dev_dbg(dev, "already suspended, leaving early\n"); - pdata->already_suspended = 1; - return 0; - } - - dev_dbg(dev, "suspending...\n"); - - hcd->state = HC_STATE_SUSPENDED; - dev->power.power_state = PMSG_SUSPEND; - - /* ignore non-host interrupts */ - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* stop the controller */ - tmp = ehci_readl(ehci, &ehci->regs->command); - tmp &= ~CMD_RUN; - ehci_writel(ehci, tmp, &ehci->regs->command); - - /* save EHCI registers */ - pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); - pdata->pm_command &= ~CMD_RUN; - pdata->pm_status = ehci_readl(ehci, &ehci->regs->status); - pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); - pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); - pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment); - pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); - pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); - pdata->pm_configured_flag = - ehci_readl(ehci, &ehci->regs->configured_flag); - pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); - pdata->pm_usbgenctrl = ehci_readl(ehci, - hcd->regs + FSL_SOC_USB_USBGENCTRL); - - /* clear the W1C bits */ - pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); - - pdata->suspended = 1; - - /* clear PP to cut power to the port */ - tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); - tmp &= ~PORT_POWER; - ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); - - return 0; -} - -static int ehci_fsl_mpc512x_drv_resume(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct fsl_usb2_platform_data *pdata = dev->platform_data; - u32 tmp; - - dev_dbg(dev, "suspend=%d already_suspended=%d\n", - pdata->suspended, pdata->already_suspended); - - /* - * If the controller was already suspended at suspend time, - * then don't resume it now. - */ - if (pdata->already_suspended) { - dev_dbg(dev, "already suspended, leaving early\n"); - pdata->already_suspended = 0; - return 0; - } - - if (!pdata->suspended) { - dev_dbg(dev, "not suspended, leaving early\n"); - return 0; - } - - pdata->suspended = 0; - - dev_dbg(dev, "resuming...\n"); - - /* set host mode */ - tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); - ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE); - - ehci_writel(ehci, pdata->pm_usbgenctrl, - hcd->regs + FSL_SOC_USB_USBGENCTRL); - ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, - hcd->regs + FSL_SOC_USB_ISIPHYCTRL); - - /* restore EHCI registers */ - ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); - ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); - ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); - ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); - ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); - ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); - ehci_writel(ehci, pdata->pm_configured_flag, - &ehci->regs->configured_flag); - ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); - - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - hcd->state = HC_STATE_RUNNING; - dev->power.power_state = PMSG_ON; - - tmp = ehci_readl(ehci, &ehci->regs->command); - tmp |= CMD_RUN; - ehci_writel(ehci, tmp, &ehci->regs->command); - - usb_hcd_resume_root_hub(hcd); - - return 0; -} -#else -static inline int ehci_fsl_mpc512x_drv_suspend(struct device *dev) -{ - return 0; -} - -static inline int ehci_fsl_mpc512x_drv_resume(struct device *dev) -{ - return 0; -} -#endif /* CONFIG_PPC_MPC512x */ - static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -517,11 +341,6 @@ static int ehci_fsl_drv_suspend(struct device *dev) struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); void __iomem *non_ehci = hcd->regs; - if (of_device_is_compatible(dev->parent->of_node, - "fsl,mpc5121-usb2-dr")) { - return ehci_fsl_mpc512x_drv_suspend(dev); - } - ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), device_may_wakeup(dev)); if (!fsl_deep_sleep()) @@ -538,11 +357,6 @@ static int ehci_fsl_drv_resume(struct device *dev) struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; - if (of_device_is_compatible(dev->parent->of_node, - "fsl,mpc5121-usb2-dr")) { - return ehci_fsl_mpc512x_drv_resume(dev); - } - ehci_prepare_ports_for_controller_resume(ehci); if (!fsl_deep_sleep()) return 0; @@ -577,38 +391,6 @@ static struct dev_pm_ops ehci_fsl_pm_ops = { #define EHCI_FSL_PM_OPS NULL #endif /* CONFIG_PM */ -#ifdef CONFIG_USB_OTG -static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 status; - - if (!port) - return -EINVAL; - - port--; - - /* start port reset before HNP protocol time out */ - status = readl(&ehci->regs->port_status[port]); - if (!(status & PORT_CONNECT)) - return -ENODEV; - - /* khubd will finish the reset later */ - if (ehci_is_TDI(ehci)) { - writel(PORT_RESET | - (status & ~(PORT_CSC | PORT_PEC | PORT_OCC)), - &ehci->regs->port_status[port]); - } else { - writel(PORT_RESET, &ehci->regs->port_status[port]); - } - - return 0; -} -#else -#define ehci_start_port_reset NULL -#endif /* CONFIG_USB_OTG */ - - static const struct hc_driver ehci_fsl_hc_driver = { .description = hcd_name, .product_desc = "Freescale On-Chip EHCI Host Controller", @@ -648,7 +430,6 @@ static const struct hc_driver ehci_fsl_hc_driver = { .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, - .start_port_reset = ehci_start_port_reset, .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, diff --git a/trunk/drivers/usb/host/ehci-fsl.h b/trunk/drivers/usb/host/ehci-fsl.h index 491806221165..3fabed33d940 100644 --- a/trunk/drivers/usb/host/ehci-fsl.h +++ b/trunk/drivers/usb/host/ehci-fsl.h @@ -27,10 +27,6 @@ #define PORT_PTS_SERIAL (3<<30) #define PORT_PTS_PTW (1<<28) #define FSL_SOC_USB_PORTSC2 0x188 -#define FSL_SOC_USB_USBMODE 0x1a8 -#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */ -#define USBMODE_CM_HOST (3 << 0) /* controller mode: host */ -#define USBMODE_ES (1 << 2) /* (Big) Endian Select */ #define FSL_SOC_USB_USBGENCTRL 0x200 #define USBGENCTRL_PPP (1 << 3) diff --git a/trunk/drivers/usb/host/ehci-hub.c b/trunk/drivers/usb/host/ehci-hub.c index ea6184bf48d0..1a21799195af 100644 --- a/trunk/drivers/usb/host/ehci-hub.c +++ b/trunk/drivers/usb/host/ehci-hub.c @@ -27,7 +27,6 @@ */ /*-------------------------------------------------------------------------*/ -#include #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) @@ -802,13 +801,6 @@ static int ehci_hub_control ( goto error; if (ehci->no_selective_suspend) break; -#ifdef CONFIG_USB_OTG - if ((hcd->self.otg_port == (wIndex + 1)) - && hcd->self.b_hnp_enable) { - otg_start_hnp(ehci->transceiver); - break; - } -#endif if (!(temp & PORT_SUSPEND)) break; if ((temp & PORT_PE) == 0) diff --git a/trunk/drivers/usb/host/ehci.h b/trunk/drivers/usb/host/ehci.h index e9ba8e252489..168f1a88c4d0 100644 --- a/trunk/drivers/usb/host/ehci.h +++ b/trunk/drivers/usb/host/ehci.h @@ -161,10 +161,6 @@ struct ehci_hcd { /* one per controller */ #ifdef DEBUG struct dentry *debug_dir; #endif - /* - * OTG controllers and transceivers need software interaction - */ - struct otg_transceiver *transceiver; }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/trunk/drivers/usb/host/isp1760-hcd.c b/trunk/drivers/usb/host/isp1760-hcd.c index dd98a966b58b..795345ad45e6 100644 --- a/trunk/drivers/usb/host/isp1760-hcd.c +++ b/trunk/drivers/usb/host/isp1760-hcd.c @@ -8,8 +8,6 @@ * * (c) 2007 Sebastian Siewior * - * (c) 2011 Arvid Brodin - * */ #include #include @@ -28,16 +26,14 @@ static struct kmem_cache *qtd_cachep; static struct kmem_cache *qh_cachep; -static struct kmem_cache *urb_listitem_cachep; struct isp1760_hcd { u32 hcs_params; spinlock_t lock; - struct slotinfo atl_slots[32]; - struct slotinfo int_slots[32]; + struct inter_packet_info atl_ints[32]; + struct inter_packet_info int_ints[32]; struct memory_chunk memory_pool[BLOCKS]; - struct list_head controlqhs, bulkqhs, interruptqhs; - int active_ptds; + u32 atl_queued; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 @@ -89,34 +85,18 @@ struct isp1760_qtd { struct list_head qtd_list; struct urb *urb; size_t length; - size_t actual_length; - - /* QTD_ENQUEUED: waiting for transfer (inactive) */ - /* QTD_PAYLOAD_ALLOC: chip mem has been allocated for payload */ - /* QTD_XFER_STARTED: valid ptd has been written to isp176x - only - interrupt handler may touch this qtd! */ - /* QTD_XFER_COMPLETE: payload has been transferred successfully */ - /* QTD_RETIRE: transfer error/abort qtd */ -#define QTD_ENQUEUED 0 -#define QTD_PAYLOAD_ALLOC 1 -#define QTD_XFER_STARTED 2 -#define QTD_XFER_COMPLETE 3 -#define QTD_RETIRE 4 + + /* isp special*/ u32 status; +#define URB_ENQUEUED (1 << 1) }; -/* Queue head, one for each active endpoint */ struct isp1760_qh { - struct list_head qh_list; + /* first part defined by EHCI spec */ struct list_head qtd_list; + u32 toggle; u32 ping; - int slot; -}; - -struct urb_listitem { - struct list_head urb_list; - struct urb *urb; }; /* @@ -292,7 +272,7 @@ static void init_memory(struct isp1760_hcd *priv) payload_addr += priv->memory_pool[curr + i].size; } - WARN_ON(payload_addr - priv->memory_pool[0].start > PAYLOAD_AREA_SIZE); + BUG_ON(payload_addr - priv->memory_pool[0].start > PAYLOAD_AREA_SIZE); } static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) @@ -300,7 +280,7 @@ static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) struct isp1760_hcd *priv = hcd_to_priv(hcd); int i; - WARN_ON(qtd->payload_addr); + BUG_ON(qtd->payload_addr); if (!qtd->length) return; @@ -313,6 +293,19 @@ static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) return; } } + + dev_err(hcd->self.controller, + "%s: Cannot allocate %zu bytes of memory\n" + "Current memory map:\n", + __func__, qtd->length); + for (i = 0; i < BLOCKS; i++) { + dev_err(hcd->self.controller, "Pool %2d size %4d status: %d\n", + i, priv->memory_pool[i].size, + priv->memory_pool[i].free); + } + /* XXX maybe -ENOMEM could be possible */ + BUG(); + return; } static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) @@ -325,7 +318,7 @@ static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) for (i = 0; i < BLOCKS; i++) { if (priv->memory_pool[i].start == qtd->payload_addr) { - WARN_ON(priv->memory_pool[i].free); + BUG_ON(priv->memory_pool[i].free); priv->memory_pool[i].free = 1; qtd->payload_addr = 0; return; @@ -334,8 +327,19 @@ static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) dev_err(hcd->self.controller, "%s: Invalid pointer: %08x\n", __func__, qtd->payload_addr); - WARN_ON(1); - qtd->payload_addr = 0; + BUG(); +} + +static void isp1760_init_regs(struct usb_hcd *hcd) +{ + reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0); + reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); + reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); + reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); + + reg_write32(hcd->regs, HC_ATL_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE); + reg_write32(hcd->regs, HC_INT_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE); + reg_write32(hcd->regs, HC_ISO_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE); } static int handshake(struct usb_hcd *hcd, u32 reg, @@ -373,27 +377,31 @@ static int ehci_reset(struct usb_hcd *hcd) return retval; } -static struct isp1760_qh *qh_alloc(gfp_t flags) +static void qh_destroy(struct isp1760_qh *qh) +{ + BUG_ON(!list_empty(&qh->qtd_list)); + kmem_cache_free(qh_cachep, qh); +} + +static struct isp1760_qh *isp1760_qh_alloc(gfp_t flags) { struct isp1760_qh *qh; qh = kmem_cache_zalloc(qh_cachep, flags); if (!qh) - return NULL; + return qh; - INIT_LIST_HEAD(&qh->qh_list); INIT_LIST_HEAD(&qh->qtd_list); - qh->slot = -1; - return qh; } -static void qh_free(struct isp1760_qh *qh) -{ - WARN_ON(!list_empty(&qh->qtd_list)); - WARN_ON(qh->slot > -1); - kmem_cache_free(qh_cachep, qh); -} +/* magic numbers that can affect system performance */ +#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ +#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ +#define EHCI_TUNE_RL_TT 0 +#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ +#define EHCI_TUNE_MULT_TT 1 +#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ /* one-time init, only for memory state */ static int priv_init(struct usb_hcd *hcd) @@ -403,10 +411,6 @@ static int priv_init(struct usb_hcd *hcd) spin_lock_init(&priv->lock); - INIT_LIST_HEAD(&priv->interruptqhs); - INIT_LIST_HEAD(&priv->controlqhs); - INIT_LIST_HEAD(&priv->bulkqhs); - /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -464,10 +468,7 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) } /* pre reset */ - reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0); - reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); - reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); - reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); + isp1760_init_regs(hcd); /* reset */ reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_ALL); @@ -487,15 +488,12 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ? "analog" : "digital"); - /* This is weird: at the first plug-in of a device there seems to be - one packet queued that never gets returned? */ - priv->active_ptds = -1; - /* ATL reset */ reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET); mdelay(10); reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode); + reg_write32(hcd->regs, HC_INTERRUPT_REG, INTERRUPT_ENABLE_MASK); reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, INTERRUPT_ENABLE_MASK); /* @@ -518,21 +516,14 @@ static void isp1760_init_maps(struct usb_hcd *hcd) reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000); reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000); reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001); - - reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0); - reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0); - reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0); - - reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, - ATL_BUF_FILL | INT_BUF_FILL); } static void isp1760_enable_interrupts(struct usb_hcd *hcd) { reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0); - reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff); + reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0); reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0); - reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff); + reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0); reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0); reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff); /* step 23 passed */ @@ -557,7 +548,8 @@ static int isp1760_run(struct usb_hcd *hcd) command |= CMD_RUN; reg_write32(hcd->regs, HC_USBCMD, command); - retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000); + retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, + 250 * 1000); if (retval) return retval; @@ -606,19 +598,12 @@ static int last_qtd_of_urb(struct isp1760_qtd *qtd, struct isp1760_qh *qh) return (qtd->urb != urb); } -/* magic numbers that can affect system performance */ -#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ -#define EHCI_TUNE_RL_TT 0 -#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define EHCI_TUNE_MULT_TT 1 -#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ - -static void create_ptd_atl(struct isp1760_qh *qh, +static void transform_into_atl(struct isp1760_qh *qh, struct isp1760_qtd *qtd, struct ptd *ptd) { u32 maxpacket; u32 multi; + u32 pid_code; u32 rl = RL_COUNTER; u32 nak = NAK_COUNTER; @@ -631,62 +616,67 @@ static void create_ptd_atl(struct isp1760_qh *qh, maxpacket &= 0x7ff; /* DW0 */ - ptd->dw0 = DW0_VALID_BIT; - ptd->dw0 |= TO_DW0_LENGTH(qtd->length); - ptd->dw0 |= TO_DW0_MAXPACKET(maxpacket); - ptd->dw0 |= TO_DW0_ENDPOINT(usb_pipeendpoint(qtd->urb->pipe)); + ptd->dw0 = PTD_VALID; + ptd->dw0 |= PTD_LENGTH(qtd->length); + ptd->dw0 |= PTD_MAXPACKET(maxpacket); + ptd->dw0 |= PTD_ENDPOINT(usb_pipeendpoint(qtd->urb->pipe)); /* DW1 */ ptd->dw1 = usb_pipeendpoint(qtd->urb->pipe) >> 1; - ptd->dw1 |= TO_DW1_DEVICE_ADDR(usb_pipedevice(qtd->urb->pipe)); - ptd->dw1 |= TO_DW1_PID_TOKEN(qtd->packet_type); + ptd->dw1 |= PTD_DEVICE_ADDR(usb_pipedevice(qtd->urb->pipe)); + + pid_code = qtd->packet_type; + ptd->dw1 |= PTD_PID_TOKEN(pid_code); if (usb_pipebulk(qtd->urb->pipe)) - ptd->dw1 |= DW1_TRANS_BULK; + ptd->dw1 |= PTD_TRANS_BULK; else if (usb_pipeint(qtd->urb->pipe)) - ptd->dw1 |= DW1_TRANS_INT; + ptd->dw1 |= PTD_TRANS_INT; if (qtd->urb->dev->speed != USB_SPEED_HIGH) { /* split transaction */ - ptd->dw1 |= DW1_TRANS_SPLIT; + ptd->dw1 |= PTD_TRANS_SPLIT; if (qtd->urb->dev->speed == USB_SPEED_LOW) - ptd->dw1 |= DW1_SE_USB_LOSPEED; + ptd->dw1 |= PTD_SE_USB_LOSPEED; - ptd->dw1 |= TO_DW1_PORT_NUM(qtd->urb->dev->ttport); - ptd->dw1 |= TO_DW1_HUB_NUM(qtd->urb->dev->tt->hub->devnum); + ptd->dw1 |= PTD_PORT_NUM(qtd->urb->dev->ttport); + ptd->dw1 |= PTD_HUB_NUM(qtd->urb->dev->tt->hub->devnum); /* SE bit for Split INT transfers */ if (usb_pipeint(qtd->urb->pipe) && (qtd->urb->dev->speed == USB_SPEED_LOW)) ptd->dw1 |= 2 << 16; + ptd->dw3 = 0; rl = 0; nak = 0; } else { - ptd->dw0 |= TO_DW0_MULTI(multi); + ptd->dw0 |= PTD_MULTI(multi); if (usb_pipecontrol(qtd->urb->pipe) || usb_pipebulk(qtd->urb->pipe)) - ptd->dw3 |= TO_DW3_PING(qh->ping); + ptd->dw3 = qh->ping; + else + ptd->dw3 = 0; } /* DW2 */ ptd->dw2 = 0; - ptd->dw2 |= TO_DW2_DATA_START_ADDR(base_to_chip(qtd->payload_addr)); - ptd->dw2 |= TO_DW2_RL(rl); + ptd->dw2 |= PTD_DATA_START_ADDR(base_to_chip(qtd->payload_addr)); + ptd->dw2 |= PTD_RL_CNT(rl); + ptd->dw3 |= PTD_NAC_CNT(nak); /* DW3 */ - ptd->dw3 |= TO_DW3_NAKCOUNT(nak); - ptd->dw3 |= TO_DW3_DATA_TOGGLE(qh->toggle); + ptd->dw3 |= qh->toggle; if (usb_pipecontrol(qtd->urb->pipe)) { if (qtd->data_buffer == qtd->urb->setup_packet) - ptd->dw3 &= ~TO_DW3_DATA_TOGGLE(1); + ptd->dw3 &= ~PTD_DATA_TOGGLE(1); else if (last_qtd_of_urb(qtd, qh)) - ptd->dw3 |= TO_DW3_DATA_TOGGLE(1); + ptd->dw3 |= PTD_DATA_TOGGLE(1); } - ptd->dw3 |= DW3_ACTIVE_BIT; + ptd->dw3 |= PTD_ACTIVE; /* Cerr */ - ptd->dw3 |= TO_DW3_CERR(ERR_COUNTER); + ptd->dw3 |= PTD_CERR(ERR_COUNTER); } static void transform_add_int(struct isp1760_qh *qh, @@ -741,13 +731,197 @@ static void transform_add_int(struct isp1760_qh *qh, ptd->dw4 = usof; } -static void create_ptd_int(struct isp1760_qh *qh, +static void transform_into_int(struct isp1760_qh *qh, struct isp1760_qtd *qtd, struct ptd *ptd) { - create_ptd_atl(qh, qtd, ptd); + transform_into_atl(qh, qtd, ptd); transform_add_int(qh, qtd, ptd); } +static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len, + u32 token) +{ + int count; + + qtd->data_buffer = databuffer; + qtd->packet_type = GET_QTD_TOKEN_TYPE(token); + + if (len > MAX_PAYLOAD_SIZE) + count = MAX_PAYLOAD_SIZE; + else + count = len; + + qtd->length = count; + return count; +} + +static int check_error(struct usb_hcd *hcd, struct ptd *ptd) +{ + int error = 0; + + if (ptd->dw3 & DW3_HALT_BIT) { + error = -EPIPE; + + if (ptd->dw3 & DW3_ERROR_BIT) + pr_err("error bit is set in DW3\n"); + } + + if (ptd->dw3 & DW3_QTD_ACTIVE) { + dev_err(hcd->self.controller, "Transfer active bit is set DW3\n" + "nak counter: %d, rl: %d\n", + (ptd->dw3 >> 19) & 0xf, (ptd->dw2 >> 25) & 0xf); + } + + return error; +} + +static void check_int_err_status(struct usb_hcd *hcd, u32 dw4) +{ + u32 i; + + dw4 >>= 8; + + for (i = 0; i < 8; i++) { + switch (dw4 & 0x7) { + case INT_UNDERRUN: + dev_err(hcd->self.controller, "Underrun (%d)\n", i); + break; + + case INT_EXACT: + dev_err(hcd->self.controller, + "Transaction error (%d)\n", i); + break; + + case INT_BABBLE: + dev_err(hcd->self.controller, "Babble error (%d)\n", i); + break; + } + dw4 >>= 3; + } +} + +static void enqueue_one_qtd(struct usb_hcd *hcd, struct isp1760_qtd *qtd) +{ + if (qtd->length && (qtd->length <= MAX_PAYLOAD_SIZE)) { + switch (qtd->packet_type) { + case IN_PID: + break; + case OUT_PID: + case SETUP_PID: + mem_writes8(hcd->regs, qtd->payload_addr, + qtd->data_buffer, qtd->length); + } + } +} + +static void enqueue_one_atl_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh, + u32 slot, struct isp1760_qtd *qtd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + struct ptd ptd; + + alloc_mem(hcd, qtd); + transform_into_atl(qh, qtd, &ptd); + ptd_write(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); + enqueue_one_qtd(hcd, qtd); + + priv->atl_ints[slot].qh = qh; + priv->atl_ints[slot].qtd = qtd; + qtd->status |= URB_ENQUEUED; + qtd->status |= slot << 16; +} + +static void enqueue_one_int_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh, + u32 slot, struct isp1760_qtd *qtd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + struct ptd ptd; + + alloc_mem(hcd, qtd); + transform_into_int(qh, qtd, &ptd); + ptd_write(hcd->regs, INT_PTD_OFFSET, slot, &ptd); + enqueue_one_qtd(hcd, qtd); + + priv->int_ints[slot].qh = qh; + priv->int_ints[slot].qtd = qtd; + qtd->status |= URB_ENQUEUED; + qtd->status |= slot << 16; +} + +static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, + struct isp1760_qtd *qtd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 skip_map, or_map; + u32 slot; + u32 buffstatus; + + /* + * When this function is called from the interrupt handler to enqueue + * a follow-up packet, the SKIP register gets written and read back + * almost immediately. With ISP1761, this register requires a delay of + * 195ns between a write and subsequent read (see section 15.1.1.3). + */ + mmiowb(); + ndelay(195); + skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); + + BUG_ON(!skip_map); + slot = __ffs(skip_map); + + enqueue_one_atl_qtd(hcd, qh, slot, qtd); + + or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG); + or_map |= (1 << slot); + reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map); + + skip_map &= ~(1 << slot); + reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); + + priv->atl_queued++; + if (priv->atl_queued == 2) + reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, + INTERRUPT_ENABLE_SOT_MASK); + + buffstatus = reg_read32(hcd->regs, HC_BUFFER_STATUS_REG); + buffstatus |= ATL_BUFFER; + reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, buffstatus); +} + +static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, + struct isp1760_qtd *qtd) +{ + u32 skip_map, or_map; + u32 slot; + u32 buffstatus; + + /* + * When this function is called from the interrupt handler to enqueue + * a follow-up packet, the SKIP register gets written and read back + * almost immediately. With ISP1761, this register requires a delay of + * 195ns between a write and subsequent read (see section 15.1.1.3). + */ + mmiowb(); + ndelay(195); + skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); + + BUG_ON(!skip_map); + slot = __ffs(skip_map); + + enqueue_one_int_qtd(hcd, qh, slot, qtd); + + or_map = reg_read32(hcd->regs, HC_INT_IRQ_MASK_OR_REG); + or_map |= (1 << slot); + reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, or_map); + + skip_map &= ~(1 << slot); + reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map); + + buffstatus = reg_read32(hcd->regs, HC_BUFFER_STATUS_REG); + buffstatus |= INT_BUFFER; + reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, buffstatus); +} + static void isp1760_urb_done(struct usb_hcd *hcd, struct urb *urb) __releases(priv->lock) __acquires(priv->lock) @@ -774,620 +948,557 @@ __acquires(priv->lock) spin_lock(&priv->lock); } -static struct isp1760_qtd *qtd_alloc(gfp_t flags, struct urb *urb, - u8 packet_type) -{ - struct isp1760_qtd *qtd; - - qtd = kmem_cache_zalloc(qtd_cachep, flags); - if (!qtd) - return NULL; - - INIT_LIST_HEAD(&qtd->qtd_list); - qtd->urb = urb; - qtd->packet_type = packet_type; - qtd->status = QTD_ENQUEUED; - qtd->actual_length = 0; - - return qtd; -} - -static void qtd_free(struct isp1760_qtd *qtd) +static void isp1760_qtd_free(struct isp1760_qtd *qtd) { - WARN_ON(qtd->payload_addr); + BUG_ON(qtd->payload_addr); kmem_cache_free(qtd_cachep, qtd); } -static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot, - struct slotinfo *slots, struct isp1760_qtd *qtd, - struct isp1760_qh *qh, struct ptd *ptd) +static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd, + struct isp1760_qh *qh) { - struct isp1760_hcd *priv = hcd_to_priv(hcd); - WARN_ON((slot < 0) || (slot > 31)); - WARN_ON(qtd->length && !qtd->payload_addr); - WARN_ON(slots[slot].qtd); - WARN_ON(slots[slot].qh); - WARN_ON(qtd->status != QTD_PAYLOAD_ALLOC); - - slots[slot].qtd = qtd; - slots[slot].qh = qh; - qh->slot = slot; - qtd->status = QTD_XFER_STARTED; /* Set this before writing ptd, since - interrupt routine may preempt and expects this value. */ - ptd_write(hcd->regs, ptd_offset, slot, ptd); - priv->active_ptds++; + struct isp1760_qtd *tmp_qtd; + + if (list_is_last(&qtd->qtd_list, &qh->qtd_list)) + tmp_qtd = NULL; + else + tmp_qtd = list_entry(qtd->qtd_list.next, struct isp1760_qtd, + qtd_list); + list_del(&qtd->qtd_list); + isp1760_qtd_free(qtd); + return tmp_qtd; } -static int is_short_bulk(struct isp1760_qtd *qtd) +/* + * Remove this QTD from the QH list and free its memory. If this QTD + * isn't the last one than remove also his successor(s). + * Returns the QTD which is part of an new URB and should be enqueued. + */ +static struct isp1760_qtd *clean_up_qtdlist(struct isp1760_qtd *qtd, + struct isp1760_qh *qh) { - return (usb_pipebulk(qtd->urb->pipe) && - (qtd->actual_length < qtd->length)); + struct urb *urb; + + urb = qtd->urb; + do { + qtd = clean_this_qtd(qtd, qh); + } while (qtd && (qtd->urb == urb)); + + return qtd; } -static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh, - struct list_head *urb_list) +static void do_atl_int(struct usb_hcd *hcd) { - int last_qtd; - struct isp1760_qtd *qtd, *qtd_next; - struct urb_listitem *urb_listitem; + struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 done_map, skip_map; + struct ptd ptd; + struct urb *urb; + u32 slot; + u32 length; + u32 or_map; + u32 status = -EINVAL; + int error; + struct isp1760_qtd *qtd; + struct isp1760_qh *qh; + u32 rl; + u32 nakcount; - list_for_each_entry_safe(qtd, qtd_next, &qh->qtd_list, qtd_list) { - if (qtd->status < QTD_XFER_COMPLETE) - break; + done_map = reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG); + skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); - if (list_is_last(&qtd->qtd_list, &qh->qtd_list)) - last_qtd = 1; - else - last_qtd = qtd->urb != qtd_next->urb; - - if ((!last_qtd) && (qtd->status == QTD_RETIRE)) - qtd_next->status = QTD_RETIRE; - - if (qtd->status == QTD_XFER_COMPLETE) { - if (qtd->actual_length) { - switch (qtd->packet_type) { - case IN_PID: - mem_reads8(hcd->regs, qtd->payload_addr, - qtd->data_buffer, - qtd->actual_length); - /* Fall through (?) */ - case OUT_PID: - qtd->urb->actual_length += - qtd->actual_length; - /* Fall through ... */ - case SETUP_PID: - break; - } - } + or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG); + or_map &= ~done_map; + reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map); - if (is_short_bulk(qtd)) { - if (qtd->urb->transfer_flags & URB_SHORT_NOT_OK) - qtd->urb->status = -EREMOTEIO; - if (!last_qtd) - qtd_next->status = QTD_RETIRE; - } - } + while (done_map) { + status = 0; + priv->atl_queued--; - if (qtd->payload_addr) - free_mem(hcd, qtd); + slot = __ffs(done_map); + done_map &= ~(1 << slot); + skip_map |= (1 << slot); - if (last_qtd) { - if ((qtd->status == QTD_RETIRE) && - (qtd->urb->status == -EINPROGRESS)) - qtd->urb->status = -EPIPE; - /* Defer calling of urb_done() since it releases lock */ - urb_listitem = kmem_cache_zalloc(urb_listitem_cachep, - GFP_ATOMIC); - if (unlikely(!urb_listitem)) - break; - urb_listitem->urb = qtd->urb; - list_add_tail(&urb_listitem->urb_list, urb_list); + qtd = priv->atl_ints[slot].qtd; + qh = priv->atl_ints[slot].qh; + + if (!qh) { + dev_err(hcd->self.controller, "qh is 0\n"); + continue; } + ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); - list_del(&qtd->qtd_list); - qtd_free(qtd); - } -} + rl = (ptd.dw2 >> 25) & 0x0f; + nakcount = (ptd.dw3 >> 19) & 0xf; -#define ENQUEUE_DEPTH 2 -static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) -{ - struct isp1760_hcd *priv = hcd_to_priv(hcd); - int ptd_offset; - struct slotinfo *slots; - int curr_slot, free_slot; - int n; - struct ptd ptd; - struct isp1760_qtd *qtd; + /* Transfer Error, *but* active and no HALT -> reload */ + if ((ptd.dw3 & DW3_ERROR_BIT) && (ptd.dw3 & DW3_QTD_ACTIVE) && + !(ptd.dw3 & DW3_HALT_BIT)) { + + /* according to ppriv code, we have to + * reload this one if trasfered bytes != requested bytes + * else act like everything went smooth.. + * XXX This just doesn't feel right and hasn't + * triggered so far. + */ - if (unlikely(list_empty(&qh->qtd_list))) { - WARN_ON(1); - return; - } + length = PTD_XFERRED_LENGTH(ptd.dw3); + dev_err(hcd->self.controller, + "Should reload now... transferred %d " + "of %zu\n", length, qtd->length); + BUG(); + } - if (usb_pipeint(list_entry(qh->qtd_list.next, struct isp1760_qtd, - qtd_list)->urb->pipe)) { - ptd_offset = INT_PTD_OFFSET; - slots = priv->int_slots; - } else { - ptd_offset = ATL_PTD_OFFSET; - slots = priv->atl_slots; - } + if (!nakcount && (ptd.dw3 & DW3_QTD_ACTIVE)) { + u32 buffstatus; - free_slot = -1; - for (curr_slot = 0; curr_slot < 32; curr_slot++) { - if ((free_slot == -1) && (slots[curr_slot].qtd == NULL)) - free_slot = curr_slot; - if (slots[curr_slot].qh == qh) - break; - } + /* + * NAKs are handled in HW by the chip. Usually if the + * device is not able to send data fast enough. + * This happens mostly on slower hardware. + */ - n = 0; - list_for_each_entry(qtd, &qh->qtd_list, qtd_list) { - if (qtd->status == QTD_ENQUEUED) { - WARN_ON(qtd->payload_addr); - alloc_mem(hcd, qtd); - if ((qtd->length) && (!qtd->payload_addr)) - break; + /* RL counter = ERR counter */ + ptd.dw3 &= ~(0xf << 19); + ptd.dw3 |= rl << 19; + ptd.dw3 &= ~(3 << (55 - 32)); + ptd.dw3 |= ERR_COUNTER << (55 - 32); + + /* + * It is not needed to write skip map back because it + * is unchanged. Just make sure that this entry is + * unskipped once it gets written to the HW. + */ + skip_map &= ~(1 << slot); + or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG); + or_map |= 1 << slot; + reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map); - if ((qtd->length) && - ((qtd->packet_type == SETUP_PID) || - (qtd->packet_type == OUT_PID))) { - mem_writes8(hcd->regs, qtd->payload_addr, - qtd->data_buffer, qtd->length); - } + ptd.dw0 |= PTD_VALID; + ptd_write(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); - qtd->status = QTD_PAYLOAD_ALLOC; - } + priv->atl_queued++; + if (priv->atl_queued == 2) + reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, + INTERRUPT_ENABLE_SOT_MASK); - if (qtd->status == QTD_PAYLOAD_ALLOC) { -/* - if ((curr_slot > 31) && (free_slot == -1)) - dev_dbg(hcd->self.controller, "%s: No slot " - "available for transfer\n", __func__); -*/ - /* Start xfer for this endpoint if not already done */ - if ((curr_slot > 31) && (free_slot > -1)) { - if (usb_pipeint(qtd->urb->pipe)) - create_ptd_int(qh, qtd, &ptd); - else - create_ptd_atl(qh, qtd, &ptd); - - start_bus_transfer(hcd, ptd_offset, free_slot, - slots, qtd, qh, &ptd); - curr_slot = free_slot; - } + buffstatus = reg_read32(hcd->regs, + HC_BUFFER_STATUS_REG); + buffstatus |= ATL_BUFFER; + reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, + buffstatus); + continue; + } - n++; - if (n >= ENQUEUE_DEPTH) - break; + error = check_error(hcd, &ptd); + if (error) { + status = error; + priv->atl_ints[slot].qh->toggle = 0; + priv->atl_ints[slot].qh->ping = 0; + qtd->urb->status = -EPIPE; + +#if 0 + printk(KERN_ERR "Error in %s().\n", __func__); + printk(KERN_ERR "IN dw0: %08x dw1: %08x dw2: %08x " + "dw3: %08x dw4: %08x dw5: %08x dw6: " + "%08x dw7: %08x\n", + ptd.dw0, ptd.dw1, ptd.dw2, ptd.dw3, + ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7); +#endif + } else { + priv->atl_ints[slot].qh->toggle = ptd.dw3 & (1 << 25); + priv->atl_ints[slot].qh->ping = ptd.dw3 & (1 << 26); } - } -} -void schedule_ptds(struct usb_hcd *hcd) -{ - struct isp1760_hcd *priv; - struct isp1760_qh *qh, *qh_next; - struct list_head *ep_queue; - struct usb_host_endpoint *ep; - LIST_HEAD(urb_list); - struct urb_listitem *urb_listitem, *urb_listitem_next; - - if (!hcd) { - WARN_ON(1); - return; - } + length = PTD_XFERRED_LENGTH(ptd.dw3); + if (length) { + switch (DW1_GET_PID(ptd.dw1)) { + case IN_PID: + mem_reads8(hcd->regs, qtd->payload_addr, + qtd->data_buffer, length); - priv = hcd_to_priv(hcd); + case OUT_PID: - /* - * check finished/retired xfers, transfer payloads, call urb_done() - */ - ep_queue = &priv->interruptqhs; - while (ep_queue) { - list_for_each_entry_safe(qh, qh_next, ep_queue, qh_list) { - ep = list_entry(qh->qtd_list.next, struct isp1760_qtd, - qtd_list)->urb->ep; - collect_qtds(hcd, qh, &urb_list); - if (list_empty(&qh->qtd_list)) { - list_del(&qh->qh_list); - if (ep->hcpriv == NULL) { - /* Endpoint has been disabled, so we - can free the associated queue head. */ - qh_free(qh); - } + qtd->urb->actual_length += length; + + case SETUP_PID: + break; } } - if (ep_queue == &priv->interruptqhs) - ep_queue = &priv->controlqhs; - else if (ep_queue == &priv->controlqhs) - ep_queue = &priv->bulkqhs; - else - ep_queue = NULL; - } + priv->atl_ints[slot].qtd = NULL; + priv->atl_ints[slot].qh = NULL; - list_for_each_entry_safe(urb_listitem, urb_listitem_next, &urb_list, - urb_list) { - isp1760_urb_done(hcd, urb_listitem->urb); - kmem_cache_free(urb_listitem_cachep, urb_listitem); - } + free_mem(hcd, qtd); - /* - * Schedule packets for transfer. - * - * According to USB2.0 specification: - * - * 1st prio: interrupt xfers, up to 80 % of bandwidth - * 2nd prio: control xfers - * 3rd prio: bulk xfers - * - * ... but let's use a simpler scheme here (mostly because ISP1761 doc - * is very unclear on how to prioritize traffic): - * - * 1) Enqueue any queued control transfers, as long as payload chip mem - * and PTD ATL slots are available. - * 2) Enqueue any queued INT transfers, as long as payload chip mem - * and PTD INT slots are available. - * 3) Enqueue any queued bulk transfers, as long as payload chip mem - * and PTD ATL slots are available. - * - * Use double buffering (ENQUEUE_DEPTH==2) as a compromise between - * conservation of chip mem and performance. - * - * I'm sure this scheme could be improved upon! - */ - ep_queue = &priv->controlqhs; - while (ep_queue) { - list_for_each_entry_safe(qh, qh_next, ep_queue, qh_list) - enqueue_qtds(hcd, qh); - - if (ep_queue == &priv->controlqhs) - ep_queue = &priv->interruptqhs; - else if (ep_queue == &priv->interruptqhs) - ep_queue = &priv->bulkqhs; - else - ep_queue = NULL; - } -} + reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); -#define PTD_STATE_QTD_DONE 1 -#define PTD_STATE_QTD_RELOAD 2 -#define PTD_STATE_URB_RETIRE 3 + if (qtd->urb->status == -EPIPE) { + /* HALT was received */ -static int check_int_transfer(struct usb_hcd *hcd, struct ptd *ptd, - struct urb *urb) -{ - __dw dw4; - int i; + urb = qtd->urb; + qtd = clean_up_qtdlist(qtd, qh); + isp1760_urb_done(hcd, urb); - dw4 = ptd->dw4; - dw4 >>= 8; + } else if (usb_pipebulk(qtd->urb->pipe) && + (length < qtd->length)) { + /* short BULK received */ - /* FIXME: ISP1761 datasheet does not say what to do with these. Do we - need to handle these errors? Is it done in hardware? */ + if (qtd->urb->transfer_flags & URB_SHORT_NOT_OK) { + qtd->urb->status = -EREMOTEIO; + dev_dbg(hcd->self.controller, + "short bulk, %d instead %zu " + "with URB_SHORT_NOT_OK flag.\n", + length, qtd->length); + } - if (ptd->dw3 & DW3_HALT_BIT) { + if (qtd->urb->status == -EINPROGRESS) + qtd->urb->status = 0; - urb->status = -EPROTO; /* Default unknown error */ + urb = qtd->urb; + qtd = clean_up_qtdlist(qtd, qh); + isp1760_urb_done(hcd, urb); - for (i = 0; i < 8; i++) { - switch (dw4 & 0x7) { - case INT_UNDERRUN: - dev_dbg(hcd->self.controller, "%s: underrun " - "during uFrame %d\n", - __func__, i); - urb->status = -ECOMM; /* Could not write data */ - break; - case INT_EXACT: - dev_dbg(hcd->self.controller, "%s: transaction " - "error during uFrame %d\n", - __func__, i); - urb->status = -EPROTO; /* timeout, bad CRC, PID - error etc. */ - break; - case INT_BABBLE: - dev_dbg(hcd->self.controller, "%s: babble " - "error during uFrame %d\n", - __func__, i); - urb->status = -EOVERFLOW; - break; - } - dw4 >>= 3; - } + } else if (last_qtd_of_urb(qtd, qh)) { + /* that was the last qtd of that URB */ - return PTD_STATE_URB_RETIRE; - } + if (qtd->urb->status == -EINPROGRESS) + qtd->urb->status = 0; - return PTD_STATE_QTD_DONE; -} + urb = qtd->urb; + qtd = clean_up_qtdlist(qtd, qh); + isp1760_urb_done(hcd, urb); -static int check_atl_transfer(struct usb_hcd *hcd, struct ptd *ptd, - struct urb *urb) -{ - WARN_ON(!ptd); - if (ptd->dw3 & DW3_HALT_BIT) { - if (ptd->dw3 & DW3_BABBLE_BIT) - urb->status = -EOVERFLOW; - else if (FROM_DW3_CERR(ptd->dw3)) - urb->status = -EPIPE; /* Stall */ - else if (ptd->dw3 & DW3_ERROR_BIT) - urb->status = -EPROTO; /* XactErr */ - else - urb->status = -EPROTO; /* Unknown */ -/* - dev_dbg(hcd->self.controller, "%s: ptd error:\n" - " dw0: %08x dw1: %08x dw2: %08x dw3: %08x\n" - " dw4: %08x dw5: %08x dw6: %08x dw7: %08x\n", - __func__, - ptd->dw0, ptd->dw1, ptd->dw2, ptd->dw3, - ptd->dw4, ptd->dw5, ptd->dw6, ptd->dw7); -*/ - return PTD_STATE_URB_RETIRE; - } + } else { + /* next QTD of this URB */ - if ((ptd->dw3 & DW3_ERROR_BIT) && (ptd->dw3 & DW3_ACTIVE_BIT)) { - /* Transfer Error, *but* active and no HALT -> reload */ - dev_dbg(hcd->self.controller, "PID error; reloading ptd\n"); - return PTD_STATE_QTD_RELOAD; - } + qtd = clean_this_qtd(qtd, qh); + BUG_ON(!qtd); + } - if (!FROM_DW3_NAKCOUNT(ptd->dw3) && (ptd->dw3 & DW3_ACTIVE_BIT)) { - /* - * NAKs are handled in HW by the chip. Usually if the - * device is not able to send data fast enough. - * This happens mostly on slower hardware. - */ - return PTD_STATE_QTD_RELOAD; - } + if (qtd) + enqueue_an_ATL_packet(hcd, qh, qtd); - return PTD_STATE_QTD_DONE; + skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); + } + if (priv->atl_queued <= 1) + reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, + INTERRUPT_ENABLE_MASK); } -static irqreturn_t isp1760_irq(struct usb_hcd *hcd) +static void do_intl_int(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - u32 imask; - irqreturn_t irqret = IRQ_NONE; + u32 done_map, skip_map; struct ptd ptd; - struct isp1760_qh *qh; - int int_done_map, atl_done_map; - int slot; - int state; - struct slotinfo *slots; - u32 ptd_offset; + struct urb *urb; + u32 length; + u32 or_map; + int error; + u32 slot; struct isp1760_qtd *qtd; - int modified; - static int last_active_ptds; + struct isp1760_qh *qh; - spin_lock(&priv->lock); + done_map = reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG); + skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); - if (!(hcd->state & HC_STATE_RUNNING)) - goto leave; + or_map = reg_read32(hcd->regs, HC_INT_IRQ_MASK_OR_REG); + or_map &= ~done_map; + reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, or_map); + + while (done_map) { + slot = __ffs(done_map); + done_map &= ~(1 << slot); + skip_map |= (1 << slot); + + qtd = priv->int_ints[slot].qtd; + qh = priv->int_ints[slot].qh; + + if (!qh) { + dev_err(hcd->self.controller, "(INT) qh is 0\n"); + continue; + } + + ptd_read(hcd->regs, INT_PTD_OFFSET, slot, &ptd); + check_int_err_status(hcd, ptd.dw4); + + error = check_error(hcd, &ptd); + if (error) { +#if 0 + printk(KERN_ERR "Error in %s().\n", __func__); + printk(KERN_ERR "IN dw0: %08x dw1: %08x dw2: %08x " + "dw3: %08x dw4: %08x dw5: %08x dw6: " + "%08x dw7: %08x\n", + ptd.dw0, ptd.dw1, ptd.dw2, ptd.dw3, + ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7); +#endif + qtd->urb->status = -EPIPE; + priv->int_ints[slot].qh->toggle = 0; + priv->int_ints[slot].qh->ping = 0; - imask = reg_read32(hcd->regs, HC_INTERRUPT_REG); - if (unlikely(!imask)) - goto leave; - reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */ - - int_done_map = reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG); - atl_done_map = reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG); - modified = int_done_map | atl_done_map; - - while (int_done_map || atl_done_map) { - if (int_done_map) { - /* INT ptd */ - slot = __ffs(int_done_map); - int_done_map &= ~(1 << slot); - slots = priv->int_slots; - if (!slots[slot].qh) - continue; - ptd_offset = INT_PTD_OFFSET; - ptd_read(hcd->regs, INT_PTD_OFFSET, slot, &ptd); - state = check_int_transfer(hcd, &ptd, - slots[slot].qtd->urb); } else { - /* ATL ptd */ - slot = __ffs(atl_done_map); - atl_done_map &= ~(1 << slot); - slots = priv->atl_slots; - if (!slots[slot].qh) - continue; - ptd_offset = ATL_PTD_OFFSET; - ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); - state = check_atl_transfer(hcd, &ptd, - slots[slot].qtd->urb); + priv->int_ints[slot].qh->toggle = ptd.dw3 & (1 << 25); + priv->int_ints[slot].qh->ping = ptd.dw3 & (1 << 26); } - qtd = slots[slot].qtd; - slots[slot].qtd = NULL; - qh = slots[slot].qh; - slots[slot].qh = NULL; - priv->active_ptds--; - qh->slot = -1; - - WARN_ON(qtd->status != QTD_XFER_STARTED); - - switch (state) { - case PTD_STATE_QTD_DONE: - if ((usb_pipeint(qtd->urb->pipe)) && - (qtd->urb->dev->speed != USB_SPEED_HIGH)) - qtd->actual_length = - FROM_DW3_SCS_NRBYTESTRANSFERRED(ptd.dw3); - else - qtd->actual_length = - FROM_DW3_NRBYTESTRANSFERRED(ptd.dw3); - - qtd->status = QTD_XFER_COMPLETE; - if (list_is_last(&qtd->qtd_list, &qh->qtd_list) || - is_short_bulk(qtd)) - qtd = NULL; - else - qtd = list_entry(qtd->qtd_list.next, - typeof(*qtd), qtd_list); - - qh->toggle = FROM_DW3_DATA_TOGGLE(ptd.dw3); - qh->ping = FROM_DW3_PING(ptd.dw3); - break; + if (qtd->urb->dev->speed != USB_SPEED_HIGH) + length = PTD_XFERRED_LENGTH_LO(ptd.dw3); + else + length = PTD_XFERRED_LENGTH(ptd.dw3); - case PTD_STATE_QTD_RELOAD: /* QTD_RETRY, for atls only */ - qtd->status = QTD_PAYLOAD_ALLOC; - ptd.dw0 |= DW0_VALID_BIT; - /* RL counter = ERR counter */ - ptd.dw3 &= ~TO_DW3_NAKCOUNT(0xf); - ptd.dw3 |= TO_DW3_NAKCOUNT(FROM_DW2_RL(ptd.dw2)); - ptd.dw3 &= ~TO_DW3_CERR(3); - ptd.dw3 |= TO_DW3_CERR(ERR_COUNTER); - qh->toggle = FROM_DW3_DATA_TOGGLE(ptd.dw3); - qh->ping = FROM_DW3_PING(ptd.dw3); - break; + if (length) { + switch (DW1_GET_PID(ptd.dw1)) { + case IN_PID: + mem_reads8(hcd->regs, qtd->payload_addr, + qtd->data_buffer, length); + case OUT_PID: - case PTD_STATE_URB_RETIRE: - qtd->status = QTD_RETIRE; - qtd = NULL; - qh->toggle = 0; - qh->ping = 0; - break; + qtd->urb->actual_length += length; - default: - WARN_ON(1); - continue; + case SETUP_PID: + break; + } } - if (qtd && (qtd->status == QTD_PAYLOAD_ALLOC)) { - if (slots == priv->int_slots) { - if (state == PTD_STATE_QTD_RELOAD) - dev_err(hcd->self.controller, - "%s: PTD_STATE_QTD_RELOAD on " - "interrupt packet\n", __func__); - if (state != PTD_STATE_QTD_RELOAD) - create_ptd_int(qh, qtd, &ptd); - } else { - if (state != PTD_STATE_QTD_RELOAD) - create_ptd_atl(qh, qtd, &ptd); - } + priv->int_ints[slot].qtd = NULL; + priv->int_ints[slot].qh = NULL; + + reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map); + free_mem(hcd, qtd); + + if (qtd->urb->status == -EPIPE) { + /* HALT received */ + + urb = qtd->urb; + qtd = clean_up_qtdlist(qtd, qh); + isp1760_urb_done(hcd, urb); - start_bus_transfer(hcd, ptd_offset, slot, slots, qtd, - qh, &ptd); + } else if (last_qtd_of_urb(qtd, qh)) { + + if (qtd->urb->status == -EINPROGRESS) + qtd->urb->status = 0; + + urb = qtd->urb; + qtd = clean_up_qtdlist(qtd, qh); + isp1760_urb_done(hcd, urb); + + } else { + /* next QTD of this URB */ + + qtd = clean_this_qtd(qtd, qh); + BUG_ON(!qtd); } + + if (qtd) + enqueue_an_INT_packet(hcd, qh, qtd); + + skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); } +} - if (modified) - schedule_ptds(hcd); +static struct isp1760_qh *qh_make(struct usb_hcd *hcd, struct urb *urb, + gfp_t flags) +{ + struct isp1760_qh *qh; + int is_input, type; - /* ISP1760 Errata 2 explains that interrupts may be missed (or not - happen?) if two USB devices are running simultaneously. Perhaps - this happens when a PTD is finished during interrupt handling; - enable SOF interrupts if PTDs are still scheduled when exiting this - interrupt handler, just to be safe. */ + qh = isp1760_qh_alloc(flags); + if (!qh) + return qh; - if (priv->active_ptds != last_active_ptds) { - if (priv->active_ptds > 0) - reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, - INTERRUPT_ENABLE_SOT_MASK); - else - reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, - INTERRUPT_ENABLE_MASK); - last_active_ptds = priv->active_ptds; + /* + * init endpoint/device data for this QH + */ + is_input = usb_pipein(urb->pipe); + type = usb_pipetype(urb->pipe); + + if (!usb_pipecontrol(urb->pipe)) + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input, + 1); + return qh; +} + +/* + * For control/bulk/interrupt, return QH with these TDs appended. + * Allocates and initializes the QH if necessary. + * Returns null if it can't allocate a QH it needs to. + * If the QH has TDs (urbs) already, that's great. + */ +static struct isp1760_qh *qh_append_tds(struct usb_hcd *hcd, + struct urb *urb, struct list_head *qtd_list, int epnum, + void **ptr) +{ + struct isp1760_qh *qh; + + qh = (struct isp1760_qh *)*ptr; + if (!qh) { + /* can't sleep here, we have priv->lock... */ + qh = qh_make(hcd, urb, GFP_ATOMIC); + if (!qh) + return qh; + *ptr = qh; } - irqret = IRQ_HANDLED; -leave: - spin_unlock(&priv->lock); + list_splice(qtd_list, qh->qtd_list.prev); - return irqret; + return qh; } -static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len) +static void qtd_list_free(struct urb *urb, struct list_head *qtd_list) { - qtd->data_buffer = databuffer; + struct list_head *entry, *temp; - if (len > MAX_PAYLOAD_SIZE) - len = MAX_PAYLOAD_SIZE; - qtd->length = len; + list_for_each_safe(entry, temp, qtd_list) { + struct isp1760_qtd *qtd; - return qtd->length; + qtd = list_entry(entry, struct isp1760_qtd, qtd_list); + list_del(&qtd->qtd_list); + isp1760_qtd_free(qtd); + } } -static void qtd_list_free(struct list_head *qtd_list) +static int isp1760_prepare_enqueue(struct usb_hcd *hcd, struct urb *urb, + struct list_head *qtd_list, gfp_t mem_flags, packet_enqueue *p) { - struct isp1760_qtd *qtd, *qtd_next; + struct isp1760_hcd *priv = hcd_to_priv(hcd); + struct isp1760_qtd *qtd; + int epnum; + unsigned long flags; + struct isp1760_qh *qh = NULL; + int rc; + int qh_busy; - list_for_each_entry_safe(qtd, qtd_next, qtd_list, qtd_list) { - list_del(&qtd->qtd_list); - qtd_free(qtd); + qtd = list_entry(qtd_list->next, struct isp1760_qtd, qtd_list); + epnum = urb->ep->desc.bEndpointAddress; + + spin_lock_irqsave(&priv->lock, flags); + if (!HCD_HW_ACCESSIBLE(hcd)) { + rc = -ESHUTDOWN; + goto done; + } + rc = usb_hcd_link_urb_to_ep(hcd, urb); + if (rc) + goto done; + + qh = urb->ep->hcpriv; + if (qh) + qh_busy = !list_empty(&qh->qtd_list); + else + qh_busy = 0; + + qh = qh_append_tds(hcd, urb, qtd_list, epnum, &urb->ep->hcpriv); + if (!qh) { + usb_hcd_unlink_urb_from_ep(hcd, urb); + rc = -ENOMEM; + goto done; } + + if (!qh_busy) + p(hcd, qh, qtd); + +done: + spin_unlock_irqrestore(&priv->lock, flags); + if (!qh) + qtd_list_free(urb, qtd_list); + return rc; +} + +static struct isp1760_qtd *isp1760_qtd_alloc(gfp_t flags) +{ + struct isp1760_qtd *qtd; + + qtd = kmem_cache_zalloc(qtd_cachep, flags); + if (qtd) + INIT_LIST_HEAD(&qtd->qtd_list); + + return qtd; } /* - * Packetize urb->transfer_buffer into list of packets of size wMaxPacketSize. - * Also calculate the PID type (SETUP/IN/OUT) for each packet. + * create a list of filled qtds for this URB; won't link into qh. */ #define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) -static void packetize_urb(struct usb_hcd *hcd, +static struct list_head *qh_urb_transaction(struct usb_hcd *hcd, struct urb *urb, struct list_head *head, gfp_t flags) { struct isp1760_qtd *qtd; void *buf; - int len, maxpacketsize; - u8 packet_type; + int len, maxpacket; + int is_input; + u32 token; /* * URBs map to sequences of QTDs: one logical transaction */ + qtd = isp1760_qtd_alloc(flags); + if (!qtd) + return NULL; - if (!urb->transfer_buffer && urb->transfer_buffer_length) { - /* XXX This looks like usb storage / SCSI bug */ - dev_err(hcd->self.controller, - "buf is null, dma is %08lx len is %d\n", - (long unsigned)urb->transfer_dma, - urb->transfer_buffer_length); - WARN_ON(1); - } + list_add_tail(&qtd->qtd_list, head); + qtd->urb = urb; + urb->status = -EINPROGRESS; - if (usb_pipein(urb->pipe)) - packet_type = IN_PID; - else - packet_type = OUT_PID; + token = 0; + /* for split transactions, SplitXState initialized to zero */ + len = urb->transfer_buffer_length; + is_input = usb_pipein(urb->pipe); if (usb_pipecontrol(urb->pipe)) { - qtd = qtd_alloc(flags, urb, SETUP_PID); + /* SETUP pid */ + qtd_fill(qtd, urb->setup_packet, + sizeof(struct usb_ctrlrequest), + token | SETUP_PID); + + /* ... and always at least one more pid */ + qtd = isp1760_qtd_alloc(flags); if (!qtd) goto cleanup; - qtd_fill(qtd, urb->setup_packet, sizeof(struct usb_ctrlrequest)); + qtd->urb = urb; list_add_tail(&qtd->qtd_list, head); /* for zero length DATA stages, STATUS is always IN */ - if (urb->transfer_buffer_length == 0) - packet_type = IN_PID; + if (len == 0) + token |= IN_PID; } - maxpacketsize = max_packet(usb_maxpacket(urb->dev, urb->pipe, - usb_pipeout(urb->pipe))); + /* + * data transfer stage: buffer setup + */ + buf = urb->transfer_buffer; + + if (is_input) + token |= IN_PID; + else + token |= OUT_PID; + + maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); /* * buffer gets wrapped in one or more qtds; * last one may be "short" (including zero len) * and may serve as a control status ack */ - buf = urb->transfer_buffer; - len = urb->transfer_buffer_length; - for (;;) { int this_qtd_len; - qtd = qtd_alloc(flags, urb, packet_type); - if (!qtd) - goto cleanup; - this_qtd_len = qtd_fill(qtd, buf, len); - list_add_tail(&qtd->qtd_list, head); + if (!buf && len) { + /* XXX This looks like usb storage / SCSI bug */ + dev_err(hcd->self.controller, "buf is null, dma is %08lx len is %d\n", + (long unsigned)urb->transfer_dma, len); + WARN_ON(1); + } + this_qtd_len = qtd_fill(qtd, buf, len, token); len -= this_qtd_len; buf += this_qtd_len; if (len <= 0) break; + + qtd = isp1760_qtd_alloc(flags); + if (!qtd) + goto cleanup; + qtd->urb = urb; + list_add_tail(&qtd->qtd_list, head); } /* @@ -1399,163 +1510,183 @@ static void packetize_urb(struct usb_hcd *hcd, if (usb_pipecontrol(urb->pipe)) { one_more = 1; - if (packet_type == IN_PID) - packet_type = OUT_PID; - else - packet_type = IN_PID; + /* "in" <--> "out" */ + token ^= IN_PID; } else if (usb_pipebulk(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) - && !(urb->transfer_buffer_length % - maxpacketsize)) { + && !(urb->transfer_buffer_length % maxpacket)) { one_more = 1; } if (one_more) { - qtd = qtd_alloc(flags, urb, packet_type); + qtd = isp1760_qtd_alloc(flags); if (!qtd) goto cleanup; + qtd->urb = urb; + list_add_tail(&qtd->qtd_list, head); /* never any data in such packets */ - qtd_fill(qtd, NULL, 0); - list_add_tail(&qtd->qtd_list, head); + qtd_fill(qtd, NULL, 0, token); } } - return; + qtd->status = 0; + return head; cleanup: - qtd_list_free(head); + qtd_list_free(urb, head); + return NULL; } static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { - struct isp1760_hcd *priv = hcd_to_priv(hcd); - struct list_head *ep_queue; - struct isp1760_qh *qh, *qhit; - unsigned long spinflags; - LIST_HEAD(new_qtds); - int retval; - int qh_in_queue; + struct list_head qtd_list; + packet_enqueue *pe; + + INIT_LIST_HEAD(&qtd_list); switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: - ep_queue = &priv->controlqhs; - break; case PIPE_BULK: - ep_queue = &priv->bulkqhs; + if (!qh_urb_transaction(hcd, urb, &qtd_list, mem_flags)) + return -ENOMEM; + pe = enqueue_an_ATL_packet; break; + case PIPE_INTERRUPT: - if (urb->interval < 0) - return -EINVAL; - /* FIXME: Check bandwidth */ - ep_queue = &priv->interruptqhs; + if (!qh_urb_transaction(hcd, urb, &qtd_list, mem_flags)) + return -ENOMEM; + pe = enqueue_an_INT_packet; break; + case PIPE_ISOCHRONOUS: - dev_err(hcd->self.controller, "%s: isochronous USB packets " - "not yet supported\n", - __func__); - return -EPIPE; + dev_err(hcd->self.controller, "PIPE_ISOCHRONOUS ain't supported\n"); default: - dev_err(hcd->self.controller, "%s: unknown pipe type\n", - __func__); return -EPIPE; } - if (usb_pipein(urb->pipe)) - urb->actual_length = 0; + return isp1760_prepare_enqueue(hcd, urb, &qtd_list, mem_flags, pe); +} - packetize_urb(hcd, urb, &new_qtds, mem_flags); - if (list_empty(&new_qtds)) - return -ENOMEM; - urb->hcpriv = NULL; /* Used to signal unlink to interrupt handler */ +static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + struct inter_packet_info *ints; + u32 i; + u32 reg_base, or_reg, skip_reg; + unsigned long flags; + struct ptd ptd; + packet_enqueue *pe; - retval = 0; - spin_lock_irqsave(&priv->lock, spinflags); + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + return -EPIPE; + break; - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - retval = -ESHUTDOWN; - goto out; + case PIPE_INTERRUPT: + ints = priv->int_ints; + reg_base = INT_PTD_OFFSET; + or_reg = HC_INT_IRQ_MASK_OR_REG; + skip_reg = HC_INT_PTD_SKIPMAP_REG; + pe = enqueue_an_INT_packet; + break; + + default: + ints = priv->atl_ints; + reg_base = ATL_PTD_OFFSET; + or_reg = HC_ATL_IRQ_MASK_OR_REG; + skip_reg = HC_ATL_PTD_SKIPMAP_REG; + pe = enqueue_an_ATL_packet; + break; } - retval = usb_hcd_link_urb_to_ep(hcd, urb); - if (retval) - goto out; - qh = urb->ep->hcpriv; - if (qh) { - qh_in_queue = 0; - list_for_each_entry(qhit, ep_queue, qh_list) { - if (qhit == qh) { - qh_in_queue = 1; - break; + memset(&ptd, 0, sizeof(ptd)); + spin_lock_irqsave(&priv->lock, flags); + + for (i = 0; i < 32; i++) { + if (!ints[i].qh) + continue; + BUG_ON(!ints[i].qtd); + + if (ints[i].qtd->urb == urb) { + u32 skip_map; + u32 or_map; + struct isp1760_qtd *qtd; + struct isp1760_qh *qh; + + skip_map = reg_read32(hcd->regs, skip_reg); + skip_map |= 1 << i; + reg_write32(hcd->regs, skip_reg, skip_map); + + or_map = reg_read32(hcd->regs, or_reg); + or_map &= ~(1 << i); + reg_write32(hcd->regs, or_reg, or_map); + + ptd_write(hcd->regs, reg_base, i, &ptd); + + qtd = ints[i].qtd; + qh = ints[i].qh; + + free_mem(hcd, qtd); + qtd = clean_up_qtdlist(qtd, qh); + + ints[i].qh = NULL; + ints[i].qtd = NULL; + + isp1760_urb_done(hcd, urb); + if (qtd) + pe(hcd, qh, qtd); + break; + + } else { + struct isp1760_qtd *qtd; + + list_for_each_entry(qtd, &ints[i].qtd->qtd_list, + qtd_list) { + if (qtd->urb == urb) { + clean_up_qtdlist(qtd, ints[i].qh); + isp1760_urb_done(hcd, urb); + qtd = NULL; + break; + } } + + /* We found the urb before the last slot */ + if (!qtd) + break; } - if (!qh_in_queue) - list_add_tail(&qh->qh_list, ep_queue); - } else { - qh = qh_alloc(GFP_ATOMIC); - if (!qh) { - retval = -ENOMEM; - goto out; - } - list_add_tail(&qh->qh_list, ep_queue); - urb->ep->hcpriv = qh; } - list_splice_tail(&new_qtds, &qh->qtd_list); - schedule_ptds(hcd); - -out: - spin_unlock_irqrestore(&priv->lock, spinflags); - return retval; + spin_unlock_irqrestore(&priv->lock, flags); + return 0; } -static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, - int status) +static irqreturn_t isp1760_irq(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - struct isp1760_qh *qh; - struct isp1760_qtd *qtd; - struct ptd ptd; - unsigned long spinflags; - int retval = 0; - - spin_lock_irqsave(&priv->lock, spinflags); + u32 imask; + irqreturn_t irqret = IRQ_NONE; - qh = urb->ep->hcpriv; - if (!qh) { - retval = -EINVAL; - goto out; - } + spin_lock(&priv->lock); - /* We need to forcefully reclaim the slot since some transfers never - return, e.g. interrupt transfers and NAKed bulk transfers. */ - if (qh->slot > -1) { - memset(&ptd, 0, sizeof(ptd)); - if (usb_pipebulk(urb->pipe)) { - priv->atl_slots[qh->slot].qh = NULL; - priv->atl_slots[qh->slot].qtd = NULL; - ptd_write(hcd->regs, ATL_PTD_OFFSET, qh->slot, &ptd); - } else { - priv->int_slots[qh->slot].qh = NULL; - priv->int_slots[qh->slot].qtd = NULL; - ptd_write(hcd->regs, INT_PTD_OFFSET, qh->slot, &ptd); - } - priv->active_ptds--; - qh->slot = -1; - } + if (!(hcd->state & HC_STATE_RUNNING)) + goto leave; - list_for_each_entry(qtd, &qh->qtd_list, qtd_list) { - if (qtd->urb == urb) - qtd->status = QTD_RETIRE; - } + imask = reg_read32(hcd->regs, HC_INTERRUPT_REG); + if (unlikely(!imask)) + goto leave; - urb->status = status; - schedule_ptds(hcd); + reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); + if (imask & (HC_ATL_INT | HC_SOT_INT)) + do_atl_int(hcd); -out: - spin_unlock_irqrestore(&priv->lock, spinflags); + if (imask & HC_INTL_INT) + do_intl_int(hcd); - return retval; + irqret = IRQ_HANDLED; +leave: + spin_unlock(&priv->lock); + return irqret; } static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf) @@ -1646,7 +1777,7 @@ static int check_reset_complete(struct usb_hcd *hcd, int index, /* if reset finished and it's still not enabled -- handoff */ if (!(port_status & PORT_PE)) { - dev_info(hcd->self.controller, + dev_err(hcd->self.controller, "port %d full speed --> companion\n", index + 1); @@ -1655,7 +1786,7 @@ static int check_reset_complete(struct usb_hcd *hcd, int index, reg_write32(hcd->regs, HC_PORTSC1, port_status); } else - dev_info(hcd->self.controller, "port %d high speed\n", + dev_err(hcd->self.controller, "port %d high speed\n", index + 1); return port_status; @@ -1933,32 +2064,43 @@ static void isp1760_endpoint_disable(struct usb_hcd *hcd, struct isp1760_hcd *priv = hcd_to_priv(hcd); struct isp1760_qh *qh; struct isp1760_qtd *qtd; - unsigned long spinflags; - int do_iter; + unsigned long flags; - spin_lock_irqsave(&priv->lock, spinflags); + spin_lock_irqsave(&priv->lock, flags); qh = ep->hcpriv; if (!qh) goto out; - do_iter = !list_empty(&qh->qtd_list); - while (do_iter) { - do_iter = 0; - list_for_each_entry(qtd, &qh->qtd_list, qtd_list) { - if (qtd->urb->ep == ep) { - spin_unlock_irqrestore(&priv->lock, spinflags); - isp1760_urb_dequeue(hcd, qtd->urb, -ECONNRESET); - spin_lock_irqsave(&priv->lock, spinflags); - do_iter = 1; - break; /* Restart iteration */ - } - } - } ep->hcpriv = NULL; - /* Cannot free qh here since it will be parsed by schedule_ptds() */ + do { + /* more than entry might get removed */ + if (list_empty(&qh->qtd_list)) + break; + + qtd = list_first_entry(&qh->qtd_list, struct isp1760_qtd, + qtd_list); + + if (qtd->status & URB_ENQUEUED) { + spin_unlock_irqrestore(&priv->lock, flags); + isp1760_urb_dequeue(hcd, qtd->urb, -ECONNRESET); + spin_lock_irqsave(&priv->lock, flags); + } else { + struct urb *urb; + + urb = qtd->urb; + clean_up_qtdlist(qtd, qh); + urb->status = -ECONNRESET; + isp1760_urb_done(hcd, urb); + } + } while (1); + qh_destroy(qh); + /* remove requests and leak them. + * ATL are pretty fast done, INT could take a while... + * The latter shoule be removed + */ out: - spin_unlock_irqrestore(&priv->lock, spinflags); + spin_unlock_irqrestore(&priv->lock, flags); } static int isp1760_get_frame(struct usb_hcd *hcd) @@ -2022,13 +2164,6 @@ static const struct hc_driver isp1760_hc_driver = { int __init init_kmem_once(void) { - urb_listitem_cachep = kmem_cache_create("isp1760 urb_listitem", - sizeof(struct urb_listitem), 0, SLAB_TEMPORARY | - SLAB_MEM_SPREAD, NULL); - - if (!urb_listitem_cachep) - return -ENOMEM; - qtd_cachep = kmem_cache_create("isp1760_qtd", sizeof(struct isp1760_qtd), 0, SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL); @@ -2051,7 +2186,6 @@ void deinit_kmem_cache(void) { kmem_cache_destroy(qtd_cachep); kmem_cache_destroy(qh_cachep); - kmem_cache_destroy(urb_listitem_cachep); } struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, diff --git a/trunk/drivers/usb/host/isp1760-hcd.h b/trunk/drivers/usb/host/isp1760-hcd.h index 014a7dfadf91..870507690607 100644 --- a/trunk/drivers/usb/host/isp1760-hcd.h +++ b/trunk/drivers/usb/host/isp1760-hcd.h @@ -49,9 +49,10 @@ void deinit_kmem_cache(void); #define SW_RESET_RESET_ALL (1 << 0) #define HC_BUFFER_STATUS_REG 0x334 -#define ISO_BUF_FILL (1 << 2) -#define INT_BUF_FILL (1 << 1) -#define ATL_BUF_FILL (1 << 0) +#define ATL_BUFFER 0x1 +#define INT_BUFFER 0x2 +#define ISO_BUFFER 0x4 +#define BUFFER_MAP 0x7 #define HC_MEMORY_REG 0x33c #define ISP_BANK(x) ((x) << 16) @@ -67,13 +68,14 @@ void deinit_kmem_cache(void); #define HC_INTERRUPT_REG 0x310 #define HC_INTERRUPT_ENABLE 0x314 +#define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) +#define INTERRUPT_ENABLE_SOT_MASK (HC_INTL_INT | HC_SOT_INT | HC_EOT_INT) + #define HC_ISO_INT (1 << 9) #define HC_ATL_INT (1 << 8) #define HC_INTL_INT (1 << 7) #define HC_EOT_INT (1 << 3) #define HC_SOT_INT (1 << 1) -#define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT) -#define INTERRUPT_ENABLE_SOT_MASK (HC_SOT_INT) #define HC_ISO_IRQ_MASK_OR_REG 0x318 #define HC_INT_IRQ_MASK_OR_REG 0x31C @@ -104,7 +106,7 @@ struct ptd { #define ATL_PTD_OFFSET 0x0c00 #define PAYLOAD_OFFSET 0x1000 -struct slotinfo { +struct inter_packet_info { struct isp1760_qh *qh; struct isp1760_qtd *qtd; }; @@ -154,52 +156,54 @@ struct memory_chunk { /* ATL */ /* DW0 */ -#define DW0_VALID_BIT 1 -#define FROM_DW0_VALID(x) ((x) & 0x01) -#define TO_DW0_LENGTH(x) (((u32) x) << 3) -#define TO_DW0_MAXPACKET(x) (((u32) x) << 18) -#define TO_DW0_MULTI(x) (((u32) x) << 29) -#define TO_DW0_ENDPOINT(x) (((u32) x) << 31) +#define PTD_VALID 1 +#define PTD_LENGTH(x) (((u32) x) << 3) +#define PTD_MAXPACKET(x) (((u32) x) << 18) +#define PTD_MULTI(x) (((u32) x) << 29) +#define PTD_ENDPOINT(x) (((u32) x) << 31) /* DW1 */ -#define TO_DW1_DEVICE_ADDR(x) (((u32) x) << 3) -#define TO_DW1_PID_TOKEN(x) (((u32) x) << 10) -#define DW1_TRANS_BULK ((u32) 2 << 12) -#define DW1_TRANS_INT ((u32) 3 << 12) -#define DW1_TRANS_SPLIT ((u32) 1 << 14) -#define DW1_SE_USB_LOSPEED ((u32) 2 << 16) -#define TO_DW1_PORT_NUM(x) (((u32) x) << 18) -#define TO_DW1_HUB_NUM(x) (((u32) x) << 25) +#define PTD_DEVICE_ADDR(x) (((u32) x) << 3) +#define PTD_PID_TOKEN(x) (((u32) x) << 10) +#define PTD_TRANS_BULK ((u32) 2 << 12) +#define PTD_TRANS_INT ((u32) 3 << 12) +#define PTD_TRANS_SPLIT ((u32) 1 << 14) +#define PTD_SE_USB_LOSPEED ((u32) 2 << 16) +#define PTD_PORT_NUM(x) (((u32) x) << 18) +#define PTD_HUB_NUM(x) (((u32) x) << 25) +#define PTD_PING(x) (((u32) x) << 26) /* DW2 */ -#define TO_DW2_DATA_START_ADDR(x) (((u32) x) << 8) -#define TO_DW2_RL(x) ((x) << 25) -#define FROM_DW2_RL(x) (((x) >> 25) & 0xf) +#define PTD_RL_CNT(x) (((u32) x) << 25) +#define PTD_DATA_START_ADDR(x) (((u32) x) << 8) +#define BASE_ADDR 0x1000 /* DW3 */ -#define FROM_DW3_NRBYTESTRANSFERRED(x) ((x) & 0x7fff) -#define FROM_DW3_SCS_NRBYTESTRANSFERRED(x) ((x) & 0x07ff) -#define TO_DW3_NAKCOUNT(x) ((x) << 19) -#define FROM_DW3_NAKCOUNT(x) (((x) >> 19) & 0xf) -#define TO_DW3_CERR(x) ((x) << 23) -#define FROM_DW3_CERR(x) (((x) >> 23) & 0x3) -#define TO_DW3_DATA_TOGGLE(x) ((x) << 25) -#define FROM_DW3_DATA_TOGGLE(x) (((x) >> 25) & 0x1) -#define TO_DW3_PING(x) ((x) << 26) -#define FROM_DW3_PING(x) (((x) >> 26) & 0x1) -#define DW3_ERROR_BIT (1 << 28) -#define DW3_BABBLE_BIT (1 << 29) +#define PTD_CERR(x) (((u32) x) << 23) +#define PTD_NAC_CNT(x) (((u32) x) << 19) +#define PTD_ACTIVE ((u32) 1 << 31) +#define PTD_DATA_TOGGLE(x) (((u32) x) << 25) + #define DW3_HALT_BIT (1 << 30) -#define DW3_ACTIVE_BIT (1 << 31) +#define DW3_ERROR_BIT (1 << 28) +#define DW3_QTD_ACTIVE (1 << 31) #define INT_UNDERRUN (1 << 2) #define INT_BABBLE (1 << 1) #define INT_EXACT (1 << 0) +#define DW1_GET_PID(x) (((x) >> 10) & 0x3) +#define PTD_XFERRED_LENGTH(x) ((x) & 0x7fff) +#define PTD_XFERRED_LENGTH_LO(x) ((x) & 0x7ff) + #define SETUP_PID (2) #define IN_PID (1) #define OUT_PID (0) +#define GET_QTD_TOKEN_TYPE(x) ((x) & 0x3) + +#define DATA_TOGGLE (1 << 31) +#define GET_DATA_TOGGLE(x) ((x) >> 31) /* Errata 1 */ #define RL_COUNTER (0) #define NAK_COUNTER (0) #define ERR_COUNTER (2) -#endif /* _ISP1760_HCD_H_ */ +#endif diff --git a/trunk/drivers/usb/host/xhci-dbg.c b/trunk/drivers/usb/host/xhci-dbg.c index 0231814a97a5..2e0486178dbe 100644 --- a/trunk/drivers/usb/host/xhci-dbg.c +++ b/trunk/drivers/usb/host/xhci-dbg.c @@ -147,7 +147,7 @@ static void xhci_print_op_regs(struct xhci_hcd *xhci) static void xhci_print_ports(struct xhci_hcd *xhci) { - u32 __iomem *addr; + __le32 __iomem *addr; int i, j; int ports; char *names[NUM_PORT_REGS] = { @@ -253,27 +253,27 @@ void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb) void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) { u64 address; - u32 type = xhci_readl(xhci, &trb->link.control) & TRB_TYPE_BITMASK; + u32 type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK; switch (type) { case TRB_TYPE(TRB_LINK): xhci_dbg(xhci, "Link TRB:\n"); xhci_print_trb_offsets(xhci, trb); - address = trb->link.segment_ptr; + address = le64_to_cpu(trb->link.segment_ptr); xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address); xhci_dbg(xhci, "Interrupter target = 0x%x\n", - GET_INTR_TARGET(trb->link.intr_target)); + GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target))); xhci_dbg(xhci, "Cycle bit = %u\n", - (unsigned int) (trb->link.control & TRB_CYCLE)); + (unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE)); xhci_dbg(xhci, "Toggle cycle bit = %u\n", - (unsigned int) (trb->link.control & LINK_TOGGLE)); + (unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE)); xhci_dbg(xhci, "No Snoop bit = %u\n", - (unsigned int) (trb->link.control & TRB_NO_SNOOP)); + (unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP)); break; case TRB_TYPE(TRB_TRANSFER): - address = trb->trans_event.buffer; + address = le64_to_cpu(trb->trans_event.buffer); /* * FIXME: look at flags to figure out if it's an address or if * the data is directly in the buffer field. @@ -281,11 +281,12 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address); break; case TRB_TYPE(TRB_COMPLETION): - address = trb->event_cmd.cmd_trb; + address = le64_to_cpu(trb->event_cmd.cmd_trb); xhci_dbg(xhci, "Command TRB pointer = %llu\n", address); xhci_dbg(xhci, "Completion status = %u\n", - (unsigned int) GET_COMP_CODE(trb->event_cmd.status)); - xhci_dbg(xhci, "Flags = 0x%x\n", (unsigned int) trb->event_cmd.flags); + (unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status))); + xhci_dbg(xhci, "Flags = 0x%x\n", + (unsigned int) le32_to_cpu(trb->event_cmd.flags)); break; default: xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n", @@ -311,16 +312,16 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg) { int i; - u32 addr = (u32) seg->dma; + u64 addr = seg->dma; union xhci_trb *trb = seg->trbs; for (i = 0; i < TRBS_PER_SEGMENT; ++i) { trb = &seg->trbs[i]; - xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr, - lower_32_bits(trb->link.segment_ptr), - upper_32_bits(trb->link.segment_ptr), - (unsigned int) trb->link.intr_target, - (unsigned int) trb->link.control); + xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr, + (u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)), + (u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)), + (unsigned int) le32_to_cpu(trb->link.intr_target), + (unsigned int) le32_to_cpu(trb->link.control)); addr += sizeof(*trb); } } @@ -391,18 +392,18 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci, void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) { - u32 addr = (u32) erst->erst_dma_addr; + u64 addr = erst->erst_dma_addr; int i; struct xhci_erst_entry *entry; for (i = 0; i < erst->num_entries; ++i) { entry = &erst->entries[i]; - xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", - (unsigned int) addr, - lower_32_bits(entry->seg_addr), - upper_32_bits(entry->seg_addr), - (unsigned int) entry->seg_size, - (unsigned int) entry->rsvd); + xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", + addr, + lower_32_bits(le64_to_cpu(entry->seg_addr)), + upper_32_bits(le64_to_cpu(entry->seg_addr)), + (unsigned int) le32_to_cpu(entry->seg_size), + (unsigned int) le32_to_cpu(entry->rsvd)); addr += sizeof(*entry); } } @@ -436,7 +437,7 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci, { struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); - switch (GET_SLOT_STATE(slot_ctx->dev_state)) { + switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) { case 0: return "enabled/disabled"; case 1: diff --git a/trunk/drivers/usb/host/xhci-hub.c b/trunk/drivers/usb/host/xhci-hub.c index a78f2ebd11b7..ae1d24cb9303 100644 --- a/trunk/drivers/usb/host/xhci-hub.c +++ b/trunk/drivers/usb/host/xhci-hub.c @@ -50,7 +50,7 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, temp |= 0x0008; /* Bits 6:5 - no TTs in root ports */ /* Bit 7 - no port indicators */ - desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp); + desc->wHubCharacteristics = cpu_to_le16(temp); } /* Fill in the USB 2.0 roothub descriptor */ @@ -314,7 +314,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) } static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, - u16 wIndex, u32 __iomem *addr, u32 port_status) + u16 wIndex, __le32 __iomem *addr, u32 port_status) { /* Don't allow the USB core to disable SuperSpeed ports. */ if (hcd->speed == HCD_USB3) { @@ -331,7 +331,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, } static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, - u16 wIndex, u32 __iomem *addr, u32 port_status) + u16 wIndex, __le32 __iomem *addr, u32 port_status) { char *port_change_bit; u32 status; @@ -376,7 +376,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, unsigned long flags; u32 temp, temp1, status; int retval = 0; - u32 __iomem **port_array; + __le32 __iomem **port_array; int slot_id; struct xhci_bus_state *bus_state; @@ -664,7 +664,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) int i, retval; struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ports; - u32 __iomem **port_array; + __le32 __iomem **port_array; struct xhci_bus_state *bus_state; if (hcd->speed == HCD_USB3) { @@ -709,7 +709,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); int max_ports, port_index; - u32 __iomem **port_array; + __le32 __iomem **port_array; struct xhci_bus_state *bus_state; unsigned long flags; @@ -779,7 +779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) if (DEV_HIGHSPEED(t1)) { /* enable remote wake up for USB 2.0 */ - u32 __iomem *addr; + __le32 __iomem *addr; u32 tmp; /* Add one to the port status register address to get @@ -801,7 +801,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); int max_ports, port_index; - u32 __iomem **port_array; + __le32 __iomem **port_array; struct xhci_bus_state *bus_state; u32 temp; unsigned long flags; @@ -875,7 +875,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) if (DEV_HIGHSPEED(temp)) { /* disable remote wake up for USB 2.0 */ - u32 __iomem *addr; + __le32 __iomem *addr; u32 tmp; /* Add one to the port status register address to get diff --git a/trunk/drivers/usb/host/xhci-mem.c b/trunk/drivers/usb/host/xhci-mem.c index 627f3438028c..500ec7a9eb8a 100644 --- a/trunk/drivers/usb/host/xhci-mem.c +++ b/trunk/drivers/usb/host/xhci-mem.c @@ -89,16 +89,17 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, return; prev->next = next; if (link_trbs) { - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma; + prev->trbs[TRBS_PER_SEGMENT-1].link. + segment_ptr = cpu_to_le64(next->dma); /* Set the last TRB in the segment to have a TRB type ID of Link TRB */ - val = prev->trbs[TRBS_PER_SEGMENT-1].link.control; + val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); val &= ~TRB_TYPE_BITMASK; val |= TRB_TYPE(TRB_LINK); /* Always set the chain bit with 0.95 hardware */ if (xhci_link_trb_quirk(xhci)) val |= TRB_CHAIN; - prev->trbs[TRBS_PER_SEGMENT-1].link.control = val; + prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); } xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n", (unsigned long long)prev->dma, @@ -186,7 +187,8 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, if (link_trbs) { /* See section 4.9.2.1 and 6.4.4.1 */ - prev->trbs[TRBS_PER_SEGMENT-1].link.control |= (LINK_TOGGLE); + prev->trbs[TRBS_PER_SEGMENT-1].link. + control |= cpu_to_le32(LINK_TOGGLE); xhci_dbg(xhci, "Wrote link toggle flag to" " segment %p (virtual), 0x%llx (DMA)\n", prev, (unsigned long long)prev->dma); @@ -548,7 +550,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, addr = cur_ring->first_seg->dma | SCT_FOR_CTX(SCT_PRI_TR) | cur_ring->cycle_state; - stream_info->stream_ctx_array[cur_stream].stream_ring = addr; + stream_info->stream_ctx_array[cur_stream]. + stream_ring = cpu_to_le64(addr); xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n", cur_stream, (unsigned long long) addr); @@ -614,10 +617,10 @@ void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci, max_primary_streams = fls(stream_info->num_stream_ctxs) - 2; xhci_dbg(xhci, "Setting number of stream ctx array entries to %u\n", 1 << (max_primary_streams + 1)); - ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK; - ep_ctx->ep_info |= EP_MAXPSTREAMS(max_primary_streams); - ep_ctx->ep_info |= EP_HAS_LSA; - ep_ctx->deq = stream_info->ctx_array_dma; + ep_ctx->ep_info &= cpu_to_le32(~EP_MAXPSTREAMS_MASK); + ep_ctx->ep_info |= cpu_to_le32(EP_MAXPSTREAMS(max_primary_streams) + | EP_HAS_LSA); + ep_ctx->deq = cpu_to_le64(stream_info->ctx_array_dma); } /* @@ -630,10 +633,9 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci, struct xhci_virt_ep *ep) { dma_addr_t addr; - ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK; - ep_ctx->ep_info &= ~EP_HAS_LSA; + ep_ctx->ep_info &= cpu_to_le32(~(EP_MAXPSTREAMS_MASK | EP_HAS_LSA)); addr = xhci_trb_virt_to_dma(ep->ring->deq_seg, ep->ring->dequeue); - ep_ctx->deq = addr | ep->ring->cycle_state; + ep_ctx->deq = cpu_to_le64(addr | ep->ring->cycle_state); } /* Frees all stream contexts associated with the endpoint, @@ -781,11 +783,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, dev->udev = udev; /* Point to output device context in dcbaa. */ - xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; + xhci->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(dev->out_ctx->dma); xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", - slot_id, - &xhci->dcbaa->dev_context_ptrs[slot_id], - (unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]); + slot_id, + &xhci->dcbaa->dev_context_ptrs[slot_id], + (unsigned long long) le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id])); return 1; fail: @@ -810,8 +812,9 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * configured device has reset, so all control transfers should have * been completed or cancelled before the reset. */ - ep0_ctx->deq = xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue); - ep0_ctx->deq |= ep_ring->cycle_state; + ep0_ctx->deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring->enq_seg, + ep_ring->enqueue) + | ep_ring->cycle_state); } /* @@ -885,24 +888,22 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx); /* 2) New slot context and endpoint 0 context are valid*/ - ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG; + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); /* 3) Only the control endpoint is valid - one endpoint context */ - slot_ctx->dev_info |= LAST_CTX(1); - - slot_ctx->dev_info |= (u32) udev->route; + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route); switch (udev->speed) { case USB_SPEED_SUPER: - slot_ctx->dev_info |= (u32) SLOT_SPEED_SS; + slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_SS); break; case USB_SPEED_HIGH: - slot_ctx->dev_info |= (u32) SLOT_SPEED_HS; + slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_HS); break; case USB_SPEED_FULL: - slot_ctx->dev_info |= (u32) SLOT_SPEED_FS; + slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_FS); break; case USB_SPEED_LOW: - slot_ctx->dev_info |= (u32) SLOT_SPEED_LS; + slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_LS); break; case USB_SPEED_WIRELESS: xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); @@ -916,7 +917,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud port_num = xhci_find_real_port_number(xhci, udev); if (!port_num) return -EINVAL; - slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(port_num); + slot_ctx->dev_info2 |= cpu_to_le32((u32) ROOT_HUB_PORT(port_num)); /* Set the port number in the virtual_device to the faked port number */ for (top_dev = udev; top_dev->parent && top_dev->parent->parent; top_dev = top_dev->parent) @@ -927,31 +928,31 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud /* Is this a LS/FS device under an external HS hub? */ if (udev->tt && udev->tt->hub->parent) { - slot_ctx->tt_info = udev->tt->hub->slot_id; - slot_ctx->tt_info |= udev->ttport << 8; + slot_ctx->tt_info = cpu_to_le32(udev->tt->hub->slot_id | + (udev->ttport << 8)); if (udev->tt->multi) - slot_ctx->dev_info |= DEV_MTT; + slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); } xhci_dbg(xhci, "udev->tt = %p\n", udev->tt); xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport); /* Step 4 - ring already allocated */ /* Step 5 */ - ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP); + ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); /* * XXX: Not sure about wireless USB devices. */ switch (udev->speed) { case USB_SPEED_SUPER: - ep0_ctx->ep_info2 |= MAX_PACKET(512); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512)); break; case USB_SPEED_HIGH: /* USB core guesses at a 64-byte max packet first for FS devices */ case USB_SPEED_FULL: - ep0_ctx->ep_info2 |= MAX_PACKET(64); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64)); break; case USB_SPEED_LOW: - ep0_ctx->ep_info2 |= MAX_PACKET(8); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8)); break; case USB_SPEED_WIRELESS: xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); @@ -962,12 +963,10 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud BUG(); } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ - ep0_ctx->ep_info2 |= MAX_BURST(0); - ep0_ctx->ep_info2 |= ERROR_COUNT(3); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); - ep0_ctx->deq = - dev->eps[0].ring->first_seg->dma; - ep0_ctx->deq |= dev->eps[0].ring->cycle_state; + ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma | + dev->eps[0].ring->cycle_state); /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ @@ -1133,8 +1132,8 @@ static u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci, if (udev->speed == USB_SPEED_SUPER) return ep->ss_ep_comp.wBytesPerInterval; - max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize); - max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; + max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize)); + max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) & 0x1800) >> 11; /* A 0 in max burst means 1 transfer per ESIT */ return max_packet * (max_burst + 1); } @@ -1183,10 +1182,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, } virt_dev->eps[ep_index].skip = false; ep_ring = virt_dev->eps[ep_index].new_ring; - ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; + ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma | ep_ring->cycle_state); - ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); - ep_ctx->ep_info |= EP_MULT(xhci_get_endpoint_mult(udev, ep)); + ep_ctx->ep_info = cpu_to_le32(xhci_get_endpoint_interval(udev, ep) + | EP_MULT(xhci_get_endpoint_mult(udev, ep))); /* FIXME dig Mult and streams info out of ep companion desc */ @@ -1194,22 +1193,22 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, * error count = 0 means infinite retries. */ if (!usb_endpoint_xfer_isoc(&ep->desc)) - ep_ctx->ep_info2 = ERROR_COUNT(3); + ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(3)); else - ep_ctx->ep_info2 = ERROR_COUNT(1); + ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(1)); - ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep); + ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep)); /* Set the max packet size and max burst */ switch (udev->speed) { case USB_SPEED_SUPER: - max_packet = ep->desc.wMaxPacketSize; - ep_ctx->ep_info2 |= MAX_PACKET(max_packet); + max_packet = le16_to_cpu(ep->desc.wMaxPacketSize); + ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); /* dig out max burst from ep companion desc */ max_packet = ep->ss_ep_comp.bMaxBurst; if (!max_packet) xhci_warn(xhci, "WARN no SS endpoint bMaxBurst\n"); - ep_ctx->ep_info2 |= MAX_BURST(max_packet); + ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet)); break; case USB_SPEED_HIGH: /* bits 11:12 specify the number of additional transaction @@ -1217,20 +1216,21 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, */ if (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) { - max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; - ep_ctx->ep_info2 |= MAX_BURST(max_burst); + max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) + & 0x1800) >> 11; + ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst)); } /* Fall through */ case USB_SPEED_FULL: case USB_SPEED_LOW: - max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize); - ep_ctx->ep_info2 |= MAX_PACKET(max_packet); + max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize)); + ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); break; default: BUG(); } max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep); - ep_ctx->tx_info = MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload); + ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload)); /* * XXX no idea how to calculate the average TRB buffer length for bulk @@ -1247,7 +1247,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, * use Event Data TRBs, and we don't chain in a link TRB on short * transfers, we're basically dividing by 1. */ - ep_ctx->tx_info |= AVG_TRB_LENGTH_FOR_EP(max_esit_payload); + ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload)); /* FIXME Debug endpoint context */ return 0; @@ -1347,7 +1347,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) if (!xhci->scratchpad->sp_dma_buffers) goto fail_sp4; - xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma; + xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); for (i = 0; i < num_sp; i++) { dma_addr_t dma; void *buf = pci_alloc_consistent(to_pci_dev(dev), @@ -1724,7 +1724,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) } static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, - u32 __iomem *addr, u8 major_revision) + __le32 __iomem *addr, u8 major_revision) { u32 temp, port_offset, port_count; int i; @@ -1789,7 +1789,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, */ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) { - u32 __iomem *addr; + __le32 __iomem *addr; u32 offset; unsigned int num_ports; int i, port_index; @@ -2042,8 +2042,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) /* set ring base address and size for each segment table entry */ for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { struct xhci_erst_entry *entry = &xhci->erst.entries[val]; - entry->seg_addr = seg->dma; - entry->seg_size = TRBS_PER_SEGMENT; + entry->seg_addr = cpu_to_le64(seg->dma); + entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; seg = seg->next; } diff --git a/trunk/drivers/usb/host/xhci-ring.c b/trunk/drivers/usb/host/xhci-ring.c index 7437386a9a50..9b1eeb04ce69 100644 --- a/trunk/drivers/usb/host/xhci-ring.c +++ b/trunk/drivers/usb/host/xhci-ring.c @@ -100,7 +100,7 @@ static bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring *ring, return (trb == &seg->trbs[TRBS_PER_SEGMENT]) && (seg->next == xhci->event_ring->first_seg); else - return trb->link.control & LINK_TOGGLE; + return le32_to_cpu(trb->link.control) & LINK_TOGGLE; } /* Is this TRB a link TRB or was the last TRB the last TRB in this event ring @@ -113,13 +113,15 @@ static int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, if (ring == xhci->event_ring) return trb == &seg->trbs[TRBS_PER_SEGMENT]; else - return (trb->link.control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK); + return (le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK) + == TRB_TYPE(TRB_LINK); } static int enqueue_is_link_trb(struct xhci_ring *ring) { struct xhci_link_trb *link = &ring->enqueue->link; - return ((link->control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)); + return ((le32_to_cpu(link->control) & TRB_TYPE_BITMASK) == + TRB_TYPE(TRB_LINK)); } /* Updates trb to point to the next TRB in the ring, and updates seg if the next @@ -197,7 +199,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, union xhci_trb *next; unsigned long long addr; - chain = ring->enqueue->generic.field[3] & TRB_CHAIN; + chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN; next = ++(ring->enqueue); ring->enq_updates++; @@ -223,12 +225,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, * (which may mean the chain bit is cleared). */ if (!xhci_link_trb_quirk(xhci)) { - next->link.control &= ~TRB_CHAIN; - next->link.control |= chain; + next->link.control &= + cpu_to_le32(~TRB_CHAIN); + next->link.control |= + cpu_to_le32(chain); } /* Give this link TRB to the hardware */ wmb(); - next->link.control ^= TRB_CYCLE; + next->link.control ^= cpu_to_le32(TRB_CYCLE); } /* Toggle the cycle bit after the last ring segment. */ if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) { @@ -319,7 +323,7 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int ep_index, unsigned int stream_id) { - __u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id]; + __le32 __iomem *db_addr = &xhci->dba->doorbell[slot_id]; struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; unsigned int ep_state = ep->ep_state; @@ -380,7 +384,7 @@ static struct xhci_segment *find_trb_seg( while (cur_seg->trbs > trb || &cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) { generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic; - if (generic_trb->field[3] & LINK_TOGGLE) + if (le32_to_cpu(generic_trb->field[3]) & LINK_TOGGLE) *cycle_state ^= 0x1; cur_seg = cur_seg->next; if (cur_seg == start_seg) @@ -447,6 +451,10 @@ static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, * any link TRBs with the toggle cycle bit set. * - Finally we move the dequeue state one TRB further, toggling the cycle bit * if we've moved it past a link TRB with the toggle cycle bit set. + * + * Some of the uses of xhci_generic_trb are grotty, but if they're done + * with correct __le32 accesses they should work fine. Only users of this are + * in here. */ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, @@ -480,7 +488,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, /* Dig out the cycle state saved by the xHC during the stop ep cmd */ xhci_dbg(xhci, "Finding endpoint context\n"); ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); - state->new_cycle_state = 0x1 & ep_ctx->deq; + state->new_cycle_state = 0x1 & le64_to_cpu(ep_ctx->deq); state->new_deq_ptr = cur_td->last_trb; xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n"); @@ -493,8 +501,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, } trb = &state->new_deq_ptr->generic; - if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) && - (trb->field[3] & LINK_TOGGLE)) + if ((le32_to_cpu(trb->field[3]) & TRB_TYPE_BITMASK) == + TRB_TYPE(TRB_LINK) && (le32_to_cpu(trb->field[3]) & LINK_TOGGLE)) state->new_cycle_state ^= 0x1; next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr); @@ -529,12 +537,12 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, for (cur_seg = cur_td->start_seg, cur_trb = cur_td->first_trb; true; next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { - if ((cur_trb->generic.field[3] & TRB_TYPE_BITMASK) == - TRB_TYPE(TRB_LINK)) { + if ((le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK) + == TRB_TYPE(TRB_LINK)) { /* Unchain any chained Link TRBs, but * leave the pointers intact. */ - cur_trb->generic.field[3] &= ~TRB_CHAIN; + cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN); xhci_dbg(xhci, "Cancel (unchain) link TRB\n"); xhci_dbg(xhci, "Address = %p (0x%llx dma); " "in seg %p (0x%llx dma)\n", @@ -547,8 +555,9 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, cur_trb->generic.field[1] = 0; cur_trb->generic.field[2] = 0; /* Preserve only the cycle bit of this TRB */ - cur_trb->generic.field[3] &= TRB_CYCLE; - cur_trb->generic.field[3] |= TRB_TYPE(TRB_TR_NOOP); + cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE); + cur_trb->generic.field[3] |= cpu_to_le32( + TRB_TYPE(TRB_TR_NOOP)); xhci_dbg(xhci, "Cancel TRB %p (0x%llx dma) " "in seg %p (0x%llx dma)\n", cur_trb, @@ -662,9 +671,9 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, struct xhci_dequeue_state deq_state; if (unlikely(TRB_TO_SUSPEND_PORT( - xhci->cmd_ring->dequeue->generic.field[3]))) { + le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])))) { slot_id = TRB_TO_SLOT_ID( - xhci->cmd_ring->dequeue->generic.field[3]); + le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])); virt_dev = xhci->devs[slot_id]; if (virt_dev) handle_cmd_in_cmd_wait_list(xhci, virt_dev, @@ -677,8 +686,8 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, } memset(&deq_state, 0, sizeof(deq_state)); - slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); - ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3])); + ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); ep = &xhci->devs[slot_id]->eps[ep_index]; if (list_empty(&ep->cancelled_td_list)) { @@ -910,9 +919,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; - slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); - ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); - stream_id = TRB_TO_STREAM_ID(trb->generic.field[2]); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3])); + ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); + stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2])); dev = xhci->devs[slot_id]; ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id); @@ -928,11 +937,11 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); - if (GET_COMP_CODE(event->status) != COMP_SUCCESS) { + if (GET_COMP_CODE(le32_to_cpu(event->status)) != COMP_SUCCESS) { unsigned int ep_state; unsigned int slot_state; - switch (GET_COMP_CODE(event->status)) { + switch (GET_COMP_CODE(le32_to_cpu(event->status))) { case COMP_TRB_ERR: xhci_warn(xhci, "WARN Set TR Deq Ptr cmd invalid because " "of stream ID configuration\n"); @@ -940,9 +949,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, case COMP_CTX_STATE: xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due " "to incorrect slot or ep state.\n"); - ep_state = ep_ctx->ep_info; + ep_state = le32_to_cpu(ep_ctx->ep_info); ep_state &= EP_STATE_MASK; - slot_state = slot_ctx->dev_state; + slot_state = le32_to_cpu(slot_ctx->dev_state); slot_state = GET_SLOT_STATE(slot_state); xhci_dbg(xhci, "Slot state = %u, EP state = %u\n", slot_state, ep_state); @@ -954,7 +963,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, default: xhci_warn(xhci, "WARN Set TR Deq Ptr cmd with unknown " "completion code of %u.\n", - GET_COMP_CODE(event->status)); + GET_COMP_CODE(le32_to_cpu(event->status))); break; } /* OK what do we do now? The endpoint state is hosed, and we @@ -965,10 +974,10 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, */ } else { xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", - ep_ctx->deq); + le64_to_cpu(ep_ctx->deq)); if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg, - dev->eps[ep_index].queued_deq_ptr) == - (ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) { + dev->eps[ep_index].queued_deq_ptr) == + (le64_to_cpu(ep_ctx->deq) & ~(EP_CTX_CYCLE_MASK))) { /* Update the ring's dequeue segment and dequeue pointer * to reflect the new position. */ @@ -997,13 +1006,13 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci, int slot_id; unsigned int ep_index; - slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); - ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3])); + ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); /* This command will only fail if the endpoint wasn't halted, * but we don't care. */ xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n", - (unsigned int) GET_COMP_CODE(event->status)); + (unsigned int) GET_COMP_CODE(le32_to_cpu(event->status))); /* HW with the reset endpoint quirk needs to have a configure endpoint * command complete before the endpoint can be used. Queue that here @@ -1040,8 +1049,7 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, if (xhci->cmd_ring->dequeue != command->command_trb) return 0; - command->status = - GET_COMP_CODE(event->status); + command->status = GET_COMP_CODE(le32_to_cpu(event->status)); list_del(&command->cmd_list); if (command->completion) complete(command->completion); @@ -1053,7 +1061,7 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { - int slot_id = TRB_TO_SLOT_ID(event->flags); + int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); u64 cmd_dma; dma_addr_t cmd_dequeue_dma; struct xhci_input_control_ctx *ctrl_ctx; @@ -1062,7 +1070,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_ring *ep_ring; unsigned int ep_state; - cmd_dma = event->cmd_trb; + cmd_dma = le64_to_cpu(event->cmd_trb); cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, xhci->cmd_ring->dequeue); /* Is the command ring deq ptr out of sync with the deq seg ptr? */ @@ -1075,9 +1083,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci->error_bitmask |= 1 << 5; return; } - switch (xhci->cmd_ring->dequeue->generic.field[3] & TRB_TYPE_BITMASK) { + switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) + & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): - if (GET_COMP_CODE(event->status) == COMP_SUCCESS) + if (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_SUCCESS) xhci->slot_id = slot_id; else xhci->slot_id = 0; @@ -1102,7 +1111,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); /* Input ctx add_flags are the endpoint index plus one */ - ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1; + ep_index = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags)) - 1; /* A usb_set_interface() call directly after clearing a halted * condition may race on this quirky hardware. Not worth * worrying about, since this is prototype hardware. Not sure @@ -1111,8 +1120,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, */ if (xhci->quirks & XHCI_RESET_EP_QUIRK && ep_index != (unsigned int) -1 && - ctrl_ctx->add_flags - SLOT_FLAG == - ctrl_ctx->drop_flags) { + le32_to_cpu(ctrl_ctx->add_flags) - SLOT_FLAG == + le32_to_cpu(ctrl_ctx->drop_flags)) { ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state; if (!(ep_state & EP_HALTED)) @@ -1129,18 +1138,18 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, bandwidth_change: xhci_dbg(xhci, "Completed config ep cmd\n"); xhci->devs[slot_id]->cmd_status = - GET_COMP_CODE(event->status); + GET_COMP_CODE(le32_to_cpu(event->status)); complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_EVAL_CONTEXT): virt_dev = xhci->devs[slot_id]; if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) break; - xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); + xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_ADDR_DEV): - xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); + xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); complete(&xhci->addr_dev); break; case TRB_TYPE(TRB_STOP_RING): @@ -1157,7 +1166,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, case TRB_TYPE(TRB_RESET_DEV): xhci_dbg(xhci, "Completed reset device command.\n"); slot_id = TRB_TO_SLOT_ID( - xhci->cmd_ring->dequeue->generic.field[3]); + le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])); virt_dev = xhci->devs[slot_id]; if (virt_dev) handle_cmd_in_cmd_wait_list(xhci, virt_dev, event); @@ -1171,8 +1180,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, break; } xhci_dbg(xhci, "NEC firmware version %2x.%02x\n", - NEC_FW_MAJOR(event->status), - NEC_FW_MINOR(event->status)); + NEC_FW_MAJOR(le32_to_cpu(event->status)), + NEC_FW_MINOR(le32_to_cpu(event->status))); break; default: /* Skip over unknown commands on the event ring */ @@ -1187,7 +1196,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci, { u32 trb_type; - trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]); + trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->generic.field[3])); xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type); if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST)) handle_cmd_completion(xhci, &event->event_cmd); @@ -1241,15 +1250,15 @@ static void handle_port_status(struct xhci_hcd *xhci, unsigned int faked_port_index; u8 major_revision; struct xhci_bus_state *bus_state; - u32 __iomem **port_array; + __le32 __iomem **port_array; bool bogus_port_status = false; /* Port status change events always have a successful completion code */ - if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) { + if (GET_COMP_CODE(le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS) { xhci_warn(xhci, "WARN: xHC returned failed port status event\n"); xhci->error_bitmask |= 1 << 8; } - port_id = GET_PORT_ID(event->generic.field[0]); + port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0])); xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id); max_ports = HCS_MAX_PORTS(xhci->hcs_params1); @@ -1456,7 +1465,7 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci, * endpoint anyway. Check if a babble halted the * endpoint. */ - if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_HALTED) + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED) return 1; return 0; @@ -1494,12 +1503,12 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, struct urb_priv *urb_priv; u32 trb_comp_code; - slot_id = TRB_TO_SLOT_ID(event->flags); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); xdev = xhci->devs[slot_id]; - ep_index = TRB_TO_EP_ID(event->flags) - 1; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); + ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1; + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); - trb_comp_code = GET_COMP_CODE(event->transfer_len); + trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); if (skip) goto td_cleanup; @@ -1602,12 +1611,12 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, struct xhci_ep_ctx *ep_ctx; u32 trb_comp_code; - slot_id = TRB_TO_SLOT_ID(event->flags); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); xdev = xhci->devs[slot_id]; - ep_index = TRB_TO_EP_ID(event->flags) - 1; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); + ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1; + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); - trb_comp_code = GET_COMP_CODE(event->transfer_len); + trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); xhci_debug_trb(xhci, xhci->event_ring->dequeue); switch (trb_comp_code) { @@ -1646,7 +1655,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, event_trb != td->last_trb) td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(event->transfer_len); + - TRB_LEN(le32_to_cpu(event->transfer_len)); else td->urb->actual_length = 0; @@ -1680,7 +1689,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, /* We didn't stop on a link TRB in the middle */ td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(event->transfer_len); + TRB_LEN(le32_to_cpu(event->transfer_len)); xhci_dbg(xhci, "Waiting for status " "stage event\n"); return 0; @@ -1708,8 +1717,8 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, u32 trb_comp_code; bool skip_td = false; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); - trb_comp_code = GET_COMP_CODE(event->transfer_len); + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); + trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); urb_priv = td->urb->hcpriv; idx = urb_priv->td_cnt; frame = &td->urb->iso_frame_desc[idx]; @@ -1752,15 +1761,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; cur_trb != event_trb; next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { - if ((cur_trb->generic.field[3] & + if ((le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && - (cur_trb->generic.field[3] & + (le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) - len += - TRB_LEN(cur_trb->generic.field[2]); + len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); } - len += TRB_LEN(cur_trb->generic.field[2]) - - TRB_LEN(event->transfer_len); + len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - + TRB_LEN(le32_to_cpu(event->transfer_len)); if (trb_comp_code != COMP_STOP_INVAL) { frame->actual_length = len; @@ -1815,8 +1823,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, struct xhci_segment *cur_seg; u32 trb_comp_code; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); - trb_comp_code = GET_COMP_CODE(event->transfer_len); + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); + trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); switch (trb_comp_code) { case COMP_SUCCESS: @@ -1852,18 +1860,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, "%d bytes untransferred\n", td->urb->ep->desc.bEndpointAddress, td->urb->transfer_buffer_length, - TRB_LEN(event->transfer_len)); + TRB_LEN(le32_to_cpu(event->transfer_len))); /* Fast path - was this the last TRB in the TD for this URB? */ if (event_trb == td->last_trb) { - if (TRB_LEN(event->transfer_len) != 0) { + if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(event->transfer_len); + TRB_LEN(le32_to_cpu(event->transfer_len)); if (td->urb->transfer_buffer_length < td->urb->actual_length) { xhci_warn(xhci, "HC gave bad length " "of %d bytes left\n", - TRB_LEN(event->transfer_len)); + TRB_LEN(le32_to_cpu(event->transfer_len))); td->urb->actual_length = 0; if (td->urb->transfer_flags & URB_SHORT_NOT_OK) *status = -EREMOTEIO; @@ -1894,20 +1902,20 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; cur_trb != event_trb; next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { - if ((cur_trb->generic.field[3] & + if ((le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && - (cur_trb->generic.field[3] & + (le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) td->urb->actual_length += - TRB_LEN(cur_trb->generic.field[2]); + TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); } /* If the ring didn't stop on a Link or No-op TRB, add * in the actual bytes transferred from the Normal TRB */ if (trb_comp_code != COMP_STOP_INVAL) td->urb->actual_length += - TRB_LEN(cur_trb->generic.field[2]) - - TRB_LEN(event->transfer_len); + TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - + TRB_LEN(le32_to_cpu(event->transfer_len)); } return finish_td(xhci, td, event_trb, event, ep, status, false); @@ -1937,7 +1945,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, u32 trb_comp_code; int ret = 0; - slot_id = TRB_TO_SLOT_ID(event->flags); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); xdev = xhci->devs[slot_id]; if (!xdev) { xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n"); @@ -1945,20 +1953,21 @@ static int handle_tx_event(struct xhci_hcd *xhci, } /* Endpoint ID is 1 based, our index is zero based */ - ep_index = TRB_TO_EP_ID(event->flags) - 1; + ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1; xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index); ep = &xdev->eps[ep_index]; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); if (!ep_ring || - (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { + (le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == + EP_STATE_DISABLED) { xhci_err(xhci, "ERROR Transfer event for disabled endpoint " "or incorrect stream ring\n"); return -ENODEV; } - event_dma = event->buffer; - trb_comp_code = GET_COMP_CODE(event->transfer_len); + event_dma = le64_to_cpu(event->buffer); + trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); /* Look for common error cases */ switch (trb_comp_code) { /* Skip codes that require special handling depending on @@ -2011,14 +2020,16 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (!list_empty(&ep_ring->td_list)) xhci_dbg(xhci, "Underrun Event for slot %d ep %d " "still with TDs queued?\n", - TRB_TO_SLOT_ID(event->flags), ep_index); + TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), + ep_index); goto cleanup; case COMP_OVERRUN: xhci_dbg(xhci, "overrun event on endpoint\n"); if (!list_empty(&ep_ring->td_list)) xhci_dbg(xhci, "Overrun Event for slot %d ep %d " "still with TDs queued?\n", - TRB_TO_SLOT_ID(event->flags), ep_index); + TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), + ep_index); goto cleanup; case COMP_MISSED_INT: /* @@ -2047,9 +2058,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (list_empty(&ep_ring->td_list)) { xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " "with no TDs queued?\n", - TRB_TO_SLOT_ID(event->flags), ep_index); + TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), + ep_index); xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", - (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); + (unsigned int) (le32_to_cpu(event->flags) + & TRB_TYPE_BITMASK)>>10); xhci_print_trb_offsets(xhci, (union xhci_trb *) event); if (ep->skip) { ep->skip = false; @@ -2092,7 +2105,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, * corresponding TD has been cancelled. Just ignore * the TD. */ - if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK) + if ((le32_to_cpu(event_trb->generic.field[3]) + & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_TR_NOOP)) { xhci_dbg(xhci, "event_trb is a no-op TRB. Skip it\n"); @@ -2172,15 +2186,15 @@ static void xhci_handle_event(struct xhci_hcd *xhci) event = xhci->event_ring->dequeue; /* Does the HC or OS own the TRB? */ - if ((event->event_cmd.flags & TRB_CYCLE) != - xhci->event_ring->cycle_state) { + if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) != + xhci->event_ring->cycle_state) { xhci->error_bitmask |= 1 << 2; return; } xhci_dbg(xhci, "%s - OS owns TRB\n", __func__); /* FIXME: Handle more event types. */ - switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) { + switch ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK)) { case TRB_TYPE(TRB_COMPLETION): xhci_dbg(xhci, "%s - calling handle_cmd_completion\n", __func__); handle_cmd_completion(xhci, &event->event_cmd); @@ -2202,7 +2216,8 @@ static void xhci_handle_event(struct xhci_hcd *xhci) update_ptrs = 0; break; default: - if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48)) + if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >= + TRB_TYPE(48)) handle_vendor_event(xhci, event); else xhci->error_bitmask |= 1 << 3; @@ -2252,12 +2267,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) xhci_dbg(xhci, "op reg status = %08x\n", status); xhci_dbg(xhci, "Event ring dequeue ptr:\n"); xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", - (unsigned long long) - xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), - lower_32_bits(trb->link.segment_ptr), - upper_32_bits(trb->link.segment_ptr), - (unsigned int) trb->link.intr_target, - (unsigned int) trb->link.control); + (unsigned long long) + xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), + lower_32_bits(le64_to_cpu(trb->link.segment_ptr)), + upper_32_bits(le64_to_cpu(trb->link.segment_ptr)), + (unsigned int) le32_to_cpu(trb->link.intr_target), + (unsigned int) le32_to_cpu(trb->link.control)); if (status & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); @@ -2358,10 +2373,10 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, struct xhci_generic_trb *trb; trb = &ring->enqueue->generic; - trb->field[0] = field1; - trb->field[1] = field2; - trb->field[2] = field3; - trb->field[3] = field4; + trb->field[0] = cpu_to_le32(field1); + trb->field[1] = cpu_to_le32(field2); + trb->field[2] = cpu_to_le32(field3); + trb->field[3] = cpu_to_le32(field4); inc_enq(xhci, ring, consumer, more_trbs_coming); } @@ -2414,17 +2429,16 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, next = ring->enqueue; while (last_trb(xhci, ring, ring->enq_seg, next)) { - /* If we're not dealing with 0.95 hardware, * clear the chain bit. */ if (!xhci_link_trb_quirk(xhci)) - next->link.control &= ~TRB_CHAIN; + next->link.control &= cpu_to_le32(~TRB_CHAIN); else - next->link.control |= TRB_CHAIN; + next->link.control |= cpu_to_le32(TRB_CHAIN); wmb(); - next->link.control ^= (u32) TRB_CYCLE; + next->link.control ^= cpu_to_le32((u32) TRB_CYCLE); /* Toggle the cycle bit after the last ring segment. */ if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) { @@ -2467,8 +2481,8 @@ static int prepare_transfer(struct xhci_hcd *xhci, } ret = prepare_ring(xhci, ep_ring, - ep_ctx->ep_info & EP_STATE_MASK, - num_trbs, mem_flags); + le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK, + num_trbs, mem_flags); if (ret) return ret; @@ -2570,9 +2584,9 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, */ wmb(); if (start_cycle) - start_trb->field[3] |= start_cycle; + start_trb->field[3] |= cpu_to_le32(start_cycle); else - start_trb->field[3] &= ~0x1; + start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } @@ -2590,7 +2604,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int xhci_interval; int ep_interval; - xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info); + xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info)); ep_interval = urb->interval; /* Convert to microframes */ if (urb->dev->speed == USB_SPEED_LOW || @@ -2979,12 +2993,11 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (start_cycle == 0) field |= 0x1; queue_trb(xhci, ep_ring, false, true, - /* FIXME endianness is probably going to bite my ass here. */ - setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16, - setup->wIndex | setup->wLength << 16, - TRB_LEN(8) | TRB_INTR_TARGET(0), - /* Immediate data in pointer */ - field); + setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16, + le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16, + TRB_LEN(8) | TRB_INTR_TARGET(0), + /* Immediate data in pointer */ + field); /* If there's data, queue data TRBs */ field = 0; @@ -3211,8 +3224,8 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, /* Check the ring to guarantee there is enough room for the whole urb. * Do not insert any td of the urb to the ring if the check failed. */ - ret = prepare_ring(xhci, ep_ring, ep_ctx->ep_info & EP_STATE_MASK, - num_trbs, mem_flags); + ret = prepare_ring(xhci, ep_ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK, + num_trbs, mem_flags); if (ret) return ret; @@ -3224,7 +3237,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, urb->dev->speed == USB_SPEED_FULL) urb->start_frame >>= 3; - xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info); + xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info)); ep_interval = urb->interval; /* Convert to microframes */ if (urb->dev->speed == USB_SPEED_LOW || diff --git a/trunk/drivers/usb/host/xhci.c b/trunk/drivers/usb/host/xhci.c index 81b976e45880..e8ab1899c88e 100644 --- a/trunk/drivers/usb/host/xhci.c +++ b/trunk/drivers/usb/host/xhci.c @@ -973,8 +973,8 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, out_ctx = xhci->devs[slot_id]->out_ctx; ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); - hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2); - max_packet_size = urb->dev->ep0.desc.wMaxPacketSize; + hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); + max_packet_size = le16_to_cpu(urb->dev->ep0.desc.wMaxPacketSize); if (hw_max_packet_size != max_packet_size) { xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n"); xhci_dbg(xhci, "Max packet size in usb_device = %d\n", @@ -988,15 +988,15 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, xhci->devs[slot_id]->out_ctx, ep_index); in_ctx = xhci->devs[slot_id]->in_ctx; ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); - ep_ctx->ep_info2 &= ~MAX_PACKET_MASK; - ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size); + ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); + ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); /* Set up the input context flags for the command */ /* FIXME: This won't work if a non-default control endpoint * changes max packet sizes. */ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); - ctrl_ctx->add_flags = EP0_FLAG; + ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); ctrl_ctx->drop_flags = 0; xhci_dbg(xhci, "Slot %d input context\n", slot_id); @@ -1010,7 +1010,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, /* Clean up the input context for later use by bandwidth * functions. */ - ctrl_ctx->add_flags = SLOT_FLAG; + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); } return ret; } @@ -1331,27 +1331,30 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, /* If the HC already knows the endpoint is disabled, * or the HCD has noted it is disabled, ignore this request */ - if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED || - ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) { + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == + EP_STATE_DISABLED || + le32_to_cpu(ctrl_ctx->drop_flags) & + xhci_get_endpoint_flag(&ep->desc)) { xhci_warn(xhci, "xHCI %s called with disabled ep %p\n", __func__, ep); return 0; } - ctrl_ctx->drop_flags |= drop_flag; - new_drop_flags = ctrl_ctx->drop_flags; + ctrl_ctx->drop_flags |= cpu_to_le32(drop_flag); + new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags); - ctrl_ctx->add_flags &= ~drop_flag; - new_add_flags = ctrl_ctx->add_flags; + ctrl_ctx->add_flags &= cpu_to_le32(~drop_flag); + new_add_flags = le32_to_cpu(ctrl_ctx->add_flags); - last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); + last_ctx = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags)); slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); /* Update the last valid endpoint context, if we deleted the last one */ - if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) { - slot_ctx->dev_info &= ~LAST_CTX_MASK; - slot_ctx->dev_info |= LAST_CTX(last_ctx); + if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) > + LAST_CTX(last_ctx)) { + slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK); + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx)); } - new_slot_info = slot_ctx->dev_info; + new_slot_info = le32_to_cpu(slot_ctx->dev_info); xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep); @@ -1419,7 +1422,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, /* If the HCD has already noted the endpoint is enabled, * ignore this request. */ - if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) { + if (le32_to_cpu(ctrl_ctx->add_flags) & + xhci_get_endpoint_flag(&ep->desc)) { xhci_warn(xhci, "xHCI %s called with enabled ep %p\n", __func__, ep); return 0; @@ -1437,8 +1441,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return -ENOMEM; } - ctrl_ctx->add_flags |= added_ctxs; - new_add_flags = ctrl_ctx->add_flags; + ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs); + new_add_flags = le32_to_cpu(ctrl_ctx->add_flags); /* If xhci_endpoint_disable() was called for this endpoint, but the * xHC hasn't been notified yet through the check_bandwidth() call, @@ -1446,15 +1450,16 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, * descriptors. We must drop and re-add this endpoint, so we leave the * drop flags alone. */ - new_drop_flags = ctrl_ctx->drop_flags; + new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags); slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); /* Update the last valid endpoint context, if we just added one past */ - if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) { - slot_ctx->dev_info &= ~LAST_CTX_MASK; - slot_ctx->dev_info |= LAST_CTX(last_ctx); + if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) < + LAST_CTX(last_ctx)) { + slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK); + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx)); } - new_slot_info = slot_ctx->dev_info; + new_slot_info = le32_to_cpu(slot_ctx->dev_info); /* Store the usb_device pointer for later use */ ep->hcpriv = udev; @@ -1484,9 +1489,9 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir ctrl_ctx->drop_flags = 0; ctrl_ctx->add_flags = 0; slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); - slot_ctx->dev_info &= ~LAST_CTX_MASK; + slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK); /* Endpoint 0 is always valid */ - slot_ctx->dev_info |= LAST_CTX(1); + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1)); for (i = 1; i < 31; ++i) { ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i); ep_ctx->ep_info = 0; @@ -1581,7 +1586,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, unsigned long flags; struct xhci_container_ctx *in_ctx; struct completion *cmd_completion; - int *cmd_status; + u32 *cmd_status; struct xhci_virt_device *virt_dev; spin_lock_irqsave(&xhci->lock, flags); @@ -1595,8 +1600,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, /* Enqueue pointer can be left pointing to the link TRB, * we must handle that */ - if ((command->command_trb->link.control & TRB_TYPE_BITMASK) - == TRB_TYPE(TRB_LINK)) + if ((le32_to_cpu(command->command_trb->link.control) + & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) command->command_trb = xhci->cmd_ring->enq_seg->next->trbs; @@ -1672,14 +1677,13 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */ ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); - ctrl_ctx->add_flags |= SLOT_FLAG; - ctrl_ctx->add_flags &= ~EP0_FLAG; - ctrl_ctx->drop_flags &= ~SLOT_FLAG; - ctrl_ctx->drop_flags &= ~EP0_FLAG; + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); + ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG); + ctrl_ctx->drop_flags &= cpu_to_le32(~(SLOT_FLAG | EP0_FLAG)); xhci_dbg(xhci, "New Input Control Context:\n"); slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); xhci_dbg_ctx(xhci, virt_dev->in_ctx, - LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); + LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info))); ret = xhci_configure_endpoint(xhci, udev, NULL, false, false); @@ -1690,7 +1694,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg(xhci, "Output context after successful config ep cmd:\n"); xhci_dbg_ctx(xhci, virt_dev->out_ctx, - LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); + LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info))); xhci_zero_in_ctx(xhci, virt_dev); /* Install new rings and free or cache any old rings */ @@ -1740,10 +1744,10 @@ static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci, { struct xhci_input_control_ctx *ctrl_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); - ctrl_ctx->add_flags = add_flags; - ctrl_ctx->drop_flags = drop_flags; + ctrl_ctx->add_flags = cpu_to_le32(add_flags); + ctrl_ctx->drop_flags = cpu_to_le32(drop_flags); xhci_slot_copy(xhci, in_ctx, out_ctx); - ctrl_ctx->add_flags |= SLOT_FLAG; + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); xhci_dbg(xhci, "Input Context:\n"); xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags)); @@ -1772,7 +1776,7 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, deq_state->new_deq_ptr); return; } - ep_ctx->deq = addr | deq_state->new_cycle_state; + ep_ctx->deq = cpu_to_le64(addr | deq_state->new_cycle_state); added_ctxs = xhci_get_endpoint_flag_from_index(ep_index); xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx, @@ -2327,8 +2331,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) /* Enqueue pointer can be left pointing to the link TRB, * we must handle that */ - if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK) - == TRB_TYPE(TRB_LINK)) + if ((le32_to_cpu(reset_device_cmd->command_trb->link.control) + & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) reset_device_cmd->command_trb = xhci->cmd_ring->enq_seg->next->trbs; @@ -2609,10 +2613,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64); xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n", - udev->slot_id, - &xhci->dcbaa->dev_context_ptrs[udev->slot_id], - (unsigned long long) - xhci->dcbaa->dev_context_ptrs[udev->slot_id]); + udev->slot_id, + &xhci->dcbaa->dev_context_ptrs[udev->slot_id], + (unsigned long long) + le64_to_cpu(xhci->dcbaa->dev_context_ptrs[udev->slot_id])); xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", (unsigned long long)virt_dev->out_ctx->dma); xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); @@ -2626,7 +2630,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); /* Use kernel assigned address for devices; store xHC assigned * address locally. */ - virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1; + virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK) + + 1; /* Zero the input context control for later use */ ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx->add_flags = 0; @@ -2670,16 +2675,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, spin_lock_irqsave(&xhci->lock, flags); xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx); ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx); - ctrl_ctx->add_flags |= SLOT_FLAG; + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); - slot_ctx->dev_info |= DEV_HUB; + slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); if (tt->multi) - slot_ctx->dev_info |= DEV_MTT; + slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); if (xhci->hci_version > 0x95) { xhci_dbg(xhci, "xHCI version %x needs hub " "TT think time and number of ports\n", (unsigned int) xhci->hci_version); - slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild); + slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(hdev->maxchild)); /* Set TT think time - convert from ns to FS bit times. * 0 = 8 FS bit times, 1 = 16 FS bit times, * 2 = 24 FS bit times, 3 = 32 FS bit times. @@ -2687,7 +2692,7 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, think_time = tt->think_time; if (think_time != 0) think_time = (think_time / 666) - 1; - slot_ctx->tt_info |= TT_THINK_TIME(think_time); + slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time)); } else { xhci_dbg(xhci, "xHCI version %x doesn't need hub " "TT think time or number of ports\n", diff --git a/trunk/drivers/usb/host/xhci.h b/trunk/drivers/usb/host/xhci.h index ba1be6b7cc6d..85e779808189 100644 --- a/trunk/drivers/usb/host/xhci.h +++ b/trunk/drivers/usb/host/xhci.h @@ -57,13 +57,13 @@ * @run_regs_off: RTSOFF - Runtime register space offset */ struct xhci_cap_regs { - u32 hc_capbase; - u32 hcs_params1; - u32 hcs_params2; - u32 hcs_params3; - u32 hcc_params; - u32 db_off; - u32 run_regs_off; + __le32 hc_capbase; + __le32 hcs_params1; + __le32 hcs_params2; + __le32 hcs_params3; + __le32 hcc_params; + __le32 db_off; + __le32 run_regs_off; /* Reserved up to (CAPLENGTH - 0x1C) */ }; @@ -155,26 +155,26 @@ struct xhci_cap_regs { * devices. */ struct xhci_op_regs { - u32 command; - u32 status; - u32 page_size; - u32 reserved1; - u32 reserved2; - u32 dev_notification; - u64 cmd_ring; + __le32 command; + __le32 status; + __le32 page_size; + __le32 reserved1; + __le32 reserved2; + __le32 dev_notification; + __le64 cmd_ring; /* rsvd: offset 0x20-2F */ - u32 reserved3[4]; - u64 dcbaa_ptr; - u32 config_reg; + __le32 reserved3[4]; + __le64 dcbaa_ptr; + __le32 config_reg; /* rsvd: offset 0x3C-3FF */ - u32 reserved4[241]; + __le32 reserved4[241]; /* port 1 registers, which serve as a base address for other ports */ - u32 port_status_base; - u32 port_power_base; - u32 port_link_base; - u32 reserved5; + __le32 port_status_base; + __le32 port_power_base; + __le32 port_link_base; + __le32 reserved5; /* registers for ports 2-255 */ - u32 reserved6[NUM_PORT_REGS*254]; + __le32 reserved6[NUM_PORT_REGS*254]; }; /* USBCMD - USB command - command bitmasks */ @@ -382,12 +382,12 @@ struct xhci_op_regs { * updates the dequeue pointer. */ struct xhci_intr_reg { - u32 irq_pending; - u32 irq_control; - u32 erst_size; - u32 rsvd; - u64 erst_base; - u64 erst_dequeue; + __le32 irq_pending; + __le32 irq_control; + __le32 erst_size; + __le32 rsvd; + __le64 erst_base; + __le64 erst_dequeue; }; /* irq_pending bitmasks */ @@ -432,8 +432,8 @@ struct xhci_intr_reg { * or larger accesses" */ struct xhci_run_regs { - u32 microframe_index; - u32 rsvd[7]; + __le32 microframe_index; + __le32 rsvd[7]; struct xhci_intr_reg ir_set[128]; }; @@ -447,7 +447,7 @@ struct xhci_run_regs { * Section 5.6 */ struct xhci_doorbell_array { - u32 doorbell[256]; + __le32 doorbell[256]; }; #define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) @@ -504,12 +504,12 @@ struct xhci_container_ctx { * reserved at the end of the slot context for HC internal use. */ struct xhci_slot_ctx { - u32 dev_info; - u32 dev_info2; - u32 tt_info; - u32 dev_state; + __le32 dev_info; + __le32 dev_info2; + __le32 tt_info; + __le32 dev_state; /* offset 0x10 to 0x1f reserved for HC internal use */ - u32 reserved[4]; + __le32 reserved[4]; }; /* dev_info bitmasks */ @@ -580,12 +580,12 @@ struct xhci_slot_ctx { * reserved at the end of the endpoint context for HC internal use. */ struct xhci_ep_ctx { - u32 ep_info; - u32 ep_info2; - u64 deq; - u32 tx_info; + __le32 ep_info; + __le32 ep_info2; + __le64 deq; + __le32 tx_info; /* offset 0x14 - 0x1f reserved for HC internal use */ - u32 reserved[3]; + __le32 reserved[3]; }; /* ep_info bitmasks */ @@ -660,9 +660,9 @@ struct xhci_ep_ctx { * @add_context: set the bit of the endpoint context you want to enable */ struct xhci_input_control_ctx { - u32 drop_flags; - u32 add_flags; - u32 rsvd2[6]; + __le32 drop_flags; + __le32 add_flags; + __le32 rsvd2[6]; }; /* Represents everything that is needed to issue a command on the command ring. @@ -688,9 +688,9 @@ struct xhci_command { struct xhci_stream_ctx { /* 64-bit stream ring address, cycle state, and stream type */ - u64 stream_ring; + __le64 stream_ring; /* offset 0x14 - 0x1f reserved for HC internal use */ - u32 reserved[2]; + __le32 reserved[2]; }; /* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */ @@ -803,7 +803,7 @@ struct xhci_virt_device { */ struct xhci_device_context_array { /* 64-bit device addresses; we only write 32-bit addresses */ - u64 dev_context_ptrs[MAX_HC_SLOTS]; + __le64 dev_context_ptrs[MAX_HC_SLOTS]; /* private xHCD pointers */ dma_addr_t dma; }; @@ -816,10 +816,10 @@ struct xhci_device_context_array { struct xhci_transfer_event { /* 64-bit buffer address, or immediate data */ - u64 buffer; - u32 transfer_len; + __le64 buffer; + __le32 transfer_len; /* This field is interpreted differently based on the type of TRB */ - u32 flags; + __le32 flags; }; /** Transfer Event bit fields **/ @@ -898,9 +898,9 @@ struct xhci_transfer_event { struct xhci_link_trb { /* 64-bit segment pointer*/ - u64 segment_ptr; - u32 intr_target; - u32 control; + __le64 segment_ptr; + __le32 intr_target; + __le32 control; }; /* control bitfields */ @@ -909,9 +909,9 @@ struct xhci_link_trb { /* Command completion event TRB */ struct xhci_event_cmd { /* Pointer to command TRB, or the value passed by the event data trb */ - u64 cmd_trb; - u32 status; - u32 flags; + __le64 cmd_trb; + __le32 status; + __le32 flags; }; /* flags bitmasks */ @@ -970,7 +970,7 @@ struct xhci_event_cmd { #define TRB_SIA (1<<31) struct xhci_generic_trb { - u32 field[4]; + __le32 field[4]; }; union xhci_trb { @@ -1118,10 +1118,10 @@ struct xhci_ring { struct xhci_erst_entry { /* 64-bit event ring segment address */ - u64 seg_addr; - u32 seg_size; + __le64 seg_addr; + __le32 seg_size; /* Set to zero */ - u32 rsvd; + __le32 rsvd; }; struct xhci_erst { @@ -1286,10 +1286,10 @@ struct xhci_hcd { /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ u8 *port_array; /* Array of pointers to USB 3.0 PORTSC registers */ - u32 __iomem **usb3_ports; + __le32 __iomem **usb3_ports; unsigned int num_usb3_ports; /* Array of pointers to USB 2.0 PORTSC registers */ - u32 __iomem **usb2_ports; + __le32 __iomem **usb2_ports; unsigned int num_usb2_ports; }; @@ -1322,12 +1322,12 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) /* TODO: copied from ehci.h - can be refactored? */ /* xHCI spec says all registers are little endian */ static inline unsigned int xhci_readl(const struct xhci_hcd *xhci, - __u32 __iomem *regs) + __le32 __iomem *regs) { return readl(regs); } static inline void xhci_writel(struct xhci_hcd *xhci, - const unsigned int val, __u32 __iomem *regs) + const unsigned int val, __le32 __iomem *regs) { xhci_dbg(xhci, "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n", @@ -1345,7 +1345,7 @@ static inline void xhci_writel(struct xhci_hcd *xhci, * the high dword, and write order is irrelevant. */ static inline u64 xhci_read_64(const struct xhci_hcd *xhci, - __u64 __iomem *regs) + __le64 __iomem *regs) { __u32 __iomem *ptr = (__u32 __iomem *) regs; u64 val_lo = readl(ptr); @@ -1353,7 +1353,7 @@ static inline u64 xhci_read_64(const struct xhci_hcd *xhci, return val_lo + (val_hi << 32); } static inline void xhci_write_64(struct xhci_hcd *xhci, - const u64 val, __u64 __iomem *regs) + const u64 val, __le64 __iomem *regs) { __u32 __iomem *ptr = (__u32 __iomem *) regs; u32 val_lo = lower_32_bits(val); diff --git a/trunk/drivers/usb/misc/usbtest.c b/trunk/drivers/usb/misc/usbtest.c index 7e0bb2af8e63..58a5685fb7d1 100644 --- a/trunk/drivers/usb/misc/usbtest.c +++ b/trunk/drivers/usb/misc/usbtest.c @@ -1030,8 +1030,6 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0); /* device descriptor size == 18 bytes */ len = udev->descriptor.bMaxPacketSize0; - if (udev->speed == USB_SPEED_SUPER) - len = 512; switch (len) { case 8: len = 24; @@ -2310,9 +2308,6 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) case USB_SPEED_HIGH: tmp = "high"; break; - case USB_SPEED_SUPER: - tmp = "super"; - break; default: tmp = "unknown"; break; diff --git a/trunk/drivers/usb/otg/Kconfig b/trunk/drivers/usb/otg/Kconfig index c66481ad98d7..daf3e5f1a0e7 100644 --- a/trunk/drivers/usb/otg/Kconfig +++ b/trunk/drivers/usb/otg/Kconfig @@ -122,12 +122,4 @@ config AB8500_USB This transceiver supports high and full speed devices plus, in host mode, low speed. -config FSL_USB2_OTG - bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 - select USB_OTG - select USB_OTG_UTILS - help - Enable this to support Freescale USB OTG transceiver. - endif # USB || OTG diff --git a/trunk/drivers/usb/otg/Makefile b/trunk/drivers/usb/otg/Makefile index 566655c53331..e22d917de017 100644 --- a/trunk/drivers/usb/otg/Makefile +++ b/trunk/drivers/usb/otg/Makefile @@ -19,5 +19,3 @@ obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o obj-$(CONFIG_AB8500_USB) += ab8500-usb.o -fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o -obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o diff --git a/trunk/drivers/usb/otg/fsl_otg.c b/trunk/drivers/usb/otg/fsl_otg.c deleted file mode 100644 index 0f420b25e9a9..000000000000 --- a/trunk/drivers/usb/otg/fsl_otg.c +++ /dev/null @@ -1,1169 +0,0 @@ -/* - * Copyright (C) 2007,2008 Freescale semiconductor, Inc. - * - * Author: Li Yang - * Jerry Huang - * - * Initialization based on code from Shlomi Gridish. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "fsl_otg.h" - -#define DRIVER_VERSION "Rev. 1.55" -#define DRIVER_AUTHOR "Jerry Huang/Li Yang" -#define DRIVER_DESC "Freescale USB OTG Transceiver Driver" -#define DRIVER_INFO DRIVER_DESC " " DRIVER_VERSION - -static const char driver_name[] = "fsl-usb2-otg"; - -const pm_message_t otg_suspend_state = { - .event = 1, -}; - -#define HA_DATA_PULSE - -static struct usb_dr_mmap *usb_dr_regs; -static struct fsl_otg *fsl_otg_dev; -static int srp_wait_done; - -/* FSM timers */ -struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, - *b_ase0_brst_tmr, *b_se0_srp_tmr; - -/* Driver specific timers */ -struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, - *b_srp_wait_tmr, *a_wait_enum_tmr; - -static struct list_head active_timers; - -static struct fsl_otg_config fsl_otg_initdata = { - .otg_port = 1, -}; - -#ifdef CONFIG_PPC32 -static u32 _fsl_readl_be(const unsigned __iomem *p) -{ - return in_be32(p); -} - -static u32 _fsl_readl_le(const unsigned __iomem *p) -{ - return in_le32(p); -} - -static void _fsl_writel_be(u32 v, unsigned __iomem *p) -{ - out_be32(p, v); -} - -static void _fsl_writel_le(u32 v, unsigned __iomem *p) -{ - out_le32(p, v); -} - -static u32 (*_fsl_readl)(const unsigned __iomem *p); -static void (*_fsl_writel)(u32 v, unsigned __iomem *p); - -#define fsl_readl(p) (*_fsl_readl)((p)) -#define fsl_writel(v, p) (*_fsl_writel)((v), (p)) - -#else -#define fsl_readl(addr) readl(addr) -#define fsl_writel(val, addr) writel(val, addr) -#endif /* CONFIG_PPC32 */ - -/* Routines to access transceiver ULPI registers */ -u8 view_ulpi(u8 addr) -{ - u32 temp; - - temp = 0x40000000 | (addr << 16); - fsl_writel(temp, &usb_dr_regs->ulpiview); - udelay(1000); - while (temp & 0x40) - temp = fsl_readl(&usb_dr_regs->ulpiview); - return (le32_to_cpu(temp) & 0x0000ff00) >> 8; -} - -int write_ulpi(u8 addr, u8 data) -{ - u32 temp; - - temp = 0x60000000 | (addr << 16) | data; - fsl_writel(temp, &usb_dr_regs->ulpiview); - return 0; -} - -/* -------------------------------------------------------------*/ -/* Operations that will be called from OTG Finite State Machine */ - -/* Charge vbus for vbus pulsing in SRP */ -void fsl_otg_chrg_vbus(int on) -{ - u32 tmp; - - tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; - - if (on) - /* stop discharging, start charging */ - tmp = (tmp & ~OTGSC_CTRL_VBUS_DISCHARGE) | - OTGSC_CTRL_VBUS_CHARGE; - else - /* stop charging */ - tmp &= ~OTGSC_CTRL_VBUS_CHARGE; - - fsl_writel(tmp, &usb_dr_regs->otgsc); -} - -/* Discharge vbus through a resistor to ground */ -void fsl_otg_dischrg_vbus(int on) -{ - u32 tmp; - - tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; - - if (on) - /* stop charging, start discharging */ - tmp = (tmp & ~OTGSC_CTRL_VBUS_CHARGE) | - OTGSC_CTRL_VBUS_DISCHARGE; - else - /* stop discharging */ - tmp &= ~OTGSC_CTRL_VBUS_DISCHARGE; - - fsl_writel(tmp, &usb_dr_regs->otgsc); -} - -/* A-device driver vbus, controlled through PP bit in PORTSC */ -void fsl_otg_drv_vbus(int on) -{ - u32 tmp; - - if (on) { - tmp = fsl_readl(&usb_dr_regs->portsc) & ~PORTSC_W1C_BITS; - fsl_writel(tmp | PORTSC_PORT_POWER, &usb_dr_regs->portsc); - } else { - tmp = fsl_readl(&usb_dr_regs->portsc) & - ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER; - fsl_writel(tmp, &usb_dr_regs->portsc); - } -} - -/* - * Pull-up D+, signalling connect by periperal. Also used in - * data-line pulsing in SRP - */ -void fsl_otg_loc_conn(int on) -{ - u32 tmp; - - tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; - - if (on) - tmp |= OTGSC_CTRL_DATA_PULSING; - else - tmp &= ~OTGSC_CTRL_DATA_PULSING; - - fsl_writel(tmp, &usb_dr_regs->otgsc); -} - -/* - * Generate SOF by host. This is controlled through suspend/resume the - * port. In host mode, controller will automatically send SOF. - * Suspend will block the data on the port. - */ -void fsl_otg_loc_sof(int on) -{ - u32 tmp; - - tmp = fsl_readl(&fsl_otg_dev->dr_mem_map->portsc) & ~PORTSC_W1C_BITS; - if (on) - tmp |= PORTSC_PORT_FORCE_RESUME; - else - tmp |= PORTSC_PORT_SUSPEND; - - fsl_writel(tmp, &fsl_otg_dev->dr_mem_map->portsc); - -} - -/* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */ -void fsl_otg_start_pulse(void) -{ - u32 tmp; - - srp_wait_done = 0; -#ifdef HA_DATA_PULSE - tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; - tmp |= OTGSC_HA_DATA_PULSE; - fsl_writel(tmp, &usb_dr_regs->otgsc); -#else - fsl_otg_loc_conn(1); -#endif - - fsl_otg_add_timer(b_data_pulse_tmr); -} - -void b_data_pulse_end(unsigned long foo) -{ -#ifdef HA_DATA_PULSE -#else - fsl_otg_loc_conn(0); -#endif - - /* Do VBUS pulse after data pulse */ - fsl_otg_pulse_vbus(); -} - -void fsl_otg_pulse_vbus(void) -{ - srp_wait_done = 0; - fsl_otg_chrg_vbus(1); - /* start the timer to end vbus charge */ - fsl_otg_add_timer(b_vbus_pulse_tmr); -} - -void b_vbus_pulse_end(unsigned long foo) -{ - fsl_otg_chrg_vbus(0); - - /* - * As USB3300 using the same a_sess_vld and b_sess_vld voltage - * we need to discharge the bus for a while to distinguish - * residual voltage of vbus pulsing and A device pull up - */ - fsl_otg_dischrg_vbus(1); - fsl_otg_add_timer(b_srp_wait_tmr); -} - -void b_srp_end(unsigned long foo) -{ - fsl_otg_dischrg_vbus(0); - srp_wait_done = 1; - - if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) && - fsl_otg_dev->fsm.b_sess_vld) - fsl_otg_dev->fsm.b_srp_done = 1; -} - -/* - * Workaround for a_host suspending too fast. When a_bus_req=0, - * a_host will start by SRP. It needs to set b_hnp_enable before - * actually suspending to start HNP - */ -void a_wait_enum(unsigned long foo) -{ - VDBG("a_wait_enum timeout\n"); - if (!fsl_otg_dev->otg.host->b_hnp_enable) - fsl_otg_add_timer(a_wait_enum_tmr); - else - otg_statemachine(&fsl_otg_dev->fsm); -} - -/* The timeout callback function to set time out bit */ -void set_tmout(unsigned long indicator) -{ - *(int *)indicator = 1; -} - -/* Initialize timers */ -int fsl_otg_init_timers(struct otg_fsm *fsm) -{ - /* FSM used timers */ - a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, - (unsigned long)&fsm->a_wait_vrise_tmout); - if (!a_wait_vrise_tmr) - return -ENOMEM; - - a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON, - (unsigned long)&fsm->a_wait_bcon_tmout); - if (!a_wait_bcon_tmr) - return -ENOMEM; - - a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, - (unsigned long)&fsm->a_aidl_bdis_tmout); - if (!a_aidl_bdis_tmr) - return -ENOMEM; - - b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, - (unsigned long)&fsm->b_ase0_brst_tmout); - if (!b_ase0_brst_tmr) - return -ENOMEM; - - b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, - (unsigned long)&fsm->b_se0_srp); - if (!b_se0_srp_tmr) - return -ENOMEM; - - b_srp_fail_tmr = otg_timer_initializer(&set_tmout, TB_SRP_FAIL, - (unsigned long)&fsm->b_srp_done); - if (!b_srp_fail_tmr) - return -ENOMEM; - - a_wait_enum_tmr = otg_timer_initializer(&a_wait_enum, 10, - (unsigned long)&fsm); - if (!a_wait_enum_tmr) - return -ENOMEM; - - /* device driver used timers */ - b_srp_wait_tmr = otg_timer_initializer(&b_srp_end, TB_SRP_WAIT, 0); - if (!b_srp_wait_tmr) - return -ENOMEM; - - b_data_pulse_tmr = otg_timer_initializer(&b_data_pulse_end, - TB_DATA_PLS, 0); - if (!b_data_pulse_tmr) - return -ENOMEM; - - b_vbus_pulse_tmr = otg_timer_initializer(&b_vbus_pulse_end, - TB_VBUS_PLS, 0); - if (!b_vbus_pulse_tmr) - return -ENOMEM; - - return 0; -} - -/* Uninitialize timers */ -void fsl_otg_uninit_timers(void) -{ - /* FSM used timers */ - if (a_wait_vrise_tmr != NULL) - kfree(a_wait_vrise_tmr); - if (a_wait_bcon_tmr != NULL) - kfree(a_wait_bcon_tmr); - if (a_aidl_bdis_tmr != NULL) - kfree(a_aidl_bdis_tmr); - if (b_ase0_brst_tmr != NULL) - kfree(b_ase0_brst_tmr); - if (b_se0_srp_tmr != NULL) - kfree(b_se0_srp_tmr); - if (b_srp_fail_tmr != NULL) - kfree(b_srp_fail_tmr); - if (a_wait_enum_tmr != NULL) - kfree(a_wait_enum_tmr); - - /* device driver used timers */ - if (b_srp_wait_tmr != NULL) - kfree(b_srp_wait_tmr); - if (b_data_pulse_tmr != NULL) - kfree(b_data_pulse_tmr); - if (b_vbus_pulse_tmr != NULL) - kfree(b_vbus_pulse_tmr); -} - -/* Add timer to timer list */ -void fsl_otg_add_timer(void *gtimer) -{ - struct fsl_otg_timer *timer = gtimer; - struct fsl_otg_timer *tmp_timer; - - /* - * Check if the timer is already in the active list, - * if so update timer count - */ - list_for_each_entry(tmp_timer, &active_timers, list) - if (tmp_timer == timer) { - timer->count = timer->expires; - return; - } - timer->count = timer->expires; - list_add_tail(&timer->list, &active_timers); -} - -/* Remove timer from the timer list; clear timeout status */ -void fsl_otg_del_timer(void *gtimer) -{ - struct fsl_otg_timer *timer = gtimer; - struct fsl_otg_timer *tmp_timer, *del_tmp; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) - if (tmp_timer == timer) - list_del(&timer->list); -} - -/* - * Reduce timer count by 1, and find timeout conditions. - * Called by fsl_otg 1ms timer interrupt - */ -int fsl_otg_tick_timer(void) -{ - struct fsl_otg_timer *tmp_timer, *del_tmp; - int expired = 0; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { - tmp_timer->count--; - /* check if timer expires */ - if (!tmp_timer->count) { - list_del(&tmp_timer->list); - tmp_timer->function(tmp_timer->data); - expired = 1; - } - } - - return expired; -} - -/* Reset controller, not reset the bus */ -void otg_reset_controller(void) -{ - u32 command; - - command = fsl_readl(&usb_dr_regs->usbcmd); - command |= (1 << 1); - fsl_writel(command, &usb_dr_regs->usbcmd); - while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1)) - ; -} - -/* Call suspend/resume routines in host driver */ -int fsl_otg_start_host(struct otg_fsm *fsm, int on) -{ - struct otg_transceiver *xceiv = fsm->transceiver; - struct device *dev; - struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); - u32 retval = 0; - - if (!xceiv->host) - return -ENODEV; - dev = xceiv->host->controller; - - /* - * Update a_vbus_vld state as a_vbus_vld int is disabled - * in device mode - */ - fsm->a_vbus_vld = - !!(fsl_readl(&usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID); - if (on) { - /* start fsl usb host controller */ - if (otg_dev->host_working) - goto end; - else { - otg_reset_controller(); - VDBG("host on......\n"); - if (dev->driver->pm && dev->driver->pm->resume) { - retval = dev->driver->pm->resume(dev); - if (fsm->id) { - /* default-b */ - fsl_otg_drv_vbus(1); - /* - * Workaround: b_host can't driver - * vbus, but PP in PORTSC needs to - * be 1 for host to work. - * So we set drv_vbus bit in - * transceiver to 0 thru ULPI. - */ - write_ulpi(0x0c, 0x20); - } - } - - otg_dev->host_working = 1; - } - } else { - /* stop fsl usb host controller */ - if (!otg_dev->host_working) - goto end; - else { - VDBG("host off......\n"); - if (dev && dev->driver) { - if (dev->driver->pm && dev->driver->pm->suspend) - retval = dev->driver->pm->suspend(dev); - if (fsm->id) - /* default-b */ - fsl_otg_drv_vbus(0); - } - otg_dev->host_working = 0; - } - } -end: - return retval; -} - -/* - * Call suspend and resume function in udc driver - * to stop and start udc driver. - */ -int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) -{ - struct otg_transceiver *xceiv = fsm->transceiver; - struct device *dev; - - if (!xceiv->gadget || !xceiv->gadget->dev.parent) - return -ENODEV; - - VDBG("gadget %s\n", on ? "on" : "off"); - dev = xceiv->gadget->dev.parent; - - if (on) { - if (dev->driver->resume) - dev->driver->resume(dev); - } else { - if (dev->driver->suspend) - dev->driver->suspend(dev, otg_suspend_state); - } - - return 0; -} - -/* - * Called by initialization code of host driver. Register host controller - * to the OTG. Suspend host for OTG role detection. - */ -static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) -{ - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); - - if (!otg_p || otg_dev != fsl_otg_dev) - return -ENODEV; - - otg_p->host = host; - - otg_dev->fsm.a_bus_drop = 0; - otg_dev->fsm.a_bus_req = 1; - - if (host) { - VDBG("host off......\n"); - - otg_p->host->otg_port = fsl_otg_initdata.otg_port; - otg_p->host->is_b_host = otg_dev->fsm.id; - /* - * must leave time for khubd to finish its thing - * before yanking the host driver out from under it, - * so suspend the host after a short delay. - */ - otg_dev->host_working = 1; - schedule_delayed_work(&otg_dev->otg_event, 100); - return 0; - } else { - /* host driver going away */ - if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) & - OTGSC_STS_USB_ID)) { - /* Mini-A cable connected */ - struct otg_fsm *fsm = &otg_dev->fsm; - - otg_p->state = OTG_STATE_UNDEFINED; - fsm->protocol = PROTO_UNDEF; - } - } - - otg_dev->host_working = 0; - - otg_statemachine(&otg_dev->fsm); - - return 0; -} - -/* Called by initialization code of udc. Register udc to OTG. */ -static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, - struct usb_gadget *gadget) -{ - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); - - VDBG("otg_dev 0x%x\n", (int)otg_dev); - VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); - - if (!otg_p || otg_dev != fsl_otg_dev) - return -ENODEV; - - if (!gadget) { - if (!otg_dev->otg.default_a) - otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); - usb_gadget_vbus_disconnect(otg_dev->otg.gadget); - otg_dev->otg.gadget = 0; - otg_dev->fsm.b_bus_req = 0; - otg_statemachine(&otg_dev->fsm); - return 0; - } - - otg_p->gadget = gadget; - otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; - - otg_dev->fsm.b_bus_req = 1; - - /* start the gadget right away if the ID pin says Mini-B */ - DBG("ID pin=%d\n", otg_dev->fsm.id); - if (otg_dev->fsm.id == 1) { - fsl_otg_start_host(&otg_dev->fsm, 0); - otg_drv_vbus(&otg_dev->fsm, 0); - fsl_otg_start_gadget(&otg_dev->fsm, 1); - } - - return 0; -} - -/* Set OTG port power, only for B-device */ -static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA) -{ - if (!fsl_otg_dev) - return -ENODEV; - if (otg_p->state == OTG_STATE_B_PERIPHERAL) - pr_info("FSL OTG: Draw %d mA\n", mA); - - return 0; -} - -/* - * Delayed pin detect interrupt processing. - * - * When the Mini-A cable is disconnected from the board, - * the pin-detect interrupt happens before the disconnnect - * interrupts for the connected device(s). In order to - * process the disconnect interrupt(s) prior to switching - * roles, the pin-detect interrupts are delayed, and handled - * by this routine. - */ -static void fsl_otg_event(struct work_struct *work) -{ - struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work); - struct otg_fsm *fsm = &og->fsm; - - if (fsm->id) { /* switch to gadget */ - fsl_otg_start_host(fsm, 0); - otg_drv_vbus(fsm, 0); - fsl_otg_start_gadget(fsm, 1); - } -} - -/* B-device start SRP */ -static int fsl_otg_start_srp(struct otg_transceiver *otg_p) -{ - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); - - if (!otg_p || otg_dev != fsl_otg_dev - || otg_p->state != OTG_STATE_B_IDLE) - return -ENODEV; - - otg_dev->fsm.b_bus_req = 1; - otg_statemachine(&otg_dev->fsm); - - return 0; -} - -/* A_host suspend will call this function to start hnp */ -static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) -{ - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); - - if (!otg_p || otg_dev != fsl_otg_dev) - return -ENODEV; - - DBG("start_hnp...n"); - - /* clear a_bus_req to enter a_suspend state */ - otg_dev->fsm.a_bus_req = 0; - otg_statemachine(&otg_dev->fsm); - - return 0; -} - -/* - * Interrupt handler. OTG/host/peripheral share the same int line. - * OTG driver clears OTGSC interrupts and leaves USB interrupts - * intact. It needs to have knowledge of some USB interrupts - * such as port change. - */ -irqreturn_t fsl_otg_isr(int irq, void *dev_id) -{ - struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; - struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg; - u32 otg_int_src, otg_sc; - - otg_sc = fsl_readl(&usb_dr_regs->otgsc); - otg_int_src = otg_sc & OTGSC_INTSTS_MASK & (otg_sc >> 8); - - /* Only clear otg interrupts */ - fsl_writel(otg_sc, &usb_dr_regs->otgsc); - - /*FIXME: ID change not generate when init to 0 */ - fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; - otg->default_a = (fsm->id == 0); - - /* process OTG interrupts */ - if (otg_int_src) { - if (otg_int_src & OTGSC_INTSTS_USB_ID) { - fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; - otg->default_a = (fsm->id == 0); - /* clear conn information */ - if (fsm->id) - fsm->b_conn = 0; - else - fsm->a_conn = 0; - - if (otg->host) - otg->host->is_b_host = fsm->id; - if (otg->gadget) - otg->gadget->is_a_peripheral = !fsm->id; - VDBG("ID int (ID is %d)\n", fsm->id); - - if (fsm->id) { /* switch to gadget */ - schedule_delayed_work( - &((struct fsl_otg *)dev_id)->otg_event, - 100); - } else { /* switch to host */ - cancel_delayed_work(& - ((struct fsl_otg *)dev_id)-> - otg_event); - fsl_otg_start_gadget(fsm, 0); - otg_drv_vbus(fsm, 1); - fsl_otg_start_host(fsm, 1); - } - return IRQ_HANDLED; - } - } - return IRQ_NONE; -} - -static struct otg_fsm_ops fsl_otg_ops = { - .chrg_vbus = fsl_otg_chrg_vbus, - .drv_vbus = fsl_otg_drv_vbus, - .loc_conn = fsl_otg_loc_conn, - .loc_sof = fsl_otg_loc_sof, - .start_pulse = fsl_otg_start_pulse, - - .add_timer = fsl_otg_add_timer, - .del_timer = fsl_otg_del_timer, - - .start_host = fsl_otg_start_host, - .start_gadget = fsl_otg_start_gadget, -}; - -/* Initialize the global variable fsl_otg_dev and request IRQ for OTG */ -static int fsl_otg_conf(struct platform_device *pdev) -{ - struct fsl_otg *fsl_otg_tc; - int status; - - if (fsl_otg_dev) - return 0; - - /* allocate space to fsl otg device */ - fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL); - if (!fsl_otg_tc) - return -ENOMEM; - - INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event); - - INIT_LIST_HEAD(&active_timers); - status = fsl_otg_init_timers(&fsl_otg_tc->fsm); - if (status) { - pr_info("Couldn't init OTG timers\n"); - goto err; - } - spin_lock_init(&fsl_otg_tc->fsm.lock); - - /* Set OTG state machine operations */ - fsl_otg_tc->fsm.ops = &fsl_otg_ops; - - /* initialize the otg structure */ - fsl_otg_tc->otg.label = DRIVER_DESC; - fsl_otg_tc->otg.set_host = fsl_otg_set_host; - fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral; - fsl_otg_tc->otg.set_power = fsl_otg_set_power; - fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; - fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; - - fsl_otg_dev = fsl_otg_tc; - - /* Store the otg transceiver */ - status = otg_set_transceiver(&fsl_otg_tc->otg); - if (status) { - pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); - goto err; - } - - return 0; -err: - fsl_otg_uninit_timers(); - kfree(fsl_otg_tc); - return status; -} - -/* OTG Initialization */ -int usb_otg_start(struct platform_device *pdev) -{ - struct fsl_otg *p_otg; - struct otg_transceiver *otg_trans = otg_get_transceiver(); - struct otg_fsm *fsm; - int status; - struct resource *res; - u32 temp; - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - - p_otg = container_of(otg_trans, struct fsl_otg, otg); - fsm = &p_otg->fsm; - - /* Initialize the state machine structure with default values */ - SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); - fsm->transceiver = &p_otg->otg; - - /* We don't require predefined MEM/IRQ resource index */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - /* We don't request_mem_region here to enable resource sharing - * with host/device */ - - usb_dr_regs = ioremap(res->start, sizeof(struct usb_dr_mmap)); - p_otg->dr_mem_map = (struct usb_dr_mmap *)usb_dr_regs; - pdata->regs = (void *)usb_dr_regs; - - if (pdata->init && pdata->init(pdev) != 0) - return -EINVAL; - - if (pdata->big_endian_mmio) { - _fsl_readl = _fsl_readl_be; - _fsl_writel = _fsl_writel_be; - } else { - _fsl_readl = _fsl_readl_le; - _fsl_writel = _fsl_writel_le; - } - - /* request irq */ - p_otg->irq = platform_get_irq(pdev, 0); - status = request_irq(p_otg->irq, fsl_otg_isr, - IRQF_SHARED, driver_name, p_otg); - if (status) { - dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n", - p_otg->irq, status); - iounmap(p_otg->dr_mem_map); - kfree(p_otg); - return status; - } - - /* stop the controller */ - temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); - temp &= ~USB_CMD_RUN_STOP; - fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); - - /* reset the controller */ - temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); - temp |= USB_CMD_CTRL_RESET; - fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); - - /* wait reset completed */ - while (fsl_readl(&p_otg->dr_mem_map->usbcmd) & USB_CMD_CTRL_RESET) - ; - - /* configure the VBUSHS as IDLE(both host and device) */ - temp = USB_MODE_STREAM_DISABLE | (pdata->es ? USB_MODE_ES : 0); - fsl_writel(temp, &p_otg->dr_mem_map->usbmode); - - /* configure PHY interface */ - temp = fsl_readl(&p_otg->dr_mem_map->portsc); - temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW); - switch (pdata->phy_mode) { - case FSL_USB2_PHY_ULPI: - temp |= PORTSC_PTS_ULPI; - break; - case FSL_USB2_PHY_UTMI_WIDE: - temp |= PORTSC_PTW_16BIT; - /* fall through */ - case FSL_USB2_PHY_UTMI: - temp |= PORTSC_PTS_UTMI; - /* fall through */ - default: - break; - } - fsl_writel(temp, &p_otg->dr_mem_map->portsc); - - if (pdata->have_sysif_regs) { - /* configure control enable IO output, big endian register */ - temp = __raw_readl(&p_otg->dr_mem_map->control); - temp |= USB_CTRL_IOENB; - __raw_writel(temp, &p_otg->dr_mem_map->control); - } - - /* disable all interrupt and clear all OTGSC status */ - temp = fsl_readl(&p_otg->dr_mem_map->otgsc); - temp &= ~OTGSC_INTERRUPT_ENABLE_BITS_MASK; - temp |= OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE; - fsl_writel(temp, &p_otg->dr_mem_map->otgsc); - - /* - * The identification (id) input is FALSE when a Mini-A plug is inserted - * in the devices Mini-AB receptacle. Otherwise, this input is TRUE. - * Also: record initial state of ID pin - */ - if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) { - p_otg->otg.state = OTG_STATE_UNDEFINED; - p_otg->fsm.id = 1; - } else { - p_otg->otg.state = OTG_STATE_A_IDLE; - p_otg->fsm.id = 0; - } - - DBG("initial ID pin=%d\n", p_otg->fsm.id); - - /* enable OTG ID pin interrupt */ - temp = fsl_readl(&p_otg->dr_mem_map->otgsc); - temp |= OTGSC_INTR_USB_ID_EN; - temp &= ~(OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN); - fsl_writel(temp, &p_otg->dr_mem_map->otgsc); - - return 0; -} - -/* - * state file in sysfs - */ -static int show_fsl_usb2_otg_state(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct otg_fsm *fsm = &fsl_otg_dev->fsm; - char *next = buf; - unsigned size = PAGE_SIZE; - unsigned long flags; - int t; - - spin_lock_irqsave(&fsm->lock, flags); - - /* basic driver infomation */ - t = scnprintf(next, size, - DRIVER_DESC "\n" "fsl_usb2_otg version: %s\n\n", - DRIVER_VERSION); - size -= t; - next += t; - - /* Registers */ - t = scnprintf(next, size, - "OTGSC: 0x%08x\n" - "PORTSC: 0x%08x\n" - "USBMODE: 0x%08x\n" - "USBCMD: 0x%08x\n" - "USBSTS: 0x%08x\n" - "USBINTR: 0x%08x\n", - fsl_readl(&usb_dr_regs->otgsc), - fsl_readl(&usb_dr_regs->portsc), - fsl_readl(&usb_dr_regs->usbmode), - fsl_readl(&usb_dr_regs->usbcmd), - fsl_readl(&usb_dr_regs->usbsts), - fsl_readl(&usb_dr_regs->usbintr)); - size -= t; - next += t; - - /* State */ - t = scnprintf(next, size, - "OTG state: %s\n\n", - otg_state_string(fsl_otg_dev->otg.state)); - size -= t; - next += t; - - /* State Machine Variables */ - t = scnprintf(next, size, - "a_bus_req: %d\n" - "b_bus_req: %d\n" - "a_bus_resume: %d\n" - "a_bus_suspend: %d\n" - "a_conn: %d\n" - "a_sess_vld: %d\n" - "a_srp_det: %d\n" - "a_vbus_vld: %d\n" - "b_bus_resume: %d\n" - "b_bus_suspend: %d\n" - "b_conn: %d\n" - "b_se0_srp: %d\n" - "b_sess_end: %d\n" - "b_sess_vld: %d\n" - "id: %d\n", - fsm->a_bus_req, - fsm->b_bus_req, - fsm->a_bus_resume, - fsm->a_bus_suspend, - fsm->a_conn, - fsm->a_sess_vld, - fsm->a_srp_det, - fsm->a_vbus_vld, - fsm->b_bus_resume, - fsm->b_bus_suspend, - fsm->b_conn, - fsm->b_se0_srp, - fsm->b_sess_end, - fsm->b_sess_vld, - fsm->id); - size -= t; - next += t; - - spin_unlock_irqrestore(&fsm->lock, flags); - - return PAGE_SIZE - size; -} - -static DEVICE_ATTR(fsl_usb2_otg_state, S_IRUGO, show_fsl_usb2_otg_state, NULL); - - -/* Char driver interface to control some OTG input */ - -/* - * Handle some ioctl command, such as get otg - * status and set host suspend - */ -static long fsl_otg_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - u32 retval = 0; - - switch (cmd) { - case GET_OTG_STATUS: - retval = fsl_otg_dev->host_working; - break; - - case SET_A_SUSPEND_REQ: - fsl_otg_dev->fsm.a_suspend_req = arg; - break; - - case SET_A_BUS_DROP: - fsl_otg_dev->fsm.a_bus_drop = arg; - break; - - case SET_A_BUS_REQ: - fsl_otg_dev->fsm.a_bus_req = arg; - break; - - case SET_B_BUS_REQ: - fsl_otg_dev->fsm.b_bus_req = arg; - break; - - default: - break; - } - - otg_statemachine(&fsl_otg_dev->fsm); - - return retval; -} - -static int fsl_otg_open(struct inode *inode, struct file *file) -{ - return 0; -} - -static int fsl_otg_release(struct inode *inode, struct file *file) -{ - return 0; -} - -static const struct file_operations otg_fops = { - .owner = THIS_MODULE, - .llseek = NULL, - .read = NULL, - .write = NULL, - .unlocked_ioctl = fsl_otg_ioctl, - .open = fsl_otg_open, - .release = fsl_otg_release, -}; - -static int __devinit fsl_otg_probe(struct platform_device *pdev) -{ - int ret; - - if (!pdev->dev.platform_data) - return -ENODEV; - - /* configure the OTG */ - ret = fsl_otg_conf(pdev); - if (ret) { - dev_err(&pdev->dev, "Couldn't configure OTG module\n"); - return ret; - } - - /* start OTG */ - ret = usb_otg_start(pdev); - if (ret) { - dev_err(&pdev->dev, "Can't init FSL OTG device\n"); - return ret; - } - - ret = register_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME, &otg_fops); - if (ret) { - dev_err(&pdev->dev, "unable to register FSL OTG device\n"); - return ret; - } - - ret = device_create_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); - if (ret) - dev_warn(&pdev->dev, "Can't register sysfs attribute\n"); - - return ret; -} - -static int __devexit fsl_otg_remove(struct platform_device *pdev) -{ - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - - otg_set_transceiver(NULL); - free_irq(fsl_otg_dev->irq, fsl_otg_dev); - - iounmap((void *)usb_dr_regs); - - fsl_otg_uninit_timers(); - kfree(fsl_otg_dev); - - device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); - - unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME); - - if (pdata->exit) - pdata->exit(pdev); - - return 0; -} - -struct platform_driver fsl_otg_driver = { - .probe = fsl_otg_probe, - .remove = __devexit_p(fsl_otg_remove), - .driver = { - .name = driver_name, - .owner = THIS_MODULE, - }, -}; - -static int __init fsl_usb_otg_init(void) -{ - pr_info(DRIVER_INFO "\n"); - return platform_driver_register(&fsl_otg_driver); -} -module_init(fsl_usb_otg_init); - -static void __exit fsl_usb_otg_exit(void) -{ - platform_driver_unregister(&fsl_otg_driver); -} -module_exit(fsl_usb_otg_exit); - -MODULE_DESCRIPTION(DRIVER_INFO); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/otg/fsl_otg.h b/trunk/drivers/usb/otg/fsl_otg.h deleted file mode 100644 index 3f8ef731aac9..000000000000 --- a/trunk/drivers/usb/otg/fsl_otg.h +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "otg_fsm.h" -#include -#include - -/* USB Command Register Bit Masks */ -#define USB_CMD_RUN_STOP (0x1<<0) -#define USB_CMD_CTRL_RESET (0x1<<1) -#define USB_CMD_PERIODIC_SCHEDULE_EN (0x1<<4) -#define USB_CMD_ASYNC_SCHEDULE_EN (0x1<<5) -#define USB_CMD_INT_AA_DOORBELL (0x1<<6) -#define USB_CMD_ASP (0x3<<8) -#define USB_CMD_ASYNC_SCH_PARK_EN (0x1<<11) -#define USB_CMD_SUTW (0x1<<13) -#define USB_CMD_ATDTW (0x1<<14) -#define USB_CMD_ITC (0xFF<<16) - -/* bit 15,3,2 are frame list size */ -#define USB_CMD_FRAME_SIZE_1024 (0x0<<15 | 0x0<<2) -#define USB_CMD_FRAME_SIZE_512 (0x0<<15 | 0x1<<2) -#define USB_CMD_FRAME_SIZE_256 (0x0<<15 | 0x2<<2) -#define USB_CMD_FRAME_SIZE_128 (0x0<<15 | 0x3<<2) -#define USB_CMD_FRAME_SIZE_64 (0x1<<15 | 0x0<<2) -#define USB_CMD_FRAME_SIZE_32 (0x1<<15 | 0x1<<2) -#define USB_CMD_FRAME_SIZE_16 (0x1<<15 | 0x2<<2) -#define USB_CMD_FRAME_SIZE_8 (0x1<<15 | 0x3<<2) - -/* bit 9-8 are async schedule park mode count */ -#define USB_CMD_ASP_00 (0x0<<8) -#define USB_CMD_ASP_01 (0x1<<8) -#define USB_CMD_ASP_10 (0x2<<8) -#define USB_CMD_ASP_11 (0x3<<8) -#define USB_CMD_ASP_BIT_POS (8) - -/* bit 23-16 are interrupt threshold control */ -#define USB_CMD_ITC_NO_THRESHOLD (0x00<<16) -#define USB_CMD_ITC_1_MICRO_FRM (0x01<<16) -#define USB_CMD_ITC_2_MICRO_FRM (0x02<<16) -#define USB_CMD_ITC_4_MICRO_FRM (0x04<<16) -#define USB_CMD_ITC_8_MICRO_FRM (0x08<<16) -#define USB_CMD_ITC_16_MICRO_FRM (0x10<<16) -#define USB_CMD_ITC_32_MICRO_FRM (0x20<<16) -#define USB_CMD_ITC_64_MICRO_FRM (0x40<<16) -#define USB_CMD_ITC_BIT_POS (16) - -/* USB Status Register Bit Masks */ -#define USB_STS_INT (0x1<<0) -#define USB_STS_ERR (0x1<<1) -#define USB_STS_PORT_CHANGE (0x1<<2) -#define USB_STS_FRM_LST_ROLL (0x1<<3) -#define USB_STS_SYS_ERR (0x1<<4) -#define USB_STS_IAA (0x1<<5) -#define USB_STS_RESET_RECEIVED (0x1<<6) -#define USB_STS_SOF (0x1<<7) -#define USB_STS_DCSUSPEND (0x1<<8) -#define USB_STS_HC_HALTED (0x1<<12) -#define USB_STS_RCL (0x1<<13) -#define USB_STS_PERIODIC_SCHEDULE (0x1<<14) -#define USB_STS_ASYNC_SCHEDULE (0x1<<15) - -/* USB Interrupt Enable Register Bit Masks */ -#define USB_INTR_INT_EN (0x1<<0) -#define USB_INTR_ERR_INT_EN (0x1<<1) -#define USB_INTR_PC_DETECT_EN (0x1<<2) -#define USB_INTR_FRM_LST_ROLL_EN (0x1<<3) -#define USB_INTR_SYS_ERR_EN (0x1<<4) -#define USB_INTR_ASYN_ADV_EN (0x1<<5) -#define USB_INTR_RESET_EN (0x1<<6) -#define USB_INTR_SOF_EN (0x1<<7) -#define USB_INTR_DEVICE_SUSPEND (0x1<<8) - -/* Device Address bit masks */ -#define USB_DEVICE_ADDRESS_MASK (0x7F<<25) -#define USB_DEVICE_ADDRESS_BIT_POS (25) -/* PORTSC Register Bit Masks,Only one PORT in OTG mode*/ -#define PORTSC_CURRENT_CONNECT_STATUS (0x1<<0) -#define PORTSC_CONNECT_STATUS_CHANGE (0x1<<1) -#define PORTSC_PORT_ENABLE (0x1<<2) -#define PORTSC_PORT_EN_DIS_CHANGE (0x1<<3) -#define PORTSC_OVER_CURRENT_ACT (0x1<<4) -#define PORTSC_OVER_CUURENT_CHG (0x1<<5) -#define PORTSC_PORT_FORCE_RESUME (0x1<<6) -#define PORTSC_PORT_SUSPEND (0x1<<7) -#define PORTSC_PORT_RESET (0x1<<8) -#define PORTSC_LINE_STATUS_BITS (0x3<<10) -#define PORTSC_PORT_POWER (0x1<<12) -#define PORTSC_PORT_INDICTOR_CTRL (0x3<<14) -#define PORTSC_PORT_TEST_CTRL (0xF<<16) -#define PORTSC_WAKE_ON_CONNECT_EN (0x1<<20) -#define PORTSC_WAKE_ON_CONNECT_DIS (0x1<<21) -#define PORTSC_WAKE_ON_OVER_CURRENT (0x1<<22) -#define PORTSC_PHY_LOW_POWER_SPD (0x1<<23) -#define PORTSC_PORT_FORCE_FULL_SPEED (0x1<<24) -#define PORTSC_PORT_SPEED_MASK (0x3<<26) -#define PORTSC_TRANSCEIVER_WIDTH (0x1<<28) -#define PORTSC_PHY_TYPE_SEL (0x3<<30) -/* bit 11-10 are line status */ -#define PORTSC_LINE_STATUS_SE0 (0x0<<10) -#define PORTSC_LINE_STATUS_JSTATE (0x1<<10) -#define PORTSC_LINE_STATUS_KSTATE (0x2<<10) -#define PORTSC_LINE_STATUS_UNDEF (0x3<<10) -#define PORTSC_LINE_STATUS_BIT_POS (10) - -/* bit 15-14 are port indicator control */ -#define PORTSC_PIC_OFF (0x0<<14) -#define PORTSC_PIC_AMBER (0x1<<14) -#define PORTSC_PIC_GREEN (0x2<<14) -#define PORTSC_PIC_UNDEF (0x3<<14) -#define PORTSC_PIC_BIT_POS (14) - -/* bit 19-16 are port test control */ -#define PORTSC_PTC_DISABLE (0x0<<16) -#define PORTSC_PTC_JSTATE (0x1<<16) -#define PORTSC_PTC_KSTATE (0x2<<16) -#define PORTSC_PTC_SEQNAK (0x3<<16) -#define PORTSC_PTC_PACKET (0x4<<16) -#define PORTSC_PTC_FORCE_EN (0x5<<16) -#define PORTSC_PTC_BIT_POS (16) - -/* bit 27-26 are port speed */ -#define PORTSC_PORT_SPEED_FULL (0x0<<26) -#define PORTSC_PORT_SPEED_LOW (0x1<<26) -#define PORTSC_PORT_SPEED_HIGH (0x2<<26) -#define PORTSC_PORT_SPEED_UNDEF (0x3<<26) -#define PORTSC_SPEED_BIT_POS (26) - -/* bit 28 is parallel transceiver width for UTMI interface */ -#define PORTSC_PTW (0x1<<28) -#define PORTSC_PTW_8BIT (0x0<<28) -#define PORTSC_PTW_16BIT (0x1<<28) - -/* bit 31-30 are port transceiver select */ -#define PORTSC_PTS_UTMI (0x0<<30) -#define PORTSC_PTS_ULPI (0x2<<30) -#define PORTSC_PTS_FSLS_SERIAL (0x3<<30) -#define PORTSC_PTS_BIT_POS (30) - -#define PORTSC_W1C_BITS \ - (PORTSC_CONNECT_STATUS_CHANGE | \ - PORTSC_PORT_EN_DIS_CHANGE | \ - PORTSC_OVER_CUURENT_CHG) - -/* OTG Status Control Register Bit Masks */ -#define OTGSC_CTRL_VBUS_DISCHARGE (0x1<<0) -#define OTGSC_CTRL_VBUS_CHARGE (0x1<<1) -#define OTGSC_CTRL_OTG_TERMINATION (0x1<<3) -#define OTGSC_CTRL_DATA_PULSING (0x1<<4) -#define OTGSC_CTRL_ID_PULL_EN (0x1<<5) -#define OTGSC_HA_DATA_PULSE (0x1<<6) -#define OTGSC_HA_BA (0x1<<7) -#define OTGSC_STS_USB_ID (0x1<<8) -#define OTGSC_STS_A_VBUS_VALID (0x1<<9) -#define OTGSC_STS_A_SESSION_VALID (0x1<<10) -#define OTGSC_STS_B_SESSION_VALID (0x1<<11) -#define OTGSC_STS_B_SESSION_END (0x1<<12) -#define OTGSC_STS_1MS_TOGGLE (0x1<<13) -#define OTGSC_STS_DATA_PULSING (0x1<<14) -#define OTGSC_INTSTS_USB_ID (0x1<<16) -#define OTGSC_INTSTS_A_VBUS_VALID (0x1<<17) -#define OTGSC_INTSTS_A_SESSION_VALID (0x1<<18) -#define OTGSC_INTSTS_B_SESSION_VALID (0x1<<19) -#define OTGSC_INTSTS_B_SESSION_END (0x1<<20) -#define OTGSC_INTSTS_1MS (0x1<<21) -#define OTGSC_INTSTS_DATA_PULSING (0x1<<22) -#define OTGSC_INTR_USB_ID_EN (0x1<<24) -#define OTGSC_INTR_A_VBUS_VALID_EN (0x1<<25) -#define OTGSC_INTR_A_SESSION_VALID_EN (0x1<<26) -#define OTGSC_INTR_B_SESSION_VALID_EN (0x1<<27) -#define OTGSC_INTR_B_SESSION_END_EN (0x1<<28) -#define OTGSC_INTR_1MS_TIMER_EN (0x1<<29) -#define OTGSC_INTR_DATA_PULSING_EN (0x1<<30) -#define OTGSC_INTSTS_MASK (0x00ff0000) - -/* USB MODE Register Bit Masks */ -#define USB_MODE_CTRL_MODE_IDLE (0x0<<0) -#define USB_MODE_CTRL_MODE_DEVICE (0x2<<0) -#define USB_MODE_CTRL_MODE_HOST (0x3<<0) -#define USB_MODE_CTRL_MODE_RSV (0x1<<0) -#define USB_MODE_SETUP_LOCK_OFF (0x1<<3) -#define USB_MODE_STREAM_DISABLE (0x1<<4) -#define USB_MODE_ES (0x1<<2) /* Endian Select */ - -/* control Register Bit Masks */ -#define USB_CTRL_IOENB (0x1<<2) -#define USB_CTRL_ULPI_INT0EN (0x1<<0) - -/* BCSR5 */ -#define BCSR5_INT_USB (0x02) - -/* USB module clk cfg */ -#define SCCR_OFFS (0xA08) -#define SCCR_USB_CLK_DISABLE (0x00000000) /* USB clk disable */ -#define SCCR_USB_MPHCM_11 (0x00c00000) -#define SCCR_USB_MPHCM_01 (0x00400000) -#define SCCR_USB_MPHCM_10 (0x00800000) -#define SCCR_USB_DRCM_11 (0x00300000) -#define SCCR_USB_DRCM_01 (0x00100000) -#define SCCR_USB_DRCM_10 (0x00200000) - -#define SICRL_OFFS (0x114) -#define SICRL_USB0 (0x40000000) -#define SICRL_USB1 (0x20000000) - -#define SICRH_OFFS (0x118) -#define SICRH_USB_UTMI (0x00020000) - -/* OTG interrupt enable bit masks */ -#define OTGSC_INTERRUPT_ENABLE_BITS_MASK \ - (OTGSC_INTR_USB_ID_EN | \ - OTGSC_INTR_1MS_TIMER_EN | \ - OTGSC_INTR_A_VBUS_VALID_EN | \ - OTGSC_INTR_A_SESSION_VALID_EN | \ - OTGSC_INTR_B_SESSION_VALID_EN | \ - OTGSC_INTR_B_SESSION_END_EN | \ - OTGSC_INTR_DATA_PULSING_EN) - -/* OTG interrupt status bit masks */ -#define OTGSC_INTERRUPT_STATUS_BITS_MASK \ - (OTGSC_INTSTS_USB_ID | \ - OTGSC_INTR_1MS_TIMER_EN | \ - OTGSC_INTSTS_A_VBUS_VALID | \ - OTGSC_INTSTS_A_SESSION_VALID | \ - OTGSC_INTSTS_B_SESSION_VALID | \ - OTGSC_INTSTS_B_SESSION_END | \ - OTGSC_INTSTS_DATA_PULSING) - -/* - * A-DEVICE timing constants - */ - -/* Wait for VBUS Rise */ -#define TA_WAIT_VRISE (100) /* a_wait_vrise 100 ms, section: 6.6.5.1 */ - -/* Wait for B-Connect */ -#define TA_WAIT_BCON (10000) /* a_wait_bcon > 1 sec, section: 6.6.5.2 - * This is only used to get out of - * OTG_STATE_A_WAIT_BCON state if there was - * no connection for these many milliseconds - */ - -/* A-Idle to B-Disconnect */ -/* It is necessary for this timer to be more than 750 ms because of a bug in OPT - * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated - * in the test description - */ -#define TA_AIDL_BDIS (5000) /* a_suspend minimum 200 ms, section: 6.6.5.3 */ - -/* B-Idle to A-Disconnect */ -#define TA_BIDL_ADIS (12) /* 3 to 200 ms */ - -/* B-device timing constants */ - - -/* Data-Line Pulse Time*/ -#define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms, section:5.3.3 */ -#define TB_DATA_PLS_MIN (5) /* minimum 5 ms */ -#define TB_DATA_PLS_MAX (10) /* maximum 10 ms */ - -/* SRP Initiate Time */ -#define TB_SRP_INIT (100) /* b_srp_init,maximum 100 ms, section:5.3.8 */ - -/* SRP Fail Time */ -#define TB_SRP_FAIL (7000) /* b_srp_init,Fail time 5~30s, section:6.8.2.2*/ - -/* SRP result wait time */ -#define TB_SRP_WAIT (60) - -/* VBus time */ -#define TB_VBUS_PLS (30) /* time to keep vbus pulsing asserted */ - -/* Discharge time */ -/* This time should be less than 10ms. It varies from system to system. */ -#define TB_VBUS_DSCHRG (8) - -/* A-SE0 to B-Reset */ -#define TB_ASE0_BRST (20) /* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */ - -/* A bus suspend timer before we can switch to b_wait_aconn */ -#define TB_A_SUSPEND (7) -#define TB_BUS_RESUME (12) - -/* SE0 Time Before SRP */ -#define TB_SE0_SRP (2) /* b_idle,minimum 2 ms, section:5.3.2 */ - -#define SET_OTG_STATE(otg_ptr, newstate) ((otg_ptr)->state = newstate) - -struct usb_dr_mmap { - /* Capability register */ - u8 res1[256]; - u16 caplength; /* Capability Register Length */ - u16 hciversion; /* Host Controller Interface Version */ - u32 hcsparams; /* Host Controller Structual Parameters */ - u32 hccparams; /* Host Controller Capability Parameters */ - u8 res2[20]; - u32 dciversion; /* Device Controller Interface Version */ - u32 dccparams; /* Device Controller Capability Parameters */ - u8 res3[24]; - /* Operation register */ - u32 usbcmd; /* USB Command Register */ - u32 usbsts; /* USB Status Register */ - u32 usbintr; /* USB Interrupt Enable Register */ - u32 frindex; /* Frame Index Register */ - u8 res4[4]; - u32 deviceaddr; /* Device Address */ - u32 endpointlistaddr; /* Endpoint List Address Register */ - u8 res5[4]; - u32 burstsize; /* Master Interface Data Burst Size Register */ - u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ - u8 res6[8]; - u32 ulpiview; /* ULPI register access */ - u8 res7[12]; - u32 configflag; /* Configure Flag Register */ - u32 portsc; /* Port 1 Status and Control Register */ - u8 res8[28]; - u32 otgsc; /* On-The-Go Status and Control */ - u32 usbmode; /* USB Mode Register */ - u32 endptsetupstat; /* Endpoint Setup Status Register */ - u32 endpointprime; /* Endpoint Initialization Register */ - u32 endptflush; /* Endpoint Flush Register */ - u32 endptstatus; /* Endpoint Status Register */ - u32 endptcomplete; /* Endpoint Complete Register */ - u32 endptctrl[6]; /* Endpoint Control Registers */ - u8 res9[552]; - u32 snoop1; - u32 snoop2; - u32 age_cnt_thresh; /* Age Count Threshold Register */ - u32 pri_ctrl; /* Priority Control Register */ - u32 si_ctrl; /* System Interface Control Register */ - u8 res10[236]; - u32 control; /* General Purpose Control Register */ -}; - -struct fsl_otg_timer { - unsigned long expires; /* Number of count increase to timeout */ - unsigned long count; /* Tick counter */ - void (*function)(unsigned long); /* Timeout function */ - unsigned long data; /* Data passed to function */ - struct list_head list; -}; - -inline struct fsl_otg_timer *otg_timer_initializer -(void (*function)(unsigned long), unsigned long expires, unsigned long data) -{ - struct fsl_otg_timer *timer; - - timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL); - if (!timer) - return NULL; - timer->function = function; - timer->expires = expires; - timer->data = data; - return timer; -} - -struct fsl_otg { - struct otg_transceiver otg; - struct otg_fsm fsm; - struct usb_dr_mmap *dr_mem_map; - struct delayed_work otg_event; - - /* used for usb host */ - struct work_struct work_wq; - u8 host_working; - - int irq; -}; - -struct fsl_otg_config { - u8 otg_port; -}; - -/* For SRP and HNP handle */ -#define FSL_OTG_MAJOR 240 -#define FSL_OTG_NAME "fsl-usb2-otg" -/* Command to OTG driver ioctl */ -#define OTG_IOCTL_MAGIC FSL_OTG_MAJOR -/* if otg work as host, it should return 1, otherwise return 0 */ -#define GET_OTG_STATUS _IOR(OTG_IOCTL_MAGIC, 1, int) -#define SET_A_SUSPEND_REQ _IOW(OTG_IOCTL_MAGIC, 2, int) -#define SET_A_BUS_DROP _IOW(OTG_IOCTL_MAGIC, 3, int) -#define SET_A_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 4, int) -#define SET_B_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 5, int) -#define GET_A_SUSPEND_REQ _IOR(OTG_IOCTL_MAGIC, 6, int) -#define GET_A_BUS_DROP _IOR(OTG_IOCTL_MAGIC, 7, int) -#define GET_A_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 8, int) -#define GET_B_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 9, int) - -void fsl_otg_add_timer(void *timer); -void fsl_otg_del_timer(void *timer); -void fsl_otg_pulse_vbus(void); diff --git a/trunk/drivers/usb/otg/isp1301_omap.c b/trunk/drivers/usb/otg/isp1301_omap.c index 8c282258e1bd..e25700f44b6f 100644 --- a/trunk/drivers/usb/otg/isp1301_omap.c +++ b/trunk/drivers/usb/otg/isp1301_omap.c @@ -234,9 +234,29 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) /*-------------------------------------------------------------------------*/ +static const char *state_string(enum usb_otg_state state) +{ + switch (state) { + case OTG_STATE_A_IDLE: return "a_idle"; + case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; + case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; + case OTG_STATE_A_HOST: return "a_host"; + case OTG_STATE_A_SUSPEND: return "a_suspend"; + case OTG_STATE_A_PERIPHERAL: return "a_peripheral"; + case OTG_STATE_A_WAIT_VFALL: return "a_wait_vfall"; + case OTG_STATE_A_VBUS_ERR: return "a_vbus_err"; + case OTG_STATE_B_IDLE: return "b_idle"; + case OTG_STATE_B_SRP_INIT: return "b_srp_init"; + case OTG_STATE_B_PERIPHERAL: return "b_peripheral"; + case OTG_STATE_B_WAIT_ACON: return "b_wait_acon"; + case OTG_STATE_B_HOST: return "b_host"; + default: return "UNDEFINED"; + } +} + static inline const char *state_name(struct isp1301 *isp) { - return otg_state_string(isp->otg.state); + return state_string(isp->otg.state); } /*-------------------------------------------------------------------------*/ @@ -481,7 +501,7 @@ static void check_state(struct isp1301 *isp, const char *tag) if (isp->otg.state == state && !extra) return; pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, - otg_state_string(state), fsm, state_name(isp), + state_string(state), fsm, state_name(isp), omap_readl(OTG_CTRL)); } @@ -1075,7 +1095,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) if (state != isp->otg.state) pr_debug(" isp, %s -> %s\n", - otg_state_string(state), state_name(isp)); + state_string(state), state_name(isp)); #ifdef CONFIG_USB_OTG /* update the OTG controller state to match the isp1301; may diff --git a/trunk/drivers/usb/otg/langwell_otg.c b/trunk/drivers/usb/otg/langwell_otg.c index f08f784086f7..e973ff19c55a 100644 --- a/trunk/drivers/usb/otg/langwell_otg.c +++ b/trunk/drivers/usb/otg/langwell_otg.c @@ -82,6 +82,40 @@ static struct pci_driver otg_pci_driver = { .resume = langwell_otg_resume, }; +static const char *state_string(enum usb_otg_state state) +{ + switch (state) { + case OTG_STATE_A_IDLE: + return "a_idle"; + case OTG_STATE_A_WAIT_VRISE: + return "a_wait_vrise"; + case OTG_STATE_A_WAIT_BCON: + return "a_wait_bcon"; + case OTG_STATE_A_HOST: + return "a_host"; + case OTG_STATE_A_SUSPEND: + return "a_suspend"; + case OTG_STATE_A_PERIPHERAL: + return "a_peripheral"; + case OTG_STATE_A_WAIT_VFALL: + return "a_wait_vfall"; + case OTG_STATE_A_VBUS_ERR: + return "a_vbus_err"; + case OTG_STATE_B_IDLE: + return "b_idle"; + case OTG_STATE_B_SRP_INIT: + return "b_srp_init"; + case OTG_STATE_B_PERIPHERAL: + return "b_peripheral"; + case OTG_STATE_B_WAIT_ACON: + return "b_wait_acon"; + case OTG_STATE_B_HOST: + return "b_host"; + default: + return "UNDEFINED"; + } +} + /* HSM timers */ static inline struct langwell_otg_timer *otg_timer_initializer (void (*function)(unsigned long), unsigned long expires, unsigned long data) @@ -934,7 +968,7 @@ static void langwell_otg_work(struct work_struct *work) pdev = to_pci_dev(lnw->dev); dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, - otg_state_string(iotg->otg.state)); + state_string(iotg->otg.state)); switch (iotg->otg.state) { case OTG_STATE_UNDEFINED: @@ -1669,7 +1703,7 @@ static void langwell_otg_work(struct work_struct *work) } dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, - otg_state_string(iotg->otg.state)); + state_string(iotg->otg.state)); } static ssize_t @@ -1755,7 +1789,7 @@ show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) "b_bus_req = \t%d\n" "b_bus_suspend_tmout = \t%d\n" "b_bus_suspend_vld = \t%d\n", - otg_state_string(iotg->otg.state), + state_string(iotg->otg.state), iotg->hsm.a_bus_resume, iotg->hsm.a_bus_suspend, iotg->hsm.a_conn, diff --git a/trunk/drivers/usb/otg/otg.c b/trunk/drivers/usb/otg/otg.c index fb7adeff9ffa..0a43a7db750f 100644 --- a/trunk/drivers/usb/otg/otg.c +++ b/trunk/drivers/usb/otg/otg.c @@ -64,38 +64,3 @@ int otg_set_transceiver(struct otg_transceiver *x) return 0; } EXPORT_SYMBOL(otg_set_transceiver); - -const char *otg_state_string(enum usb_otg_state state) -{ - switch (state) { - case OTG_STATE_A_IDLE: - return "a_idle"; - case OTG_STATE_A_WAIT_VRISE: - return "a_wait_vrise"; - case OTG_STATE_A_WAIT_BCON: - return "a_wait_bcon"; - case OTG_STATE_A_HOST: - return "a_host"; - case OTG_STATE_A_SUSPEND: - return "a_suspend"; - case OTG_STATE_A_PERIPHERAL: - return "a_peripheral"; - case OTG_STATE_A_WAIT_VFALL: - return "a_wait_vfall"; - case OTG_STATE_A_VBUS_ERR: - return "a_vbus_err"; - case OTG_STATE_B_IDLE: - return "b_idle"; - case OTG_STATE_B_SRP_INIT: - return "b_srp_init"; - case OTG_STATE_B_PERIPHERAL: - return "b_peripheral"; - case OTG_STATE_B_WAIT_ACON: - return "b_wait_acon"; - case OTG_STATE_B_HOST: - return "b_host"; - default: - return "UNDEFINED"; - } -} -EXPORT_SYMBOL(otg_state_string); diff --git a/trunk/drivers/usb/otg/otg_fsm.c b/trunk/drivers/usb/otg/otg_fsm.c deleted file mode 100644 index b0cc422f2ff9..000000000000 --- a/trunk/drivers/usb/otg/otg_fsm.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * OTG Finite State Machine from OTG spec - * - * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. - * - * Author: Li Yang - * Jerry Huang - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "otg_fsm.h" - -/* Change USB protocol when there is a protocol change */ -static int otg_set_protocol(struct otg_fsm *fsm, int protocol) -{ - int ret = 0; - - if (fsm->protocol != protocol) { - VDBG("Changing role fsm->protocol= %d; new protocol= %d\n", - fsm->protocol, protocol); - /* stop old protocol */ - if (fsm->protocol == PROTO_HOST) - ret = fsm->ops->start_host(fsm, 0); - else if (fsm->protocol == PROTO_GADGET) - ret = fsm->ops->start_gadget(fsm, 0); - if (ret) - return ret; - - /* start new protocol */ - if (protocol == PROTO_HOST) - ret = fsm->ops->start_host(fsm, 1); - else if (protocol == PROTO_GADGET) - ret = fsm->ops->start_gadget(fsm, 1); - if (ret) - return ret; - - fsm->protocol = protocol; - return 0; - } - - return 0; -} - -static int state_changed; - -/* Called when leaving a state. Do state clean up jobs here */ -void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) -{ - switch (old_state) { - case OTG_STATE_B_IDLE: - otg_del_timer(fsm, b_se0_srp_tmr); - fsm->b_se0_srp = 0; - break; - case OTG_STATE_B_SRP_INIT: - fsm->b_srp_done = 0; - break; - case OTG_STATE_B_PERIPHERAL: - break; - case OTG_STATE_B_WAIT_ACON: - otg_del_timer(fsm, b_ase0_brst_tmr); - fsm->b_ase0_brst_tmout = 0; - break; - case OTG_STATE_B_HOST: - break; - case OTG_STATE_A_IDLE: - break; - case OTG_STATE_A_WAIT_VRISE: - otg_del_timer(fsm, a_wait_vrise_tmr); - fsm->a_wait_vrise_tmout = 0; - break; - case OTG_STATE_A_WAIT_BCON: - otg_del_timer(fsm, a_wait_bcon_tmr); - fsm->a_wait_bcon_tmout = 0; - break; - case OTG_STATE_A_HOST: - otg_del_timer(fsm, a_wait_enum_tmr); - break; - case OTG_STATE_A_SUSPEND: - otg_del_timer(fsm, a_aidl_bdis_tmr); - fsm->a_aidl_bdis_tmout = 0; - fsm->a_suspend_req = 0; - break; - case OTG_STATE_A_PERIPHERAL: - break; - case OTG_STATE_A_WAIT_VFALL: - otg_del_timer(fsm, a_wait_vrise_tmr); - break; - case OTG_STATE_A_VBUS_ERR: - break; - default: - break; - } -} - -/* Called when entering a state */ -int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) -{ - state_changed = 1; - if (fsm->transceiver->state == new_state) - return 0; - VDBG("Set state: %s\n", otg_state_string(new_state)); - otg_leave_state(fsm, fsm->transceiver->state); - switch (new_state) { - case OTG_STATE_B_IDLE: - otg_drv_vbus(fsm, 0); - otg_chrg_vbus(fsm, 0); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_UNDEF); - otg_add_timer(fsm, b_se0_srp_tmr); - break; - case OTG_STATE_B_SRP_INIT: - otg_start_pulse(fsm); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_UNDEF); - otg_add_timer(fsm, b_srp_fail_tmr); - break; - case OTG_STATE_B_PERIPHERAL: - otg_chrg_vbus(fsm, 0); - otg_loc_conn(fsm, 1); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_GADGET); - break; - case OTG_STATE_B_WAIT_ACON: - otg_chrg_vbus(fsm, 0); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_HOST); - otg_add_timer(fsm, b_ase0_brst_tmr); - fsm->a_bus_suspend = 0; - break; - case OTG_STATE_B_HOST: - otg_chrg_vbus(fsm, 0); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 1); - otg_set_protocol(fsm, PROTO_HOST); - usb_bus_start_enum(fsm->transceiver->host, - fsm->transceiver->host->otg_port); - break; - case OTG_STATE_A_IDLE: - otg_drv_vbus(fsm, 0); - otg_chrg_vbus(fsm, 0); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_HOST); - break; - case OTG_STATE_A_WAIT_VRISE: - otg_drv_vbus(fsm, 1); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_HOST); - otg_add_timer(fsm, a_wait_vrise_tmr); - break; - case OTG_STATE_A_WAIT_BCON: - otg_drv_vbus(fsm, 1); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_HOST); - otg_add_timer(fsm, a_wait_bcon_tmr); - break; - case OTG_STATE_A_HOST: - otg_drv_vbus(fsm, 1); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 1); - otg_set_protocol(fsm, PROTO_HOST); - /* - * When HNP is triggered while a_bus_req = 0, a_host will - * suspend too fast to complete a_set_b_hnp_en - */ - if (!fsm->a_bus_req || fsm->a_suspend_req) - otg_add_timer(fsm, a_wait_enum_tmr); - break; - case OTG_STATE_A_SUSPEND: - otg_drv_vbus(fsm, 1); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_HOST); - otg_add_timer(fsm, a_aidl_bdis_tmr); - - break; - case OTG_STATE_A_PERIPHERAL: - otg_loc_conn(fsm, 1); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_GADGET); - otg_drv_vbus(fsm, 1); - break; - case OTG_STATE_A_WAIT_VFALL: - otg_drv_vbus(fsm, 0); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_HOST); - break; - case OTG_STATE_A_VBUS_ERR: - otg_drv_vbus(fsm, 0); - otg_loc_conn(fsm, 0); - otg_loc_sof(fsm, 0); - otg_set_protocol(fsm, PROTO_UNDEF); - break; - default: - break; - } - - fsm->transceiver->state = new_state; - return 0; -} - -/* State change judgement */ -int otg_statemachine(struct otg_fsm *fsm) -{ - enum usb_otg_state state; - unsigned long flags; - - spin_lock_irqsave(&fsm->lock, flags); - - state = fsm->transceiver->state; - state_changed = 0; - /* State machine state change judgement */ - - switch (state) { - case OTG_STATE_UNDEFINED: - VDBG("fsm->id = %d\n", fsm->id); - if (fsm->id) - otg_set_state(fsm, OTG_STATE_B_IDLE); - else - otg_set_state(fsm, OTG_STATE_A_IDLE); - break; - case OTG_STATE_B_IDLE: - if (!fsm->id) - otg_set_state(fsm, OTG_STATE_A_IDLE); - else if (fsm->b_sess_vld && fsm->transceiver->gadget) - otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); - else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) - otg_set_state(fsm, OTG_STATE_B_SRP_INIT); - break; - case OTG_STATE_B_SRP_INIT: - if (!fsm->id || fsm->b_srp_done) - otg_set_state(fsm, OTG_STATE_B_IDLE); - break; - case OTG_STATE_B_PERIPHERAL: - if (!fsm->id || !fsm->b_sess_vld) - otg_set_state(fsm, OTG_STATE_B_IDLE); - else if (fsm->b_bus_req && fsm->transceiver-> - gadget->b_hnp_enable && fsm->a_bus_suspend) - otg_set_state(fsm, OTG_STATE_B_WAIT_ACON); - break; - case OTG_STATE_B_WAIT_ACON: - if (fsm->a_conn) - otg_set_state(fsm, OTG_STATE_B_HOST); - else if (!fsm->id || !fsm->b_sess_vld) - otg_set_state(fsm, OTG_STATE_B_IDLE); - else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) { - fsm->b_ase0_brst_tmout = 0; - otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); - } - break; - case OTG_STATE_B_HOST: - if (!fsm->id || !fsm->b_sess_vld) - otg_set_state(fsm, OTG_STATE_B_IDLE); - else if (!fsm->b_bus_req || !fsm->a_conn) - otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); - break; - case OTG_STATE_A_IDLE: - if (fsm->id) - otg_set_state(fsm, OTG_STATE_B_IDLE); - else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det)) - otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); - break; - case OTG_STATE_A_WAIT_VRISE: - if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld || - fsm->a_wait_vrise_tmout) { - otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); - } - break; - case OTG_STATE_A_WAIT_BCON: - if (!fsm->a_vbus_vld) - otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); - else if (fsm->b_conn) - otg_set_state(fsm, OTG_STATE_A_HOST); - else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout) - otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); - break; - case OTG_STATE_A_HOST: - if ((!fsm->a_bus_req || fsm->a_suspend_req) && - fsm->transceiver->host->b_hnp_enable) - otg_set_state(fsm, OTG_STATE_A_SUSPEND); - else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) - otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); - else if (!fsm->a_vbus_vld) - otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); - break; - case OTG_STATE_A_SUSPEND: - if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable) - otg_set_state(fsm, OTG_STATE_A_PERIPHERAL); - else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable) - otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); - else if (fsm->a_bus_req || fsm->b_bus_resume) - otg_set_state(fsm, OTG_STATE_A_HOST); - else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout) - otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); - else if (!fsm->a_vbus_vld) - otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); - break; - case OTG_STATE_A_PERIPHERAL: - if (fsm->id || fsm->a_bus_drop) - otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); - else if (fsm->b_bus_suspend) - otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); - else if (!fsm->a_vbus_vld) - otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); - break; - case OTG_STATE_A_WAIT_VFALL: - if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld && - !fsm->b_conn)) - otg_set_state(fsm, OTG_STATE_A_IDLE); - break; - case OTG_STATE_A_VBUS_ERR: - if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err) - otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); - break; - default: - break; - } - spin_unlock_irqrestore(&fsm->lock, flags); - - VDBG("quit statemachine, changed = %d\n", state_changed); - return state_changed; -} diff --git a/trunk/drivers/usb/otg/otg_fsm.h b/trunk/drivers/usb/otg/otg_fsm.h deleted file mode 100644 index 0cecf1d593a0..000000000000 --- a/trunk/drivers/usb/otg/otg_fsm.h +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#undef DEBUG -#undef VERBOSE - -#ifdef DEBUG -#define DBG(fmt, args...) printk(KERN_DEBUG "[%s] " fmt , \ - __func__, ## args) -#else -#define DBG(fmt, args...) do {} while (0) -#endif - -#ifdef VERBOSE -#define VDBG DBG -#else -#define VDBG(stuff...) do {} while (0) -#endif - -#ifdef VERBOSE -#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) -#else -#define MPC_LOC do {} while (0) -#endif - -#define PROTO_UNDEF (0) -#define PROTO_HOST (1) -#define PROTO_GADGET (2) - -/* OTG state machine according to the OTG spec */ -struct otg_fsm { - /* Input */ - int a_bus_resume; - int a_bus_suspend; - int a_conn; - int a_sess_vld; - int a_srp_det; - int a_vbus_vld; - int b_bus_resume; - int b_bus_suspend; - int b_conn; - int b_se0_srp; - int b_sess_end; - int b_sess_vld; - int id; - - /* Internal variables */ - int a_set_b_hnp_en; - int b_srp_done; - int b_hnp_enable; - - /* Timeout indicator for timers */ - int a_wait_vrise_tmout; - int a_wait_bcon_tmout; - int a_aidl_bdis_tmout; - int b_ase0_brst_tmout; - - /* Informative variables */ - int a_bus_drop; - int a_bus_req; - int a_clr_err; - int a_suspend_req; - int b_bus_req; - - /* Output */ - int drv_vbus; - int loc_conn; - int loc_sof; - - struct otg_fsm_ops *ops; - struct otg_transceiver *transceiver; - - /* Current usb protocol used: 0:undefine; 1:host; 2:client */ - int protocol; - spinlock_t lock; -}; - -struct otg_fsm_ops { - void (*chrg_vbus)(int on); - void (*drv_vbus)(int on); - void (*loc_conn)(int on); - void (*loc_sof)(int on); - void (*start_pulse)(void); - void (*add_timer)(void *timer); - void (*del_timer)(void *timer); - int (*start_host)(struct otg_fsm *fsm, int on); - int (*start_gadget)(struct otg_fsm *fsm, int on); -}; - - -static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on) -{ - fsm->ops->chrg_vbus(on); -} - -static inline void otg_drv_vbus(struct otg_fsm *fsm, int on) -{ - if (fsm->drv_vbus != on) { - fsm->drv_vbus = on; - fsm->ops->drv_vbus(on); - } -} - -static inline void otg_loc_conn(struct otg_fsm *fsm, int on) -{ - if (fsm->loc_conn != on) { - fsm->loc_conn = on; - fsm->ops->loc_conn(on); - } -} - -static inline void otg_loc_sof(struct otg_fsm *fsm, int on) -{ - if (fsm->loc_sof != on) { - fsm->loc_sof = on; - fsm->ops->loc_sof(on); - } -} - -static inline void otg_start_pulse(struct otg_fsm *fsm) -{ - fsm->ops->start_pulse(); -} - -static inline void otg_add_timer(struct otg_fsm *fsm, void *timer) -{ - fsm->ops->add_timer(timer); -} - -static inline void otg_del_timer(struct otg_fsm *fsm, void *timer) -{ - fsm->ops->del_timer(timer); -} - -int otg_statemachine(struct otg_fsm *fsm); - -/* Defined by device specific driver, for different timer implementation */ -extern struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, - *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr, - *a_wait_enum_tmr; diff --git a/trunk/include/linux/fsl_devices.h b/trunk/include/linux/fsl_devices.h index fffdf00f87b9..4eb56ed75fbc 100644 --- a/trunk/include/linux/fsl_devices.h +++ b/trunk/include/linux/fsl_devices.h @@ -72,7 +72,6 @@ struct fsl_usb2_platform_data { void (*exit)(struct platform_device *); void __iomem *regs; /* ioremap'd register base */ struct clk *clk; - unsigned power_budget; /* hcd->power_budget */ unsigned big_endian_mmio:1; unsigned big_endian_desc:1; unsigned es:1; /* need USBMODE:ES */ @@ -80,21 +79,6 @@ struct fsl_usb2_platform_data { unsigned have_sysif_regs:1; unsigned invert_drvvbus:1; unsigned invert_pwr_fault:1; - - unsigned suspended:1; - unsigned already_suspended:1; - - /* register save area for suspend/resume */ - u32 pm_command; - u32 pm_status; - u32 pm_intr_enable; - u32 pm_frame_index; - u32 pm_segment; - u32 pm_frame_list; - u32 pm_async_next; - u32 pm_configured_flag; - u32 pm_portsc; - u32 pm_usbgenctrl; }; /* Flags in fsl_usb2_mph_platform_data */ diff --git a/trunk/include/linux/usb/otg.h b/trunk/include/linux/usb/otg.h index bc84858b3a4d..6e40718f5abe 100644 --- a/trunk/include/linux/usb/otg.h +++ b/trunk/include/linux/usb/otg.h @@ -246,6 +246,5 @@ otg_unregister_notifier(struct otg_transceiver *otg, struct notifier_block *nb) /* for OTG controller drivers (and maybe other stuff) */ extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); -extern const char *otg_state_string(enum usb_otg_state state); #endif /* __LINUX_USB_OTG_H */