static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 val;

	/* Fence read for coherency of AHB master intiated writes */
	if (tegra->phy->instance == 0)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
	else if (tegra->phy->instance == 1)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
	else if (tegra->phy->instance == 2)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));

	if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
		(tegra->ehci->has_hostpc)) {
		/* check if there is any remote wake event */
		if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
			spin_lock (&ehci->lock);
			usb_hcd_resume_root_hub(hcd);
			spin_unlock (&ehci->lock);
		}
	}
	if (tegra->phy->hotplug) {
		spin_lock(&ehci->lock);
		val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
		if ((val  & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
			val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB |
				TEGRA_USB_PHY_CLK_VALID_INT_STS;
			writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));

			val = readl(&hw->status);
			if (!(val  & STS_PCD)) {
				spin_unlock(&ehci->lock);
				return 0;
			}
			val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
			val &= ~(TEGRA_USB_PORTSC1_WKCN | PORT_RWC_BITS);
			writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
		}
		spin_unlock(&ehci->lock);
	}
	return ehci_irq(hcd);
}
Beispiel #2
0
static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct ehci_regs __iomem *hw = ehci->regs;
	u32 val;
	//(weron) if receive more than 100 interrupt during usb resume, it means 3G module already crazy
	//Here we disable USB interrupt and recover later
	if (tegra->phy->instance == 1)
	{
		if(my_resume_process==1)
		{
			count++;
			if(count>100)
			{
				printk("I am crazy!!!\n");
				ehci_writel(tegra->ehci, 0, &tegra->ehci->regs->intr_enable);
				count=0;
				crazyflag=1;
			}
		}
		else
			count=0;
	}
	if (tegra->phy->instance == 2) {
		spin_lock(&ehci->lock);
		val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
		if ((val  & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
			val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB | TEGRA_USB_PHY_CLK_VALID_INT_STS;
			writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));

			val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
			val &= ~(TEGRA_USB_PORTSC1_WKCN | PORT_CSC | PORT_PEC | PORT_OCC);
			writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));

			val = readl(&hw->status);
			if (!(val  & STS_PCD)) {
				spin_unlock(&ehci->lock);
				return IRQ_NONE;
			}
		}
		spin_unlock (&ehci->lock);
	}
	return ehci_irq(hcd);
}
static irqreturn_t ehci_msp_irq(struct usb_hcd *hcd)
{
	u32 int_src;
	struct device *dev = hcd->self.controller;
	struct platform_device *pdev;
	struct mspusb_device *mdev;
	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
	
	pdev = to_platform_device(dev);
	mdev = to_mspusb_device(pdev);

	
	int_src = ehci_readl(ehci, &mdev->mab_regs->int_stat);
	if (int_src & (1 << pdev->id))
		return ehci_irq(hcd);

	
	return IRQ_NONE;
}
Beispiel #4
0
/*
 * Wrapper around the main ehci_irq.  Since both USB host controllers are
 * sharing the same IRQ, need to first determine whether we're the intended
 * recipient of this interrupt.
 */
