/** * hw_ep_flush: flush endpoint fifo (execute without interruption) * @num: endpoint number * @dir: endpoint direction * * This function returns an error code */ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) { int n = hw_ep_bit(num, dir); do { /* flush any pending transfer */ hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n)); while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) cpu_relax(); } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); return 0; }
int ci_hdrc_host_init(struct ci_hdrc *ci) { struct ci_role_driver *rdrv; if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC)) return -ENXIO; rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); if (!rdrv) return -ENOMEM; rdrv->start = host_start; rdrv->stop = host_stop; rdrv->irq = host_irq; rdrv->suspend = ci_hdrc_host_suspend; rdrv->resume = ci_hdrc_host_resume; rdrv->name = "host"; ci->roles[CI_ROLE_HOST] = rdrv; ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides); orig_bus_suspend = ci_ehci_hc_driver.bus_suspend; orig_bus_resume = ci_ehci_hc_driver.bus_resume; orig_hub_control = ci_ehci_hc_driver.hub_control; ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend; if (ci->platdata->flags & CI_HDRC_IMX_EHCI_QUIRK) { ci_ehci_hc_driver.bus_resume = ci_imx_ehci_bus_resume; ci_ehci_hc_driver.hub_control = ci_imx_ehci_hub_control; } return 0; }
/** * hw_ep_prime: primes endpoint (execute without interruption) * @num: endpoint number * @dir: endpoint direction * @is_ctrl: true if control endpoint * * This function returns an error code */ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) { int n = hw_ep_bit(num, dir); if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n)); while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) cpu_relax(); if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; /* status shoult be tested according with manual but it doesn't work */ return 0; }
int main () { int i; int c; /* Initialize UART */ hw_write(UARTIBRD, 0x01); hw_write(UARTCR, 0x0301); hw_write(IOSTATUS, 1); //printf ("Starting main\n"); ffFull = false; writeUart("Testing\n"); i = GetNextPrimes(10000000, 100); hw_write(IOSTATUS, 2); printf ("Prime is %d\n", i); /*asm volatile ("cpsie i");*/ NVIC_EnableIRQ(1); while (true) { while (!ffFull) { //printf ("Called wfi\n"); hw_write(IOSTATUS, 0); asm volatile("wfi"); hw_write(IOSTATUS, 1); } c = hw_read(FFCOUNT); while (c != 0) { i = hw_read(FF); c = hw_read(FFCOUNT); //printf ("Read i = %d\n", i); } //printf ("Finished read loop\n"); ffFull = false; } //printf ("Returning from main\n"); return 0; }
int ci_hdrc_host_init(struct ci_hdrc *ci) { struct ci_role_driver *rdrv; if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC)) return -ENXIO; rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); if (!rdrv) return -ENOMEM; rdrv->start = host_start; rdrv->stop = host_stop; rdrv->irq = host_irq; rdrv->name = "host"; ci->roles[CI_ROLE_HOST] = rdrv; return 0; }
/** * hw_usb_reset: restart device after a bus reset (execute without * interruption) * * This function returns an error code */ static int hw_usb_reset(struct ci_hdrc *ci) { hw_usb_set_address(ci, 0); /* ESS flushes only at end?!? */ hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); /* clear setup token semaphores */ hw_write(ci, OP_ENDPTSETUPSTAT, 0, 0); /* clear complete status */ hw_write(ci, OP_ENDPTCOMPLETE, 0, 0); /* wait until all bits cleared */ while (hw_read(ci, OP_ENDPTPRIME, ~0)) udelay(10); /* not RTOS friendly */ /* reset all endpoints ? */ /* reset internal status and wait for further instructions no need to verify the port reset status (ESS does it) */ return 0; }
/** * hw_read_otgsc returns otgsc register bits value. * @mask: bitfield mask */ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) { return hw_read(ci, OP_OTGSC, mask); }
/** * hw_is_port_high_speed: test if port is high speed * * This function returns true if high speed port */ static int hw_port_is_high_speed(struct ci_hdrc *ci) { return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : hw_read(ci, OP_PORTSC, PORTSC_HSP); }
/** * hw_ep_get_halt: return endpoint halt status * @num: endpoint number * @dir: endpoint direction * * This function returns 1 if endpoint halted */ static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir) { u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0; }
/** * hw_read_intr_status: returns interrupt status register * * This function returns register data */ static u32 hw_read_intr_status(struct ci_hdrc *ci) { return hw_read(ci, OP_USBSTS, ~0); }
/** * hw_read_intr_enable: returns interrupt enable register * * This function returns register data */ static u32 hw_read_intr_enable(struct ci_hdrc *ci) { return hw_read(ci, OP_USBINTR, ~0); }
/** * _hardware_queue: configures a request at hardware level * @gadget: gadget * @mEp: endpoint * * This function returns an error code */ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) { struct ci13xxx *ci = mEp->ci; unsigned i; int ret = 0; unsigned length = mReq->req.length; /* don't queue twice */ if (mReq->req.status == -EALREADY) return -EALREADY; mReq->req.status = -EALREADY; if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) { mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC, &mReq->zdma); if (mReq->zptr == NULL) return -ENOMEM; memset(mReq->zptr, 0, sizeof(*mReq->zptr)); mReq->zptr->next = TD_TERMINATE; mReq->zptr->token = TD_STATUS_ACTIVE; if (!mReq->req.no_interrupt) mReq->zptr->token |= TD_IOC; } ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir); if (ret) return ret; /* * TD configuration * TODO - handle requests which spawns into several TDs */ memset(mReq->ptr, 0, sizeof(*mReq->ptr)); mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES); mReq->ptr->token &= TD_TOTAL_BYTES; mReq->ptr->token |= TD_STATUS_ACTIVE; if (mReq->zptr) { mReq->ptr->next = mReq->zdma; } else { mReq->ptr->next = TD_TERMINATE; if (!mReq->req.no_interrupt) mReq->ptr->token |= TD_IOC; } mReq->ptr->page[0] = mReq->req.dma; for (i = 1; i < 5; i++) mReq->ptr->page[i] = (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK; if (!list_empty(&mEp->qh.queue)) { struct ci13xxx_req *mReqPrev; int n = hw_ep_bit(mEp->num, mEp->dir); int tmp_stat; mReqPrev = list_entry(mEp->qh.queue.prev, struct ci13xxx_req, queue); if (mReqPrev->zptr) mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK; else mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK; wmb(); if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) goto done; do { hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n)); } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW)); hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0); if (tmp_stat) goto done; } /* QH configuration */ mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */ mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */ mEp->qh.ptr->cap |= QH_ZLT; wmb(); /* synchronize before ep prime */ ret = hw_ep_prime(ci, mEp->num, mEp->dir, mEp->type == USB_ENDPOINT_XFER_CONTROL); done: return ret; }