static irqreturn_t pic32_interrupt(int irq, void *hci) { struct musb *musb = hci; irqreturn_t ret = IRQ_NONE; u32 epintr, usbintr; /* ack usb core interrupts */ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); if (musb->int_usb) musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); /* ack endpoint interrupts */ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX) & PIC32_RX_EP_MASK; if (musb->int_rx) musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX) & PIC32_TX_EP_MASK; if (musb->int_tx) musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); /* drop spurious RX and TX if device is disconnected */ if (musb->int_usb & MUSB_INTR_DISCONNECT) { musb->int_tx = 0; musb->int_rx = 0; } if (musb->int_tx || musb->int_rx || musb->int_usb) ret = musb_interrupt(musb); return ret; }
static int ux500_dma_channel_abort(struct dma_channel *channel) { struct ux500_dma_channel *ux500_channel = channel->private_data; struct ux500_dma_controller *controller = ux500_channel->controller; struct musb *musb = controller->private_data; void __iomem *epio = musb->endpoints[ux500_channel->hw_ep->epnum].regs; u16 csr; dev_dbg(musb->controller, "channel=%d, is_tx=%d\n", ux500_channel->ch_num, ux500_channel->is_tx); if (channel->status == MUSB_DMA_STATUS_BUSY) { if (ux500_channel->is_tx) { csr = musb_readw(epio, MUSB_TXCSR); csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE); musb_writew(epio, MUSB_TXCSR, csr); } else { csr = musb_readw(epio, MUSB_RXCSR); csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAMODE); musb_writew(epio, MUSB_RXCSR, csr); } ux500_channel->dma_chan->device-> device_control(ux500_channel->dma_chan, DMA_TERMINATE_ALL, 0); channel->status = MUSB_DMA_STATUS_FREE; } return 0; }
void musb_h_in_data(unsigned char *buf, u16 len){//will receive all of the data in this transfer. unsigned short csr0; u16 received = 0; bool bshort = false; DBG(0,"musb_h_in_data++\n"); while((received<len)&&(!bshort)){ csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); csr0 |= MUSB_CSR0_H_REQPKT; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0,csr0);//send in token. if(musb_polling_ep0_interrupt()) return; csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); DBG(0,"csr0 = 0x%x!\n",csr0); if(csr0 & MUSB_CSR0_RXPKTRDY){ //get the data from ep fifo u8 count = musb_readb(mtk_musb->mregs,MUSB_OTG_COUNT0); if(count < 64) bshort = true; musb_otg_read_fifo(count,buf+received); received += count; csr0 &= ~MUSB_CSR0_RXPKTRDY; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0,csr0); //clear RXPKTRDY } else DBG(0,"error, not receive the rxpktrdy interrupt!\n"); DBG(0,"musb_h_in_data--\n"); } }
void musb_h_in_status(void){ unsigned short csr0; DBG(0,"musb_h_in_status++\n"); csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); csr0 |= MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0,csr0); if(musb_polling_ep0_interrupt()) return; csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); DBG(0,"csr0 = 0x%x!\n",csr0); if(csr0 & MUSB_CSR0_RXPKTRDY){ csr0 &= ~MUSB_CSR0_RXPKTRDY; if(csr0 & MUSB_CSR0_H_STATUSPKT){//whether this bit will be cleared auto, need to clear by sw?? csr0 &= ~MUSB_CSR0_H_STATUSPKT; } musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0,csr0); } else if(csr0 & MUSB_CSR0_H_RXSTALL){ DBG(0,"stall!\n"); if(set_hnp){ DBG(0,"will pop up:DEV_NOT_RESPONSE!\n"); g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE; set_hnp = false; msleep(1000); } } DBG(0,"musb_h_in_status--\n"); return; }
int musb_otg_env_init(void){ u8 power; //u8 intrusb; //step1: mask the PMU/PMIC EINT mtk_musb->usb_if = true; mtk_musb->is_host = true;//workaround for PMIC charger detection //mt65xx_eint_mask(EINT_CHR_DET_NUM); upmu_interrupt_chrdet_int_en(0); #ifndef MTK_FAN5405_SUPPORT #ifndef MTK_NCP1851_SUPPORT #ifndef MTK_BQ24196_SUPPORT #ifndef MTK_BQ24158_SUPPORT //set the drvvbus mode as drvvbus(mode 6) #if !(defined(CONFIG_MT6585_FPGA) || defined(CONFIG_MT6577_FPGA) || defined(CONFIG_MT6589_FPGA) || defined(CONFIG_MT6582_FPGA)) mt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN,6); #endif #endif #endif #endif #endif //step5: make sure to power on the USB module if(mtk_musb->power) mtk_musb->power = FALSE; musb_platform_enable(mtk_musb); //step6: clear session bit musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,0); //step7: disable and enable usb interrupt usb_l1intm_store = musb_readl(mtk_musb->mregs,USB_L1INTM); usb_intrrxe_store = musb_readw(mtk_musb->mregs,MUSB_INTRRXE); usb_intrtxe_store = musb_readw(mtk_musb->mregs,MUSB_INTRTXE); usb_intrusbe_store = musb_readb(mtk_musb->mregs,MUSB_INTRUSBE); musb_writel(mtk_musb->mregs,USB_L1INTM,0); musb_writew(mtk_musb->mregs,MUSB_INTRRXE,0); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,0); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0); musb_writew(mtk_musb->mregs,MUSB_INTRRX,0xffff); musb_writew(mtk_musb->mregs,MUSB_INTRTX,0xffff); musb_writeb(mtk_musb->mregs,MUSB_INTRUSB,0xff); free_irq (mtk_musb->nIrq, mtk_musb); musb_writel(mtk_musb->mregs,USB_L1INTM,0x105); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,1); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0xf7); //setp8: set the index to 0 for ep0, maybe no need. Designers said it is better not to use the index register. musb_writeb(mtk_musb->mregs, MUSB_INDEX, 0); //setp9: init message g_otg_message.msg = 0; spin_lock_init(&g_otg_message.lock); init_completion(&stop_event); #ifdef DX_DBG power = musb_readb(mtk_musb->mregs,MUSB_POWER); DBG(0,"start the USB-IF test in EM,power=0x%x!\n",power); #endif return 0; }
static int cppi41_dma_channel_abort(struct dma_channel *channel) { struct cppi41_dma_channel *cppi41_channel = channel->private_data; struct cppi41_dma_controller *controller = cppi41_channel->controller; struct musb *musb = controller->musb; void __iomem *epio = cppi41_channel->hw_ep->regs; int tdbit; int ret; unsigned is_tx; u16 csr; is_tx = cppi41_channel->is_tx; dev_dbg(musb->controller, "abort channel=%d, is_tx=%d\n", cppi41_channel->port_num, is_tx); if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE) return 0; if (is_tx) { csr = musb_readw(epio, MUSB_TXCSR); csr &= ~MUSB_TXCSR_DMAENAB; musb_writew(epio, MUSB_TXCSR, csr); } else { csr = musb_readw(epio, MUSB_RXCSR); csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB); musb_writew(epio, MUSB_RXCSR, csr); csr = musb_readw(epio, MUSB_RXCSR); if (csr & MUSB_RXCSR_RXPKTRDY) { csr |= MUSB_RXCSR_FLUSHFIFO; musb_writew(epio, MUSB_RXCSR, csr); musb_writew(epio, MUSB_RXCSR, csr); } } tdbit = 1 << cppi41_channel->port_num; if (is_tx) tdbit <<= 16; do { musb_writel(musb->ctrl_base, USB_TDOWN, tdbit); ret = dmaengine_terminate_all(cppi41_channel->dc); } while (ret == -EAGAIN); musb_writel(musb->ctrl_base, USB_TDOWN, tdbit); if (is_tx) { csr = musb_readw(epio, MUSB_TXCSR); if (csr & MUSB_TXCSR_TXPKTRDY) { csr |= MUSB_TXCSR_FLUSHFIFO; musb_writew(epio, MUSB_TXCSR, csr); } } cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE; return 0; }
void musb_d_enumerated(void){ unsigned char devctl; unsigned short csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); DBG(0,"csr0=0x%x\n",csr0); if(csr0 & MUSB_CSR0_P_SETUPEND){ DBG(0,"SETUPEND\n"); csr0 |= MUSB_CSR0_P_SVDSETUPEND; musb_writeb(mtk_musb->mregs, MUSB_OTG_CSR0,csr0); csr0 &= ~MUSB_CSR0_P_SVDSETUPEND; } if(csr0&MUSB_CSR0_RXPKTRDY){ u8 count0; count0 = musb_readb(mtk_musb->mregs,MUSB_OTG_COUNT0); if(count0==8){//enumeration struct usb_ctrlrequest setup_packet; musb_d_setup(&setup_packet, count0);//get the setup packet if(setup_packet.bRequest == USB_REQ_SET_ADDRESS){ device_enumed = false; csr0 |= MUSB_CSR0_P_SVDRXPKTRDY|MUSB_CSR0_P_DATAEND; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0, csr0);//clear the RXPKTRDY if(musb_polling_ep0_interrupt()) { DBG(0,"B-UUT:when set address, do not detect ep0 interrupt\n"); return; } musb_writeb (mtk_musb->mregs,MUSB_FADDR,(u8)setup_packet.wValue); } else if(setup_packet.bRequest == USB_REQ_GET_DESCRIPTOR){ csr0 |= MUSB_CSR0_P_SVDRXPKTRDY; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0, csr0);//clear the RXPKTRDY musb_d_out_data(&setup_packet);//device --> host } else if(setup_packet.bRequest == USB_REQ_SET_CONFIGURATION){ csr0 |= MUSB_CSR0_P_SVDRXPKTRDY|MUSB_CSR0_P_DATAEND; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0, csr0);//clear the RXPKTRDY if(musb_polling_ep0_interrupt()) { return; } device_enumed = true; //will set host_req for B-device devctl = musb_readb(mtk_musb->mregs,MUSB_DEVCTL); if(devctl&MUSB_DEVCTL_BDEVICE){ devctl |= MUSB_DEVCTL_HR; musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,devctl); } } else if(setup_packet.bRequest == USB_REQ_SET_FEATURE){ csr0 |= MUSB_CSR0_P_SVDRXPKTRDY|MUSB_CSR0_P_DATAEND; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0, csr0);//clear the RXPKTRDY if(musb_polling_ep0_interrupt()) { return; } } } } }
void musb_read_clear_generic_interrupt(struct musb *musb) { musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); mb(); musb_writew(musb->mregs,MUSB_INTRRX,musb->int_rx); musb_writew(musb->mregs,MUSB_INTRTX,musb->int_tx); musb_writeb(musb->mregs,MUSB_INTRUSB,musb->int_usb); }
int musb_otg_env_init(void){ u8 power; //u8 intrusb; //step1: mask the PMU/PMIC EINT mtk_musb->usb_if = true; mtk_musb->is_host = true;//workaround for PMIC charger detection //mt65xx_eint_mask(EINT_CHR_DET_NUM); pmic_chrdet_int_en(0); mt_usb_init_drvvbus(); //step5: make sure to power on the USB module if(mtk_musb->power) mtk_musb->power = FALSE; musb_platform_enable(mtk_musb); //step6: clear session bit musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,0); //step7: disable and enable usb interrupt usb_l1intm_store = musb_readl(mtk_musb->mregs,USB_L1INTM); usb_intrrxe_store = musb_readw(mtk_musb->mregs,MUSB_INTRRXE); usb_intrtxe_store = musb_readw(mtk_musb->mregs,MUSB_INTRTXE); usb_intrusbe_store = musb_readb(mtk_musb->mregs,MUSB_INTRUSBE); musb_writel(mtk_musb->mregs,USB_L1INTM,0); musb_writew(mtk_musb->mregs,MUSB_INTRRXE,0); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,0); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0); musb_writew(mtk_musb->mregs,MUSB_INTRRX,0xffff); musb_writew(mtk_musb->mregs,MUSB_INTRTX,0xffff); musb_writeb(mtk_musb->mregs,MUSB_INTRUSB,0xff); free_irq (mtk_musb->nIrq, mtk_musb); musb_writel(mtk_musb->mregs,USB_L1INTM,0x105); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,1); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0xf7); //setp8: set the index to 0 for ep0, maybe no need. Designers said it is better not to use the index register. musb_writeb(mtk_musb->mregs, MUSB_INDEX, 0); //setp9: init message g_otg_message.msg = 0; spin_lock_init(&g_otg_message.lock); init_completion(&stop_event); #ifdef DX_DBG power = musb_readb(mtk_musb->mregs,MUSB_POWER); DBG(0,"start the USB-IF test in EM,power=0x%x!\n",power); #endif return 0; }
static int dma_channel_abort(struct dma_channel *channel) { struct musb_dma_channel *musb_channel = channel->private_data; void __iomem *mbase = musb_channel->controller->base; u8 bchannel = musb_channel->idx; int offset; u16 csr; if (channel->status == MUSB_DMA_STATUS_BUSY) { if (musb_channel->transmit) { offset = MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR); /* * The programming guide says that we must clear * the DMAENAB bit before the DMAMODE bit... */ csr = musb_readw(mbase, offset); csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); musb_writew(mbase, offset, csr); csr &= ~MUSB_TXCSR_DMAMODE; musb_writew(mbase, offset, csr); } else { offset = MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR); csr = musb_readw(mbase, offset); csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAMODE); musb_writew(mbase, offset, csr); } musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), 0); musb_write_hsdma_addr(mbase, bchannel, 0); musb_write_hsdma_count(mbase, bchannel, 0); channel->status = MUSB_DMA_STATUS_FREE; if (musb_channel->transmit) musb_channel->controller->tx_active &= ~(1 << bchannel); else musb_channel->controller->rx_active &= ~(1 << bchannel); } return 0; }
/* * Load an endpoint's FIFO */ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) { void __iomem *fifo; if(mtk_musb->is_host) fifo = hw_ep->fifo; else fifo = mtk_musb->mregs + MUSB_FIFO_OFFSET(hw_ep->ep_in.current_epnum); prefetch((u8 *)src); DBG(4, "%cX ep%d fifo %p count %d buf %p\n", 'T', hw_ep->epnum, fifo, len, src); /* we can't assume unaligned reads work */ if (likely((0x01 & (unsigned long) src) == 0)) { u16 index = 0; /* best case is 32bit-aligned source address */ if ((0x02 & (unsigned long) src) == 0) { if (len >= 4) { writesl(fifo, src + index, len >> 2); index += len & ~0x03; } if (len & 0x02) { dumpTime(funcWritew, 0); musb_writew(fifo, 0, *(u16 *)&src[index]); index += 2; } } else {
static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel) { u16 csr; u8 toggle; if (cppi41_channel->is_tx) return; if (!is_host_active(cppi41_channel->controller->musb)) return; csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR); toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0; /* * AM335x Advisory 1.0.13: Due to internal synchronisation error the * data toggle may reset from DATA1 to DATA0 during receiving data from * more than one endpoint. */ if (!toggle && toggle == cppi41_channel->usb_toggle) { csr |= MUSB_RXCSR_H_DATATOGGLE | MUSB_RXCSR_H_WR_DATATOGGLE; musb_writew(cppi41_channel->hw_ep->regs, MUSB_RXCSR, csr); dev_dbg(cppi41_channel->controller->musb->controller, "Restoring DATA1 toggle.\n"); } cppi41_channel->usb_toggle = toggle; }
/* * Load an endpoint's FIFO */ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) { struct musb *musb = hw_ep->musb; void __iomem *fifo = hw_ep->fifo; if (unlikely(len == 0)) return; prefetch((u8 *)src); dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", 'T', hw_ep->epnum, fifo, len, src); /* we can't assume unaligned reads work */ if (likely((0x01 & (unsigned long) src) == 0)) { u16 index = 0; /* best case is 32bit-aligned source address */ if ((0x02 & (unsigned long) src) == 0) { if (len >= 4) { writesl(fifo, src + index, len >> 2); index += len & ~0x03; } if (len & 0x02) { musb_writew(fifo, 0, *(u16 *)&src[index]); index += 2; } } else {
void musb_d_reset(void){ unsigned short swrst; swrst = musb_readw(mtk_musb->mregs,0x74); swrst |= 0x2; musb_writew(mtk_musb->mregs,0x74,swrst); return; }
static void musb_sysdma_completion(int lch, u16 ch_status, void *data) { u32 addr; unsigned long flags; struct dma_channel *channel; struct musb_dma_channel *musb_channel = (struct musb_dma_channel *) data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; void __iomem *mbase = controller->base; channel = &musb_channel->channel; DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status); spin_lock_irqsave(&musb->lock, flags); if (musb_channel->transmit) addr = (u32) omap_get_dma_src_pos(musb_channel->sysdma_channel); else addr = (u32) omap_get_dma_dst_pos(musb_channel->sysdma_channel); if (musb_channel->len == 0) channel->actual_len = 0; else channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0 " : " => complete"); channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((musb_channel->transmit) && (channel->desired_mode == 0) && (channel->actual_len == musb_channel->max_packet_sz)) { u8 epnum = musb_channel->epnum; int offset = MUSB_EP_OFFSET(musb, epnum, MUSB_TXCSR); u16 txcsr; /* * The programming guide says that we * must clear DMAENAB before DMAMODE. */ musb_ep_select(musb, mbase, epnum); txcsr = musb_readw(mbase, offset); txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } musb_dma_completion(musb, musb_channel->epnum, musb_channel->transmit); spin_unlock_irqrestore(&musb->lock, flags); return; }
void musb_generic_disable(struct musb *musb) { void __iomem *mbase = musb->mregs; /* disable interrupts */ musb_writeb(mbase, MUSB_INTRUSBE, 0); musb_writew(mbase, MUSB_INTRTXE, 0); musb_writew(mbase, MUSB_INTRRXE, 0); /* off */ //musb_writeb(mbase, MUSB_DEVCTL, 0); /* flush pending interrupts */ musb_writew(musb->mregs,MUSB_INTRRX,0xFFFF); musb_writew(musb->mregs,MUSB_INTRTX,0xFFFF); musb_writeb(musb->mregs,MUSB_INTRUSB,0xEF); }
void musb_platform_reset(struct musb *musb) { u16 swrst = 0; void __iomem *mbase = musb->mregs; swrst = musb_readw(mbase,MUSB_SWRST); swrst |= (MUSB_SWRST_DISUSBRESET | MUSB_SWRST_SWRST); musb_writew(mbase, MUSB_SWRST,swrst); }
static int dma_channel_abort(struct dma_channel *channel) { struct musb_dma_channel *musb_channel = channel->private_data; void __iomem *mbase = musb_channel->controller->base; u8 bchannel = musb_channel->idx; u16 csr; if (channel->status == MUSB_DMA_STATUS_BUSY) { if (musb_channel->transmit) { csr = musb_readw(mbase, MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR)); csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE); musb_writew(mbase, MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), csr); } else { if (musb_channel->sysdma_channel != -1) omap_stop_dma(musb_channel->sysdma_channel); csr = musb_readw(mbase, MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR)); csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAMODE); musb_writew(mbase, MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR), csr); } musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), 0); musb_write_hsdma_addr(mbase, bchannel, 0); musb_write_hsdma_count(mbase, bchannel, 0); channel->status = MUSB_DMA_STATUS_FREE; } return 0; }
/* NOTE: DaVinci autoreq is ignored except for host side "RNDIS" mode RX; * so we won't ever use it (see "CPPI RX Woes" below). */ static inline int cppi_autoreq_update(struct cppi_channel *rx, void __iomem *tibase, int onepacket, unsigned n_bds) { u32 val; #ifdef RNDIS_RX_IS_USABLE u32 tmp; /* assert(is_host_active(musb)) */ /* start from "AutoReq never" */ tmp = musb_readl(tibase, DAVINCI_AUTOREQ_REG); val = tmp & ~((0x3) << (rx->index * 2)); /* HCD arranged reqpkt for packet #1. we arrange int * for all but the last one, maybe in two segments. */ if (!onepacket) { #if 0 /* use two segments, autoreq "all" then the last "never" */ val |= ((0x3) << (rx->index * 2)); n_bds--; #else /* one segment, autoreq "all-but-last" */ val |= ((0x1) << (rx->index * 2)); #endif } if (val != tmp) { int n = 100; /* make sure that autoreq is updated before continuing */ musb_writel(tibase, DAVINCI_AUTOREQ_REG, val); do { tmp = musb_readl(tibase, DAVINCI_AUTOREQ_REG); if (tmp == val) break; cpu_relax(); } while (n-- > 0); } #endif /* REQPKT is turned off after each segment */ if (n_bds && rx->channel.actual_len) { void __iomem *regs = rx->hw_ep->regs; val = musb_readw(regs, MUSB_RXCSR); if (!(val & MUSB_RXCSR_H_REQPKT)) { val |= MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_H_WZC_BITS; musb_writew(regs, MUSB_RXCSR, val); /* flush writebuffer */ val = musb_readw(regs, MUSB_RXCSR); } } return n_bds; }
int __init musb_platform_init(struct musb *musb) { struct otg_transceiver *xceiv; xceiv = kzalloc(sizeof(struct otg_transceiver), GFP_KERNEL); if (!xceiv) return -ENOMEM; xceiv->set_peripheral = sep0611_set_peripheral; otg_set_transceiver(xceiv); musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { return -ENODEV; } musb_platform_resume(musb); if (is_host_enabled(musb)) musb->xceiv->set_host = sep0611_set_host; musb->board_set_vbus = sep0611_set_vbus; if (is_peripheral_enabled(musb)) musb->xceiv->set_power = sep0611_set_power; musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); musb_writew(musb->mregs, RX_DPKTBUFDIS, 0xffff); /* disable RX double packet buffer */ musb_writew(musb->mregs, TX_DPKTBUFDIS, 0xffff); /* disable TX double packet buffer */ #ifdef SEP0611_ULPI_RST /*spdw_board has two usb ports,one is otg(port_index=0), the other is host(port_index=1),default is otg port*/ musb->port_index = 0; #endif #ifdef SEP0611_PHY_RST /*demo_board has two usb ports*/ musb->port_index = 0; #endif return 0; }
/* * Program the HDRC to start (enable interrupts, dma, etc.). */ static void musb_start(struct musb *musb) { void __iomem *regs = musb->mregs; u8 devctl = musb_readb(regs, MUSB_DEVCTL); dev_dbg(musb->controller, "<== devctl %02x\n", devctl); /* Set INT enable registers, enable interrupts */ musb->intrtxe = musb->epmask; musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); musb->intrrxe = musb->epmask & 0xfffe; musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); musb_writeb(regs, MUSB_INTRUSBE, 0xf7); musb_writeb(regs, MUSB_TESTMODE, 0); /* put into basic highspeed mode and start session */ musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE | MUSB_POWER_HSENAB /* ENSUSPEND wedges tusb */ /* | MUSB_POWER_ENSUSPEND */ ); musb->is_active = 0; devctl = musb_readb(regs, MUSB_DEVCTL); devctl &= ~MUSB_DEVCTL_SESSION; /* session started after: * (a) ID-grounded irq, host mode; * (b) vbus present/connect IRQ, peripheral mode; * (c) peripheral initiates, using SRP */ if (musb->port_mode != MUSB_PORT_MODE_HOST && (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { musb->is_active = 1; } else { devctl |= MUSB_DEVCTL_SESSION; } musb_platform_enable(musb); musb_writeb(regs, MUSB_DEVCTL, devctl); }
void musb_tx_zlp_qmu(struct musb *musb, u32 ep_num) { /* sent ZLP through PIO */ void __iomem *epio = musb->endpoints[ep_num].regs; void __iomem *mbase = musb->mregs; unsigned long timeout = jiffies + HZ; int is_timeout = 1; u16 csr; QMU_WARN("TX ZLP direct sent\n"); musb_ep_select(mbase, ep_num); /* disable dma for pio */ csr = musb_readw(epio, MUSB_TXCSR); csr &= ~MUSB_TXCSR_DMAENAB; musb_writew(epio, MUSB_TXCSR, csr); /* TXPKTRDY */ csr = musb_readw(epio, MUSB_TXCSR); csr |= MUSB_TXCSR_TXPKTRDY; musb_writew(epio, MUSB_TXCSR, csr); /* wait ZLP sent */ while (time_before_eq(jiffies, timeout)) { csr = musb_readw(epio, MUSB_TXCSR); if (!(csr & MUSB_TXCSR_TXPKTRDY)) { is_timeout = 0; break; } } /* re-enable dma for qmu */ csr = musb_readw(epio, MUSB_TXCSR); csr |= MUSB_TXCSR_DMAENAB; musb_writew(epio, MUSB_TXCSR, csr); if (is_timeout) { QMU_ERR("TX ZLP sent fail???\n"); } QMU_WARN("TX ZLP sent done\n"); }
static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci) { struct musb *musb = __hci; irqreturn_t retval = IRQ_NONE; /* read and flush interrupts */ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); if (musb->int_usb) musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); if (musb->int_tx) musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); if (musb->int_rx) musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); if (musb->int_usb || musb->int_tx || musb->int_rx) retval |= musb_interrupt(musb); return retval; }
void musb_h_setup(struct usb_ctrlrequest *setup){ unsigned short csr0; DBG(0,"musb_h_setup++\n"); musb_otg_write_fifo(sizeof(struct usb_ctrlrequest),(u8*)setup); csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); DBG(0,"musb_h_setup,csr0=0x%x\n",csr0); csr0 |= MUSB_CSR0_H_SETUPPKT|MUSB_CSR0_TXPKTRDY; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0,csr0); //polling the Tx interrupt if(musb_polling_ep0_interrupt()) return; DBG(0,"musb_h_setup--\n"); return; }
static void configure_channel(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_controller *controller = musb_channel->controller; void __iomem *mbase = controller->base; u8 bchannel = musb_channel->idx; u16 csr = 0; DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", channel, packet_sz, dma_addr, len, mode); if (mode) { csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; BUG_ON(len < packet_sz); if (packet_sz >= 64) { csr |= MUSB_HSDMA_BURSTMODE_INCR16 << MUSB_HSDMA_BURSTMODE_SHIFT; } else if (packet_sz >= 32) { csr |= MUSB_HSDMA_BURSTMODE_INCR8 << MUSB_HSDMA_BURSTMODE_SHIFT; } else if (packet_sz >= 16) { csr |= MUSB_HSDMA_BURSTMODE_INCR4 << MUSB_HSDMA_BURSTMODE_SHIFT; } } csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) | (1 << MUSB_HSDMA_ENABLE_SHIFT) | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) | (musb_channel->transmit ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) : 0); if (musb_channel->transmit) controller->tx_active |= (1 << bchannel); else controller->rx_active |= (1 << bchannel); /* address/count */ musb_write_hsdma_addr(mbase, bchannel, dma_addr); musb_write_hsdma_count(mbase, bchannel, len); /* control (this should start things) */ musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), csr); }
void musb_h_out_status(void){ unsigned short csr0; DBG(0,"musb_h_out_status++\n"); csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); csr0 |= MUSB_CSR0_H_STATUSPKT | MUSB_CSR0_TXPKTRDY; musb_writew(mtk_musb->mregs, MUSB_OTG_CSR0, csr0); if(musb_polling_ep0_interrupt()) return; #ifdef DX_DBG csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0); DBG(0,"csr0 = 0x%x!\n",csr0); #endif DBG(0,"musb_h_out_status--\n"); return; }
static void configure_channel(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; void __iomem *mbase = controller->base; u8 bchannel = musb_channel->idx; u8 buffer_is_aligned = (dma_addr & 0x3) ? 0 : 1; u8 use_sdma = (musb_channel->sysdma_channel == -1) ? 0 : 1; u16 csr = 0; DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", channel, packet_sz, dma_addr, len, mode); if (buffer_is_aligned && (packet_sz >= 512) && (musb->hwvers >= MUSB_HWVERS_1800)) use_sdma = 0; if (use_sdma) { musb_sdma_channel_program(musb, musb_channel, dma_addr, len); } else { /* Mentor DMA */ if (mode) { csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; BUG_ON(len < packet_sz); } csr |= MUSB_HSDMA_BURSTMODE_INCR16 << MUSB_HSDMA_BURSTMODE_SHIFT; csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) | (1 << MUSB_HSDMA_ENABLE_SHIFT) | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) | (musb_channel->transmit ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) : 0); /* address/count */ musb_write_hsdma_addr(mbase, bchannel, dma_addr); musb_write_hsdma_count(mbase, bchannel, len); /* control (this should start things) */ musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), csr); } }
void musb_otg_reset_usb(void){ //reset all of the USB IP, including PHY and MAC unsigned int usb_reset; usb_reset = __raw_readl(PERICFG_BASE); usb_reset |= 1<<29; __raw_writel(usb_reset,PERICFG_BASE); mdelay(10); usb_reset &= ~(1<<29); __raw_writel(usb_reset,PERICFG_BASE); //power on the USB usb_phy_poweron(); //enable interrupt musb_writel(mtk_musb->mregs,USB_L1INTM,0x105); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,1); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0xf7); }
unsigned int musb_polling_ep0_interrupt(void){ unsigned short intrtx; DBG(0,"polling ep0 interrupt\n"); do{ intrtx = musb_readw(mtk_musb->mregs,MUSB_INTRTX); mb(); musb_writew(mtk_musb->mregs,MUSB_INTRTX,intrtx); if(intrtx&0x1){//ep0 interrupt happen DBG(0,"get ep0 interrupt,csr0=0x%x\n",musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0)); break; } else{ DBG(0,"polling ep0 interrupt,csr0=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_OTG_CSR0)); wait_for_completion_timeout (&stop_event,1); if(!g_exec) return TEST_IS_STOP; } } while(g_exec); return 0; }
int musb_otg_env_exit(void){ DBG(0,"stop the USB-IF test in EM!\n"); musb_writel(mtk_musb->mregs,USB_L1INTM,0); musb_writew(mtk_musb->mregs,MUSB_INTRRXE,0); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,0); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0); musb_writew(mtk_musb->mregs,MUSB_INTRRX,0xffff); musb_writew(mtk_musb->mregs,MUSB_INTRTX,0xffff); musb_writeb(mtk_musb->mregs,MUSB_INTRUSB,0xff); musb_writel(mtk_musb->mregs,USB_L1INTM,usb_l1intm_store); musb_writew(mtk_musb->mregs,MUSB_INTRRXE,usb_intrrxe_store); musb_writew(mtk_musb->mregs,MUSB_INTRTXE,usb_intrtxe_store); musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,usb_intrusbe_store); mtk_musb->usb_if = false; mtk_musb->is_host = false; upmu_interrupt_chrdet_int_en(1); return 0; }