static irqreturn_t ehci_msp_irq(struct usb_hcd *hcd)
{
    u32 int_src;
    struct device *dev = hcd->self.controller;
    struct platform_device *pdev;
    struct mspusb_device *mdev;
    struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
    /* need to reverse-map a couple of containers to get our device */
    pdev = to_platform_device(dev);
    mdev = to_mspusb_device(pdev);

    /* Check to see if this interrupt is for this host controller */
    int_src = ehci_readl(ehci, &mdev->mab_regs->int_stat);
    if (int_src & (1 << pdev->id))
        return ehci_irq(hcd);

    /* Not for this device */
    return IRQ_NONE;
}
Beispiel #5
0
static irqreturn_t msm_ehci_irq(struct usb_hcd *hcd)
{
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
	int ret = 0;

	if (atomic_read(&mhcd->in_lpm)) {
		dev_dbg(mhcd->dev, "phy async intr\n");
		ret = pm_runtime_get(mhcd->dev);
		if ((ret == 1) || (ret == -EINPROGRESS)) {
			pm_runtime_put_noidle(mhcd->dev);
		} else {
			disable_irq_nosync(hcd->irq);
			mhcd->async_int = true;
		}
		return IRQ_HANDLED;
	}

	return ehci_irq(hcd);
}
Beispiel #6
0
void tegra_ehci_enable_host (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	unsigned long flags;

	spin_lock_irqsave (&ehci->lock, flags);

	if (ehci->transceiver->state == OTG_STATE_A_HOST) {
		if (!ehci->host_reinited) {
			schedule_work(&ehci->irq_work);
			spin_unlock_irqrestore (&ehci->lock, flags);
			return;
		} else
			printk(KERN_DEBUG "%s host initialized already\n", __func__);
	} else if (ehci->transceiver->state == OTG_STATE_A_SUSPEND) {
		if (!ehci->host_reinited) {
			printk(KERN_DEBUG "%s host not initialized\n", __func__);
			spin_unlock_irqrestore (&ehci->lock, flags);
			return;
		}
		else {
			/* Force the disconnect because otherwise we could get
			 * left in the connected state if the last getPorStatus
			 * request comes in before the HOST -> SUSPEND state
			 * change. */
			spin_unlock_irqrestore (&ehci->lock, flags);
			/* indicate hcd flags, that hardware is not accessible now */
			clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
			ehci_halt(ehci);
			tegra_ehci_power_down(hcd);
			ehci->transceiver->state = OTG_STATE_UNDEFINED;
			ehci->host_reinited = 0;
			return;
		}
	} else
		printk(KERN_DEBUG "%s unexpected state\n", __func__);

	spin_unlock_irqrestore (&ehci->lock, flags);
	ehci_irq(hcd);

	return;
}
static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
	u32			status;

	if (atomic_read(&mehci->in_lpm)) {
		disable_irq_nosync(hcd->irq);
		dev_dbg(mehci->dev, "phy async intr\n");
		mehci->async_int = true;
		pm_runtime_get(mehci->dev);
		return IRQ_HANDLED;
	}

	status = ehci_readl(ehci, &ehci->regs->status);

	if (status & STS_GPTIMER0_INTERRUPT) {
		int timeleft;

		dbg_log_event(NULL, "FPR: gpt0_isr", 0);

		timeleft = GPT_CNT(ehci_readl(ehci,
						 &mehci->timer->gptimer1_ctrl));
		if (timeleft) {
			ehci_writel(ehci, ehci_readl(ehci,
				&ehci->regs->command) | CMD_RUN,
				&ehci->regs->command);
		} else
			mehci->resume_again = 1;

		dbg_log_event(NULL, "FPR: timeleft", timeleft);

		complete(&mehci->gpt0_completion);
		ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
	}

	return ehci_irq(hcd);
}
Beispiel #8
0
static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 val;

	if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
		(tegra->ehci->has_hostpc)) {
		/* check if there is any remote wake event */
		if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
			spin_lock (&ehci->lock);
			usb_hcd_resume_root_hub(hcd);
			spin_unlock (&ehci->lock);
		}
	}
	if (tegra->hotplug) {
		spin_lock(&ehci->lock);
		val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
		if ((val  & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
			val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB |
				TEGRA_USB_PHY_CLK_VALID_INT_STS;
			writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));

			val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
			val &= ~TEGRA_USB_PORTSC1_WKCN;
			writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));

			val = readl(&hw->status);
			if (!(val  & STS_PCD)) {
				spin_unlock(&ehci->lock);
				return 0;
			}
		}
		spin_unlock(&ehci->lock);
	}
	return ehci_irq(hcd);
}
Beispiel #9
0
int new_usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
			 __u16 value, __u16 index, void *data, __u16 size, int timeout)
{

#ifdef CONFIG_ENABLE_MIPS16
	u8 *dma_data=kmalloc(16,GFP_NOIO);
#endif
	struct usb_ctrlrequest *dr;
	struct urb *urb;
	volatile int done=0;
	unsigned long expire;
	int retry_cnt=0;	
	int status;
	int retval;
#ifdef USB_LOCK_ENABLE
	unsigned long flags;
#endif
	
	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
	if (!dr)
	{
		return -ENOMEM;
	}

	dr->bRequestType= requesttype;
	dr->bRequest = request;
	dr->wValue = cpu_to_le16p(&value);
	dr->wIndex = cpu_to_le16p(&index);
	dr->wLength = cpu_to_le16p(&size);

	if((value==0x300)||(value==0x320))
	{
		printk("Can't submit control msg value=%x\n",value);
		if(size==4)
			*(u32*)(data)=0;
		else if(size==1)
			*(u8*)(data)=0;
		else if(size==2)
			*(u16*)(data)=0;
		
		kfree(dr);
		return 0;
	}
	
#ifdef __LINUX_2_6__
	urb = usb_alloc_urb(0, GFP_ATOMIC);
#else
	urb = usb_alloc_urb(0);
#endif
	if (!urb)
	{
		kfree(dr);
		return -ENOMEM;
	}

	usb_control_cnt++;
	if(usb_control_cnt>1)
		printk("Error usb_control_cnt=%x\n",usb_control_cnt);	

//  printk("fill urb data=%x indx=%x size=%d\n",*(u8*)data,index,size);
#ifdef CONFIG_ENABLE_MIPS16
	usb_fill_control_urb(urb, dev, pipe, (unsigned char *)dr, (void*)dma_data,
			     size, new_usb_api_blocking_completion, (void *)&done);
#else
	usb_fill_control_urb(urb, dev, pipe, (unsigned char *)dr, data,
			     size, new_usb_api_blocking_completion, (void *)&done);
#endif
	urb->actual_length = 0;

#ifdef CONFIG_ENABLE_MIPS16
	if(request==RTL8192_REQ_SET_REGS) memcpy(dma_data,data,size);
	dma_cache_wback_inv((u32)dma_data,size);
	//rtl_cache_sync_wback(priv, (unsigned int)dma_data, size, 0);
#else
	if(request==RTL8192_REQ_SET_REGS)
		dma_cache_wback_inv((unsigned long)data, size);
#endif

#ifdef __LINUX_2_6__
	status = usb_submit_urb(urb, GFP_ATOMIC);
#else
	status = usb_submit_urb(urb);
#endif
	if (unlikely(status))
	{
		goto out;
	}


	if(timeout)		//expire = msecs_to_jiffies(timeout) + jiffies;
		expire = timeout + jiffies;
	else
		expire =  200 + jiffies; //cathy
 
	if(expire<200)
	{
		if(!in_atomic())
		{
			delay_ms(2100);
			expire=jiffies+200;
		}
		else
			expire=0xffffffffL; 
	}
 
retry:
	
	if(done==1) goto out;
	if(jiffies>=expire) goto out;
	
#ifndef USB_LOCK_ENABLE
	if(in_atomic())
#endif
	{
		unsigned long		flags=0;
		retry_cnt++;
		if(retry_cnt>2000) goto out;

#ifdef CONFIG_USB_OTG_Driver
		dwc_otg_hcd_irq(usbhcd, NULL);
		printk("%s %d done=%x jiffies=%x expire=%x\n",__FUNCTION__,__LINE__,done,jiffies,expire);
#elif defined(CONFIG_USB_OTG_HOST_RTL8672)
		usb_scan_async(dev->bus, 0);
#elif defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_RTL8652)
{
		struct usb_hcd *hcd=bus_to_hcd(dev->bus);
#ifdef __LINUX_2_6__
		struct ehci_hcd *ehci=(struct ehci_hcd *)hcd->hcd_priv;
		spin_lock_irqsave (&ehci->lock, flags);
		//scan_async(ehci);
		ehci_irq(hcd);		
		spin_unlock_irqrestore (&ehci->lock, flags);
#else
		ehci_irq(hcd, NULL);
#endif
}
#endif
		
	}
#ifndef USB_LOCK_ENABLE
	else
		schedule();	
#endif

	goto retry;

out:

	if(retry_cnt>2000)
	{
		printk("Timeout! requesttype=%x request=%x value=%x index=%x size=%x retry_cnt=%d\n",requesttype,request,value,index,size,retry_cnt);
	}
	
	if(done==0)
	{
#if 0
		printk("USB Timeout!!!\n");		
		if(!in_atomic()) 
		{
			usb_kill_urb(urb);
		}
		else
		{
			printk("in atomic, can't kill urb\n");
		}
		status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
#else
		retval = new_usb_kill_urb(urb);
		status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
		if((status != 0) && (status!= -ETIMEDOUT)) {
			printk("[%s,%d], urb->status = %d, retval = %d\n", __func__, __LINE__, urb->status, retval);
		}
#endif
	}
	else
	{
//		  printk("index=%x data=%x done\n",index,*(u8*)data); 
#ifdef CONFIG_ENABLE_MIPS16
		if(request==RTL8192_REQ_GET_REGS) memcpy(data,dma_data,size);
#endif
		status = urb->status;
	}

	usb_free_urb(urb);
#ifdef CONFIG_ENABLE_MIPS16
	kfree(dma_data);
#endif
	kfree(dr);

	usb_control_cnt--;
	return status;
}
static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 val;
	irqreturn_t irq_status;
	bool pmc_remote_wakeup = false;

	/* Fence read for coherency of AHB master intiated writes */
	if (tegra->phy->instance == 0)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
	else if (tegra->phy->instance == 1)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
	else if (tegra->phy->instance == 2)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));

	if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
		(tegra->ehci->has_hostpc)) {
		/* check if there is any remote wake event */
		if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
			pmc_remote_wakeup = true;
			spin_lock (&ehci->lock);
			usb_hcd_resume_root_hub(hcd);
			spin_unlock (&ehci->lock);
		}
	}
	if (tegra->phy->hotplug) {
		spin_lock(&ehci->lock);
		val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
		if ((val  & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
			val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB |
				TEGRA_USB_PHY_CLK_VALID_INT_STS;
			writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));
			val = readl(&hw->status);
			if (!(val  & STS_PCD)) {
				spin_unlock(&ehci->lock);
				return 0;
			}
			val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
			val &= ~(TEGRA_USB_PORTSC1_WKCN | PORT_RWC_BITS);
			writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
		}
		else if (tegra->bus_suspended &&
				tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
			printk("%s: no device connected before suspend\n", __func__);
			spin_unlock(&ehci->lock);
			return 0;
		}
		spin_unlock(&ehci->lock);
	}

	irq_status = ehci_irq(hcd);

	if (pmc_remote_wakeup || tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
		ehci->controller_remote_wakeup = false;
	}

	if (ehci->controller_remote_wakeup) {
		ehci->controller_remote_wakeup = false;
		/* disable interrupts */
		ehci_writel(ehci, 0, &ehci->regs->intr_enable);
		tegra_usb_phy_preresume(tegra->phy, true);
		tegra->port_resuming = 1;
	}
	return irq_status;
}
static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
{
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	irqreturn_t irq_status;
	bool pmc_remote_wakeup = false;
	struct platform_device *pdev = container_of(hcd->self.controller, struct platform_device, dev);
	int ehci_id = pdev->id;

	spin_lock(&ehci->lock);
	irq_status = tegra_usb_phy_irq(tegra->phy);
	if (irq_status == IRQ_NONE) {
		spin_unlock(&ehci->lock);
		return irq_status;
	}
	if (tegra_usb_phy_remote_wakeup(tegra->phy)) {
		ehci_info(ehci, "remote wakeup detected on controller.%d\n", ehci_id);

		/* +SSD_RIL: workaround for remote wake AT timeout. */
		if (Modem_is_IMC() && ehci_id == MODEM_EHCI_ID)
		{
			debug_gpio_dump();
			//trigger_radio_fatal_get_coredump("remote wakeup in PMC");
		}
		else
		{
			pmc_remote_wakeup = true;
			usb_hcd_resume_root_hub(hcd);
		}
		/* -SSD_RIL: workaround for remote wake AT timeout. */

		spin_unlock(&ehci->lock);
		return irq_status;
	}
	spin_unlock(&ehci->lock);

//	EHCI_DBG("%s() cmd = 0x%x, int_sts = 0x%x, portsc = 0x%x\n", __func__,
//		ehci_readl(ehci, &ehci->regs->command),
//		ehci_readl(ehci, &ehci->regs->status),
//		ehci_readl(ehci, &ehci->regs->port_status[0]));

	irq_status = ehci_irq(hcd);

	if (pmc_remote_wakeup) {
		ehci->controller_remote_wakeup = false;
	}

	if (ehci->controller_remote_wakeup) {
		ehci->controller_remote_wakeup = false;

		/* +SSD_RIL: workaround for remote wake hang. */
		if (Modem_is_IMC() && ehci_id == MODEM_EHCI_ID)
		{
			ehci_info(ehci, "controller.%d remote wakeup detected", ehci_id);
			debug_gpio_dump();
			//trigger_radio_fatal_get_coredump("remote wakeup in controller");
		}
		else
		{
			tegra_usb_phy_pre_resume(tegra->phy, true);
			tegra->port_resuming = 1;
		}
		/* -SSD_RIL: workaround for remote wake hang. */
	}
	return irq_status;
}