Esempio n. 1
0
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;
                }
                }
            }
        }
}
Esempio n. 8
0
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;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 13
0
/*
 * 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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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);
}
Esempio n. 17
0
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);
}
Esempio n. 18
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;
	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;
}
Esempio n. 19
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;
}
Esempio n. 21
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);
}
Esempio n. 22
0
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");
}
Esempio n. 23
0
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;
}
Esempio n. 25
0
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;
}
Esempio n. 27
0
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;
}