/** * hw_device_state: enables/disables interrupts (execute without interruption) * @dma: 0 => disable, !0 => enable and set dma engine * * This function returns an error code */ static int hw_device_state(struct ci_hdrc *ci, u32 dma) { if (dma) { hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); /* interrupt, error, port change, reset, sleep/suspend */ hw_write(ci, OP_USBINTR, ~0, USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); } else { hw_write(ci, OP_USBINTR, ~0, 0); } return 0; }
/** * hw_test_and_clear_intr_active: test & clear active interrupts (execute * without interruption) * * This function returns active interrutps */ static u32 hw_test_and_clear_intr_active(struct ci_hdrc *ci) { u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); hw_write(ci, OP_USBSTS, ~0, reg); return reg; }
void writeUart(char *s) { char* ch = s; while (*ch != NULL) { hw_write(UART, *ch); ch++; } }
/** * hw_ep_enable: enables endpoint (execute without interruption) * @num: endpoint number * @dir: endpoint direction * @type: endpoint type * * This function returns an error code */ static int hw_ep_enable(struct ci_hdrc *ci, int num, int dir, int type) { u32 mask, data; if (dir) { mask = ENDPTCTRL_TXT; /* type */ data = type << __ffs(mask); mask |= ENDPTCTRL_TXS; /* unstall */ mask |= ENDPTCTRL_TXR; /* reset data toggle */ data |= ENDPTCTRL_TXR; mask |= ENDPTCTRL_TXE; /* enable */ data |= ENDPTCTRL_TXE; } else { mask = ENDPTCTRL_RXT; /* type */ data = type << __ffs(mask); mask |= ENDPTCTRL_RXS; /* unstall */ mask |= ENDPTCTRL_RXR; /* reset data toggle */ data |= ENDPTCTRL_RXR; mask |= ENDPTCTRL_RXE; /* enable */ data |= ENDPTCTRL_RXE; } hw_write(ci, OP_ENDPTCTRL + num, mask, data); return 0; }
/** * hw_ep_disable: disables endpoint (execute without interruption) * @num: endpoint number * @dir: endpoint direction * * This function returns an error code */ static int hw_ep_disable(struct ci_hdrc *ci, int num, int dir) { hw_ep_flush(ci, num, dir); hw_write(ci, OP_ENDPTCTRL + num, dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); return 0; }
static int host_start(struct ci_hdrc *ci) { struct usb_hcd *hcd; struct ehci_hcd *ehci; int ret; if (usb_disabled()) return -ENODEV; hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); if (!hcd) return -ENOMEM; dev_set_drvdata(ci->dev, ci); hcd->rsrc_start = ci->hw_bank.phys; hcd->rsrc_len = ci->hw_bank.size; hcd->regs = ci->hw_bank.abs; hcd->has_tt = 1; hcd->power_budget = ci->platdata->power_budget; hcd->phy = ci->transceiver; ehci = hcd_to_ehci(hcd); ehci->caps = ci->hw_bank.cap; ehci->has_hostpc = ci->hw_bank.lpm; ehci->has_tdi_phy_lpm = ci->hw_bank.lpm; ehci->imx28_write_fix = ci->imx28_write_fix; if (ci->platdata->reg_vbus) { ret = regulator_enable(ci->platdata->reg_vbus); if (ret) { dev_err(ci->dev, "Failed to enable vbus regulator, ret=%d\n", ret); goto put_hcd; } } ret = usb_add_hcd(hcd, 0, 0); if (ret) goto disable_reg; else ci->hcd = hcd; if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); return ret; disable_reg: if (ci->platdata->reg_vbus) regulator_disable(ci->platdata->reg_vbus); put_hcd: usb_put_hcd(hcd); return ret; }
/** * 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; }
/** * 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_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; }
/** * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute * without interruption) * @num: endpoint number * @dir: endpoint direction * @value: true => stall, false => unstall * * This function returns an error code */ static int hw_ep_set_halt(struct ci_hdrc *ci, int num, int dir, int value) { if (value != 0 && value != 1) return -EINVAL; do { enum ci_hw_regs reg = OP_ENDPTCTRL + num; u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; /* data toggle - reserved for EP0 but it's in ESS */ hw_write(ci, reg, mask_xs|mask_xr, value ? mask_xs : mask_xr); } while (value != hw_ep_get_halt(ci, num, dir)); return 0; }
static int host_start(struct ci13xxx *ci) { struct usb_hcd *hcd; struct ehci_hcd *ehci; int ret; if (usb_disabled()) return -ENODEV; hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); if (!hcd) return -ENOMEM; dev_set_drvdata(ci->dev, ci); hcd->rsrc_start = ci->hw_bank.phys; hcd->rsrc_len = ci->hw_bank.size; hcd->regs = ci->hw_bank.abs; hcd->has_tt = 1; hcd->power_budget = ci->platdata->power_budget; hcd->phy = ci->transceiver; ehci = hcd_to_ehci(hcd); ehci->caps = ci->hw_bank.cap; ehci->has_hostpc = ci->hw_bank.lpm; ret = usb_add_hcd(hcd, 0, 0); if (ret) usb_put_hcd(hcd); else ci->hcd = hcd; if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); return ret; }
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; }
static int host_start(struct ci_hdrc *ci) { struct usb_hcd *hcd; struct ehci_hcd *ehci; struct ehci_ci_priv *priv; int ret; if (usb_disabled()) return -ENODEV; hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); if (!hcd) return -ENOMEM; dev_set_drvdata(ci->dev, ci); hcd->rsrc_start = ci->hw_bank.phys; hcd->rsrc_len = ci->hw_bank.size; hcd->regs = ci->hw_bank.abs; hcd->has_tt = 1; hcd->power_budget = ci->platdata->power_budget; hcd->tpl_support = ci->platdata->tpl_support; if (ci->phy) hcd->phy = ci->phy; else hcd->usb_phy = ci->usb_phy; ehci = hcd_to_ehci(hcd); ehci->caps = ci->hw_bank.cap; ehci->has_hostpc = ci->hw_bank.lpm; ehci->has_tdi_phy_lpm = ci->hw_bank.lpm; ehci->imx28_write_fix = ci->imx28_write_fix; priv = (struct ehci_ci_priv *)ehci->priv; priv->reg_vbus = NULL; if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) { if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) { ret = regulator_enable(ci->platdata->reg_vbus); if (ret) { dev_err(ci->dev, "Failed to enable vbus regulator, ret=%d\n", ret); goto put_hcd; } } else { priv->reg_vbus = ci->platdata->reg_vbus; } } ret = usb_add_hcd(hcd, 0, 0); if (ret) { goto disable_reg; } else { struct usb_otg *otg = &ci->otg; ci->hcd = hcd; if (ci_otg_is_fsm_mode(ci)) { otg->host = &hcd->self; hcd->self.otg_port = 1; } } if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC); return ret; disable_reg: if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) && (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON)) regulator_disable(ci->platdata->reg_vbus); put_hcd: usb_put_hcd(hcd); return ret; }
/** * hw_write_otgsc updates target bits of OTGSC register. * @mask: bitfield mask * @data: to be written */ void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data) { hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data); }
static int host_start(struct ci_hdrc *ci) { struct usb_hcd *hcd; struct ehci_hcd *ehci; struct ehci_ci_priv *priv; int ret; if (usb_disabled()) return -ENODEV; hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); if (!hcd) return -ENOMEM; dev_set_drvdata(ci->dev, ci); hcd->rsrc_start = ci->hw_bank.phys; hcd->rsrc_len = ci->hw_bank.size; hcd->regs = ci->hw_bank.abs; hcd->has_tt = 1; hcd->power_budget = ci->platdata->power_budget; hcd->tpl_support = ci->platdata->tpl_support; if (ci->phy) hcd->phy = ci->phy; else hcd->usb_phy = ci->usb_phy; ehci = hcd_to_ehci(hcd); ehci->caps = ci->hw_bank.cap; ehci->has_hostpc = ci->hw_bank.lpm; ehci->has_tdi_phy_lpm = ci->hw_bank.lpm; ehci->imx28_write_fix = ci->imx28_write_fix; priv = (struct ehci_ci_priv *)ehci->priv; priv->reg_vbus = NULL; if (ci->platdata->reg_vbus) priv->reg_vbus = ci->platdata->reg_vbus; ret = usb_add_hcd(hcd, 0, 0); if (ret) { goto put_hcd; } else { struct usb_otg *otg = &ci->otg; ci->hcd = hcd; if (ci_otg_is_fsm_mode(ci)) { otg->host = &hcd->self; hcd->self.otg_port = 1; } } if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); return ret; put_hcd: usb_put_hcd(hcd); return ret; }
/** * hw_usb_set_address: configures USB address (execute without interruption) * @value: new USB address * * This function explicitly sets the address, without the "USBADRA" (advance) * feature, which is not supported by older versions of the controller. */ static void hw_usb_set_address(struct ci_hdrc *ci, u8 value) { hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, value << __ffs(DEVICEADDR_USBADR)); }
/** * hw_usb_set_address: configures USB address (execute without interruption) * @value: new USB address * * This function explicitly sets the address, without the "USBADRA" (advance) * feature, which is not supported by older versions of the controller. */ static void hw_usb_set_address(struct ci13xxx *ci, u8 value) { hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, value << ffs_nr(DEVICEADDR_USBADR)); }
/** * _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; }
void __attribute__ ((interrupt)) __cs3_isr_external_1(void) { ffFull = true; hw_write(FFCLRIRQ, 0); //printf (" Called isr 1\n"); }