예제 #1
0
static int /*__devinit*/ ohci_rtl819x_start(struct usb_hcd *hcd)
{
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	int ret;
    unsigned int fminterval; 

	ret = ohci_init(ohci);
	if (ret < 0)
		return ret;

#if 1
    fminterval = 0x2edf;
    ohci_writel (ohci,(fminterval * 9) / 10, &ohci->regs->periodicstart);                                           
    fminterval |= ((((fminterval - 210) * 6) / 7) << 16); 
    ohci_writel (ohci, fminterval, &ohci->regs->fminterval); 

    ohci_writel (ohci, 0x0628, &ohci->regs->lsthresh); 		/* default value from datasheet */
    ohci_writel (ohci, 0x3e67, &ohci->regs->periodicstart); /* default value from datasheet */
#endif

	ret = ohci_run(ohci);

	if (ret < 0) 
		goto err;

	return 0;

 err:
	ohci_stop(hcd);
	return ret;
}
예제 #2
0
파일: ohci-s5p.c 프로젝트: Hackhao/tzos
int s5p_ohci_port_power_off(struct platform_device *pdev)
{
	struct s5p_ohci_hcd *s5p_ohci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ohci->hcd;
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);

	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	ohci_writel (ohci, RH_HS_LPS, &ohci->regs->roothub.status);

	return 0;
}
예제 #3
0
static int ohci_brcm_suspend(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	unsigned long	flags;
	int		rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 */
	spin_lock_irqsave(&ohci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED) {
		rc = -EINVAL;
		goto bail;
	}
	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	brcm_usb_suspend(hcd);
 bail:
	spin_unlock_irqrestore(&ohci->lock, flags);

	return rc;
}
예제 #4
0
static int ohci_da8xx_init(struct usb_hcd *hcd)
{
	struct device *dev		= hcd->self.controller;
	struct da8xx_ohci_root_hub *hub	= dev->platform_data;
	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
	int result;
	u32 rh_a;

	dev_dbg(dev, "starting USB controller\n");

	ohci_da8xx_clock(1);

	/*
	 * DA830 only has 1 port connected to the pins but its HC root hub
	 * register A reports 2 ports, thus we'll have to override it...
	 */
	ohci->num_ports = 1;

	result = ohci_init(ohci);
	if (result < 0)
		return result;

	/*
	 * Since we're providing a board-specific root hub port power control
	 * and over-current reporting, we have to override the HC root hub A
	 * register's default value, so that ohci_hub_control() could return
	 * the correct hub descriptor...
	 */
	rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
	rh_a &= ~(RH_A_POTPGT | RH_A_NPS | RH_A_NOCP);
	rh_a |=  (hub->potpgt << 24) | RH_A_PSM | RH_A_OCPM;
	ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);

	return result;
}
예제 #5
0
static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	unsigned long flags;
	int rc;

	rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 */
	spin_lock_irqsave(&ohci->lock, flags);
	if (ohci->rh_state != OHCI_RH_SUSPENDED) {
		rc = -EINVAL;
		goto bail;
	}
	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

	alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
bail:
	spin_unlock_irqrestore(&ohci->lock, flags);

	return rc;
}
예제 #6
0
파일: ohci-s5p.c 프로젝트: Hackhao/tzos
static int ohci_hcd_s5p_drv_runtime_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct s5p_ohci_platdata *pdata = pdev->dev.platform_data;
	struct s5p_ohci_hcd *s5p_ohci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ohci->hcd;
#ifdef CONFIG_USB_EXYNOS_SWITCH
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
#endif
	if (dev->power.is_suspended)
		return 0;

	if (pdata->phy_resume)
		pdata->phy_resume(pdev, S5P_USB_PHY_HOST);
	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

#ifdef CONFIG_USB_EXYNOS_SWITCH
	if (samsung_board_rev_is_0_0())
		ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);
#endif

	ohci_finish_controller_resume(hcd);
	return 0;
}
static void ohci_exynos_stop(struct usb_hcd *hcd)
{
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);

	ohci_dump(ohci, 1);

	if (quirk_nec(ohci))
		flush_work_sync(&ohci->nec_work);

	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	ohci_usb_reset(ohci);

	free_irq(hcd->irq, hcd);
	hcd->irq = 0;

	if (quirk_zfmicro(ohci))
		del_timer(&ohci->unlink_watchdog);
	if (quirk_amdiso(ohci))
		usb_amd_dev_put();

	remove_debug_files(ohci);
	ohci_mem_cleanup(ohci);
	if (ohci->hcca) {
		dma_free_coherent(hcd->self.controller,
				sizeof *ohci->hcca,
				ohci->hcca, ohci->hcca_dma);
		ohci->hcca = NULL;
		ohci->hcca_dma = 0;
	}
}
static int exynos_ohci_runtime_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
	struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = exynos_ohci->hcd;
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
	unsigned long flags;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave(&ohci->lock, flags);
	if (ohci->rh_state != OHCI_RH_SUSPENDED && ohci->rh_state != OHCI_RH_HALTED) {
		spin_unlock_irqrestore(&ohci->lock, flags);
		err("Not ready %s", hcd->self.bus_name);
		return 0;
	}

	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	spin_unlock_irqrestore(&ohci->lock, flags);

	if (pdata->phy_suspend)
		pdata->phy_suspend(pdev, S5P_USB_PHY_HOST);

	return 0;
}
예제 #9
0
파일: ohci-pci.c 프로젝트: ANFS/ANFS-kernel
static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	unsigned long	flags;
	int		rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave (&ohci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED) {
		rc = -EINVAL;
		goto bail;
	}
	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 bail:
	spin_unlock_irqrestore (&ohci->lock, flags);

	return rc;
}
static int ohci_da8xx_init(struct usb_hcd *hcd)
{
	struct device *dev		= hcd->self.controller;
	struct da8xx_ohci_root_hub *hub	= dev->platform_data;
	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
	int result;
	u32 rh_a;

	dev_dbg(dev, "starting USB controller\n");

	ohci_da8xx_clock(1);

	ohci->num_ports = 1;

	result = ohci_init(ohci);
	if (result < 0)
		return result;

	rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
	if (hub->set_power) {
		rh_a &= ~RH_A_NPS;
		rh_a |=  RH_A_PSM;
	}
	if (hub->get_oci) {
		rh_a &= ~RH_A_NOCP;
		rh_a |=  RH_A_OCPM;
	}
	rh_a &= ~RH_A_POTPGT;
	rh_a |= hub->potpgt << 24;
	ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);

	return result;
}
예제 #11
0
int ohci_power(void *ohci, int is_on)
{
	struct ohci_hcd *ohcip = (struct ohci_hcd *)ohci;
	int port;
	int temp;

	temp = roothub_a(ohcip);

	/* If NoPowerSwitching is true, just return */
	if (temp & RH_A_NPS) {
		return 0;
	}

	/* If port switched, switch each port */
	if (temp & RH_A_PSM) {
		for (port = ohcip->num_ports; port > 0; ) {
			(void) ohci_hub_control(ohci_to_hcd(ohcip),
									is_on ? SetPortFeature : ClearPortFeature,
									USB_PORT_FEAT_POWER,
									port--, NULL, 0);
		}
	}
	/* Else use Global Power */
	else {
		temp = roothub_status(ohcip);
		if (is_on) {
			temp |= RH_HS_LPSC;	 /* SetGlobalPower */
		}
		else {
			temp |= RH_HS_LPS;	 /* ClearGlobalPower */
		}
		ohci_writel(ohcip, temp, &ohcip->regs->roothub.status);
	}
	return 0;
}
예제 #12
0
/*
*******************************************************************************
*                     sw_ohci_hcd_suspend
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int sw_ohci_hcd_suspend(struct device *dev)
{
	struct sw_hci_hcd *sw_ohci  = NULL;
	struct usb_hcd *hcd         = NULL;
	struct ohci_hcd	*ohci       = NULL;
	unsigned long flags         = 0;
	int rc                      = 0;

	if(dev == NULL){
		DMSG_PANIC("ERR: Argment is invalid\n");
		return 0;
	}

	hcd = dev_get_drvdata(dev);
	if(hcd == NULL){
		DMSG_PANIC("ERR: hcd is null\n");
		return 0;
	}

	sw_ohci = dev->platform_data;
	if(sw_ohci == NULL){
		DMSG_PANIC("ERR: sw_ohci is null\n");
		return 0;
	}

	if(sw_ohci->probe == 0){
		DMSG_PANIC("ERR: sw_ohci is disable, can not suspend\n");
		return 0;
	}

	ohci = hcd_to_ohci(hcd);
	if(ohci == NULL){
		DMSG_PANIC("ERR: ohci is null\n");
		return 0;
	}

 	DMSG_INFO("[%s]: sw_ohci_hcd_suspend\n", sw_ohci->hci_name);

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave(&ohci->lock, flags);

    ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
    (void)ohci_readl(ohci, &ohci->regs->intrdisable);

    clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

    spin_unlock_irqrestore(&ohci->lock, flags);

    sw_stop_ohc(sw_ohci);

    return rc;
}
예제 #13
0
파일: ohci-s5p.c 프로젝트: Hackhao/tzos
int s5p_ohci_port_power_on(struct platform_device *pdev)
{
	struct s5p_ohci_hcd *s5p_ohci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ohci->hcd;
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);

	ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);

	return 0;
}
예제 #14
0
/* hcd->hub_irq_enable() */
static void ohci_rhsc_enable (struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);

	spin_lock_irq(&ohci->lock);
	if (!ohci->autostop)
		del_timer(&hcd->rh_timer);	/* Prevent next poll */
	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
	spin_unlock_irq(&ohci->lock);
}
예제 #15
0
static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd)
{
	int result;
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);

	
	

	ohci_writel(ohci, 0x7f000000 | RH_A_PSM | RH_A_OCPM,
		&ohci->regs->roothub.a);
	ohci_writel(ohci, 0x00060000, &ohci->regs->roothub.b);

	result = ohci_run(ohci);

	if (result < 0) {
		err("can't start %s", hcd->self.bus_name);
		ohci_stop(hcd);
	}

	return result;
}
예제 #16
0
static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd)
{
	int result;
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);

	/* Handle root hub init quirk in spider south bridge. */
	/* Also set PwrOn2PwrGood to 0x7f (254ms). */

	ohci_writel(ohci, 0x7f000000 | RH_A_PSM | RH_A_OCPM,
		&ohci->regs->roothub.a);
	ohci_writel(ohci, 0x00060000, &ohci->regs->roothub.b);

	result = ohci_run(ohci);

	if (result < 0) {
		err("can't start %s", hcd->self.bus_name);
		ohci_stop(hcd);
	}

	return result;
}
예제 #17
0
파일: ohci-s5p.c 프로젝트: Hackhao/tzos
static int ohci_hcd_s5p_drv_runtime_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct s5p_ohci_platdata *pdata = pdev->dev.platform_data;
	struct s5p_ohci_hcd *s5p_ohci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ohci->hcd;
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
	unsigned long flags;
	int rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave(&ohci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) {
		spin_unlock_irqrestore(&ohci->lock, flags);
		err("Not ready %s", hcd->self.bus_name);
		return rc;
	}

	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	spin_unlock_irqrestore(&ohci->lock, flags);

#ifdef CONFIG_USB_EXYNOS_SWITCH
	if (samsung_board_rev_is_0_0())
		ohci_writel (ohci, RH_HS_LPS, &ohci->regs->roothub.status);
#endif
	if (pdata->phy_suspend)
		pdata->phy_suspend(pdev, S5P_USB_PHY_HOST);

	return rc;
}
예제 #18
0
static int __devinit ohci_rtl8652_start(struct usb_hcd *hcd)
{
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
	int ret;
	unsigned int fminterval;

	if ((ret = ohci_init(ohci)) < 0)
		return ret;
	
  	fminterval = 0x2edf;
	ohci_writel (ohci,(fminterval * 9) / 10, &ohci->regs->periodicstart);
	fminterval |= ((((fminterval - 210) * 6) / 7) << 16); 
	ohci_writel (ohci,fminterval, &ohci->regs->fminterval);	
	ohci_writel (ohci,0x628, &ohci->regs->lsthresh);
	ohci_writel(ohci,0x3e67,&ohci->regs->periodicstart);
	if ((ret = ohci_run(ohci)) < 0) {
		err("can't start %s", hcd->self.bus_name);
		ohci_stop(hcd);
		return ret;
	}

	return 0;
}
예제 #19
0
static int ohci_da8xx_reset(struct usb_hcd *hcd)
{
	struct device *dev		= hcd->self.controller;
	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(dev);
	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
	int result;
	u32 rh_a;

	dev_dbg(dev, "starting USB controller\n");

	result = ohci_da8xx_enable(hcd);
	if (result < 0)
		return result;

	/*
	 * DA8xx only have 1 port connected to the pins but the HC root hub
	 * register A reports 2 ports, thus we'll have to override it...
	 */
	ohci->num_ports = 1;

	result = ohci_setup(hcd);
	if (result < 0) {
		ohci_da8xx_disable(hcd);
		return result;
	}

	/*
	 * Since we're providing a board-specific root hub port power control
	 * and over-current reporting, we have to override the HC root hub A
	 * register's default value, so that ohci_hub_control() could return
	 * the correct hub descriptor...
	 */
	rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
	if (ohci_da8xx_has_set_power(hcd)) {
		rh_a &= ~RH_A_NPS;
		rh_a |=  RH_A_PSM;
	}
	if (ohci_da8xx_has_oci(hcd)) {
		rh_a &= ~RH_A_NOCP;
		rh_a |=  RH_A_OCPM;
	}
	if (ohci_da8xx_has_potpgt(hcd)) {
		rh_a &= ~RH_A_POTPGT;
		rh_a |= hub->potpgt << 24;
	}
	ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);

	return result;
}
예제 #20
0
/* Following a power loss, we must prepare to regain control of the ports
 * we used to own.  This means turning on the port power before ehci-hcd
 * tries to switch ownership.
 *
 * This isn't a 100% perfect solution.  On most systems the OHCI controllers
 * lie at lower PCI addresses than the EHCI controller, so they will be
 * discovered (and hence resumed) first.  But there is no guarantee things
 * will always work this way.  If the EHCI controller is resumed first and
 * the OHCI ports are unpowered, then the handover will fail.
 */
static void prepare_for_handover(struct usb_hcd *hcd)
{
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	int		port;

	/* Here we "know" root ports should always stay powered */
	ohci_dbg(ohci, "powerup ports\n");
	for (port = 0; port < ohci->num_ports; port++)
		ohci_writel(ohci, RH_PS_PPS,
				&ohci->regs->roothub.portstatus[port]);

	/* Flush those writes */
	ohci_readl(ohci, &ohci->regs->control);
	msleep(20);
}
예제 #21
0
static int ohci_brcm_start(struct usb_hcd *hcd)
{
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	struct ohci_regs __iomem *regs;

	regs = hcd->regs;

	ohci_writel(ohci, 1, &regs->cmdstatus);
	ohci_readl(ohci, &regs->cmdstatus);
	mdelay(10);

	ohci_hcd_init(ohci);
	ohci_init(ohci);
	ohci_run(ohci);
	hcd->state = HC_STATE_RUNNING;
	return 0;
}
예제 #22
0
static int ohci_hcd_s5pv210_runtime_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	unsigned long flags;
	int rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave(&ohci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED) {
		rc = -EINVAL;
		goto bail;
	}

	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

#if defined(CONFIG_SAMSUNG_PHONE_SVNET) || defined(CONFIG_SAMSUNG_LTE) || defined(CONFIG_UMTS_LINK_HSIC)
#else
	printk(KERN_DEBUG "USB_PM ohci rt susp\n");
	usb_host_phy_off();
#endif


bail:
	spin_unlock_irqrestore(&ohci->lock, flags);

	return rc;
}
예제 #23
0
static int ohci_hcd_spmp_drv_suspend(struct platform_device *pdev,
					pm_message_t message)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
	struct spmp_ohci *spmpohci = (struct spmp_ohci *)hcd_to_ohci(hcd);
	unsigned long flags;
	int rc;

	rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave(&ohci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED) {
		rc = -EINVAL;
		goto bail;
	}
	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);

	/* make sure snapshot being resumed re-enumerates everything */
	if (message.event == PM_EVENT_PRETHAW)
		ohci_usb_reset(ohci);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

	spmp_stop_ohc(spmpohci, &pdev->dev);
bail:
	spin_unlock_irqrestore(&ohci->lock, flags);

	return rc;
}
예제 #24
0
static int
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	int		i, changed = 0, length = 1;
	int		can_suspend;
	unsigned long	flags;

	can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
	spin_lock_irqsave (&ohci->lock, flags);

	/* handle autosuspended root:  finish resuming before
	 * letting khubd or root hub timer see state changes.
	 */
	if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
		     || !HC_IS_RUNNING(hcd->state))) {
		can_suspend = 0;
		goto done;
	}

	/* undocumented erratum seen on at least rev D */
	if ((ohci->flags & OHCI_QUIRK_AMD756)
			&& (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
		ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
			  ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
		/* retry later; "should not happen" */
		goto done;
	}

	/* init status */
	if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
		buf [0] = changed = 1;
	else
		buf [0] = 0;
	if (ohci->num_ports > 7) {
		buf [1] = 0;
		length++;
	}

	/* look at each port */
	for (i = 0; i < ohci->num_ports; i++) {
		u32	status = roothub_portstatus (ohci, i);

		/* can't autosuspend with active ports */
		if ((status & RH_PS_PES) && !(status & RH_PS_PSS))
			can_suspend = 0;

		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
				| RH_PS_OCIC | RH_PS_PRSC)) {
			changed = 1;
			if (i < 7)
			    buf [0] |= 1 << (i + 1);
			else
			    buf [1] |= 1 << (i - 7);
			continue;
		}
	}

	/* after root hub changes, stop polling after debouncing
	 * for a while and maybe kicking in autosuspend
	 */
	if (changed) {
		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
		can_suspend = 0;
	} else if (time_before (jiffies, ohci->next_statechange)) {
		can_suspend = 0;
	} else {
#ifdef	CONFIG_PM
		can_suspend = can_suspend
			&& !ohci->ed_rm_list
			&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
					& ohci->hc_control)
				== OHCI_USB_OPER;
#endif
		if (hcd->uses_new_polling) {
			hcd->poll_rh = 0;
			/* use INTR_RHSC iff INTR_RD won't apply */
			if (!can_suspend)
				ohci_writel (ohci, OHCI_INTR_RHSC,
						&ohci->regs->intrenable);
		}
	}

done:
	spin_unlock_irqrestore (&ohci->lock, flags);

#ifdef	CONFIG_PM
	/* save power by autosuspending idle root hubs;
	 * INTR_RD wakes us when there's work
	 */
	if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) {
		ohci_vdbg (ohci, "autosuspend\n");
		(void) ohci_bus_suspend (hcd);
		usb_unlock_device (hcd->self.root_hub);
	}
#endif

	return changed ? length : 0;
}
예제 #25
0
static int ohci_hub_suspend (struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
	int			status = 0;
	unsigned long		flags;

#ifndef USB_FREE_IRQ_AT_SUSPEND_MODE
#if defined(CONFIG_REALTEK_VENUS_USB_1261) || defined(CONFIG_REALTEK_VENUS_USB_1261_ECO)
	return 0;
#endif /* defined(CONFIG_REALTEK_VENUS_USB_1261) || defined(CONFIG_REALTEK_VENUS_USB_1261_ECO) */
#endif /* USB_FREE_IRQ_AT_SUSPEND_MODE */

	spin_lock_irqsave (&ohci->lock, flags);

	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
	case OHCI_USB_RESUME:
		ohci_dbg (ohci, "resume/suspend?\n");
		ohci->hc_control &= ~OHCI_CTRL_HCFS;
		ohci->hc_control |= OHCI_USB_RESET;
		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
		(void) ohci_readl (ohci, &ohci->regs->control);
		/* FALL THROUGH */
	case OHCI_USB_RESET:
		status = -EBUSY;
		ohci_dbg (ohci, "needs reinit!\n");
		goto done;
	case OHCI_USB_SUSPEND:
		ohci_dbg (ohci, "already suspended\n");
		goto done;
	}
	ohci_dbg (ohci, "suspend root hub\n");

	/* First stop any processing */
	hcd->state = HC_STATE_QUIESCING;
	if (ohci->hc_control & OHCI_SCHED_ENABLES) {
		int		limit;

		ohci->hc_control &= ~OHCI_SCHED_ENABLES;
		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
		ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
		ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);

		/* sched disables take effect on the next frame,
		 * then the last WDH could take 6+ msec
		 */
		ohci_dbg (ohci, "stopping schedules ...\n");
		limit = 2000;
		while (limit > 0) {
			udelay (250);
			limit =- 250;
			if (ohci_readl (ohci, &ohci->regs->intrstatus)
					& OHCI_INTR_SF)
				break;
		}
		dl_done_list (ohci, NULL);
		mdelay (7);
	}
	dl_done_list (ohci, NULL);
	finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
			&ohci->regs->intrstatus);

	/* maybe resume can wake root hub */
	if (hcd->remote_wakeup)
		ohci->hc_control |= OHCI_CTRL_RWE;
	else
		ohci->hc_control &= ~OHCI_CTRL_RWE;

	/* Suspend hub */
	ohci->hc_control &= ~OHCI_CTRL_HCFS;
	ohci->hc_control |= OHCI_USB_SUSPEND;
	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
	(void) ohci_readl (ohci, &ohci->regs->control);

	/* no resumes until devices finish suspending */
	ohci->next_statechange = jiffies + msecs_to_jiffies (5);

done:
	if (status == 0)
		hcd->state = HC_STATE_SUSPENDED;
	spin_unlock_irqrestore (&ohci->lock, flags);
	return status;
}
예제 #26
0
파일: ohci-omap.c 프로젝트: maraz/linux-2.6
static int ohci_omap_init(struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
	struct omap_usb_config	*config = hcd->self.controller->platform_data;
	int			need_transceiver = (config->otg != 0);
	int			ret;

	dev_dbg(hcd->self.controller, "starting USB Controller\n");

	if (config->otg) {
		ohci_to_hcd(ohci)->self.otg_port = config->otg;
		/* default/minimum OTG power budget:  8 mA */
		ohci_to_hcd(ohci)->power_budget = 8;
	}

	/* boards can use OTG transceivers in non-OTG modes */
	need_transceiver = need_transceiver
			|| machine_is_omap_h2() || machine_is_omap_h3();

	if (cpu_is_omap16xx())
		ocpi_enable();

#ifdef	CONFIG_ARCH_OMAP_OTG
	if (need_transceiver) {
		ohci->transceiver = otg_get_transceiver();
		if (ohci->transceiver) {
			int	status = otg_set_host(ohci->transceiver,
						&ohci_to_hcd(ohci)->self);
			dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
					ohci->transceiver->label, status);
			if (status) {
				if (ohci->transceiver)
					put_device(ohci->transceiver->dev);
				return status;
			}
		} else {
			dev_err(hcd->self.controller, "can't find transceiver\n");
			return -ENODEV;
		}
	}
#endif

	omap_ohci_clock_power(1);

	if (cpu_is_omap1510()) {
		omap_1510_local_bus_power(1);
		omap_1510_local_bus_init();
	}

	if ((ret = ohci_init(ohci)) < 0)
		return ret;

	/* board-specific power switching and overcurrent support */
	if (machine_is_omap_osk() || machine_is_omap_innovator()) {
		u32	rh = roothub_a (ohci);

		/* power switching (ganged by default) */
		rh &= ~RH_A_NPS;

		/* TPS2045 switch for internal transceiver (port 1) */
		if (machine_is_omap_osk()) {
			ohci_to_hcd(ohci)->power_budget = 250;

			rh &= ~RH_A_NOCP;

			/* gpio9 for overcurrent detction */
			omap_cfg_reg(W8_1610_GPIO9);
			omap_request_gpio(9);
			omap_set_gpio_direction(9, 1 /* IN */);

			/* for paranoia's sake:  disable USB.PUEN */
			omap_cfg_reg(W4_USB_HIGHZ);
		}
		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
		distrust_firmware = 0;
	} else if (machine_is_nokia770()) {
		/* We require a self-powered hub, which should have
		 * plenty of power. */
		ohci_to_hcd(ohci)->power_budget = 0;
	}

	/* FIXME khubd hub requests should manage power switching */
	omap_ohci_transceiver_power(1);

	/* board init will have already handled HMC and mux setup.
	 * any external transceiver should already be initialized
	 * too, so all configured ports use the right signaling now.
	 */

	return 0;
}
예제 #27
0
파일: ohci-omap.c 프로젝트: 7799/linux
static int ohci_omap_reset(struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
	struct omap_usb_config	*config = dev_get_platdata(hcd->self.controller);
	int			need_transceiver = (config->otg != 0);
	int			ret;

	dev_dbg(hcd->self.controller, "starting USB Controller\n");

	if (config->otg) {
		hcd->self.otg_port = config->otg;
		/* default/minimum OTG power budget:  8 mA */
		hcd->power_budget = 8;
	}

	/* boards can use OTG transceivers in non-OTG modes */
	need_transceiver = need_transceiver
			|| machine_is_omap_h2() || machine_is_omap_h3();

	/* XXX OMAP16xx only */
	if (config->ocpi_enable)
		config->ocpi_enable();

#ifdef	CONFIG_USB_OTG
	if (need_transceiver) {
		hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
		if (!IS_ERR_OR_NULL(hcd->phy)) {
			int	status = otg_set_host(hcd->phy->otg,
						&ohci_to_hcd(ohci)->self);
			dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
					hcd->phy->label, status);
			if (status) {
				usb_put_phy(hcd->phy);
				return status;
			}
		} else {
			dev_err(hcd->self.controller, "can't find phy\n");
			return -ENODEV;
		}
		ohci->start_hnp = start_hnp;
	}
#endif

	omap_ohci_clock_power(1);

	if (cpu_is_omap15xx()) {
		omap_1510_local_bus_power(1);
		omap_1510_local_bus_init();
	}

	ret = ohci_setup(hcd);
	if (ret < 0)
		return ret;

	if (config->otg || config->rwc) {
		ohci->hc_control = OHCI_CTRL_RWC;
		writel(OHCI_CTRL_RWC, &ohci->regs->control);
	}

	/* board-specific power switching and overcurrent support */
	if (machine_is_omap_osk() || machine_is_omap_innovator()) {
		u32	rh = roothub_a (ohci);

		/* power switching (ganged by default) */
		rh &= ~RH_A_NPS;

		/* TPS2045 switch for internal transceiver (port 1) */
		if (machine_is_omap_osk()) {
			ohci_to_hcd(ohci)->power_budget = 250;

			rh &= ~RH_A_NOCP;

			/* gpio9 for overcurrent detction */
			omap_cfg_reg(W8_1610_GPIO9);
			gpio_request(9, "OHCI overcurrent");
			gpio_direction_input(9);

			/* for paranoia's sake:  disable USB.PUEN */
			omap_cfg_reg(W4_USB_HIGHZ);
		}
		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
		ohci->flags &= ~OHCI_QUIRK_HUB_POWER;
	} else if (machine_is_nokia770()) {
		/* We require a self-powered hub, which should have
		 * plenty of power. */
		ohci_to_hcd(ohci)->power_budget = 0;
	}

	/* FIXME khubd hub requests should manage power switching */
	omap_ohci_transceiver_power(1);

	/* board init will have already handled HMC and mux setup.
	 * any external transceiver should already be initialized
	 * too, so all configured ports use the right signaling now.
	 */

	return 0;
}
예제 #28
0
static int ohci_bus_suspend (struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
	int			status = 0;
	unsigned long		flags;

	spin_lock_irqsave (&ohci->lock, flags);

	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
		spin_unlock_irqrestore (&ohci->lock, flags);
		return -ESHUTDOWN;
	}

	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
	case OHCI_USB_RESUME:
		ohci_dbg (ohci, "resume/suspend?\n");
		ohci->hc_control &= ~OHCI_CTRL_HCFS;
		ohci->hc_control |= OHCI_USB_RESET;
		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
		(void) ohci_readl (ohci, &ohci->regs->control);
		/* FALL THROUGH */
	case OHCI_USB_RESET:
		status = -EBUSY;
		ohci_dbg (ohci, "needs reinit!\n");
		goto done;
	case OHCI_USB_SUSPEND:
		ohci_dbg (ohci, "already suspended\n");
		goto done;
	}
	ohci_dbg (ohci, "suspend root hub\n");

	/* First stop any processing */
	if (ohci->hc_control & OHCI_SCHED_ENABLES) {
		int		limit;

		ohci->hc_control &= ~OHCI_SCHED_ENABLES;
		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
		ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
		ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);

		/* sched disables take effect on the next frame,
		 * then the last WDH could take 6+ msec
		 */
		ohci_dbg (ohci, "stopping schedules ...\n");
		limit = 2000;
		while (limit > 0) {
			udelay (250);
			limit =- 250;
			if (ohci_readl (ohci, &ohci->regs->intrstatus)
					& OHCI_INTR_SF)
				break;
		}
		dl_done_list (ohci, NULL);
		mdelay (7);
	}
	dl_done_list (ohci, NULL);
	finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
			&ohci->regs->intrstatus);

	/* maybe resume can wake root hub */
	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
		ohci->hc_control |= OHCI_CTRL_RWE;
	else
		ohci->hc_control &= ~OHCI_CTRL_RWE;

	/* Suspend hub ... this is the "global (to this bus) suspend" mode,
	 * which doesn't imply ports will first be individually suspended.
	 */
	ohci->hc_control &= ~OHCI_CTRL_HCFS;
	ohci->hc_control |= OHCI_USB_SUSPEND;
	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
	(void) ohci_readl (ohci, &ohci->regs->control);

	/* no resumes until devices finish suspending */
	ohci->next_statechange = jiffies + msecs_to_jiffies (5);

	/* no timer polling */
	hcd->poll_rh = 0;

done:
	/* external suspend vs self autosuspend ... same effect */
	if (status == 0)
		usb_hcd_suspend_root_hub(hcd);
	spin_unlock_irqrestore (&ohci->lock, flags);
	return status;
}
예제 #29
0
/* hcd->hub_irq_enable() */
static void ohci_rhsc_enable (struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);

	ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
}
예제 #30
0
/* caller has locked the root hub */
static int ohci_bus_resume (struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
	u32			temp, enables;
	int			status = -EINPROGRESS;
	unsigned long		flags;

	if (time_before (jiffies, ohci->next_statechange))
		msleep(5);

	spin_lock_irqsave (&ohci->lock, flags);

	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
		spin_unlock_irqrestore (&ohci->lock, flags);
		return -ESHUTDOWN;
	}


	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);

	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
		/* this can happen after resuming a swsusp snapshot */
		if (hcd->state == HC_STATE_RESUMING) {
			ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
					ohci->hc_control);
			status = -EBUSY;
		/* this happens when pmcore resumes HC then root */
		} else {
			ohci_dbg (ohci, "duplicate resume\n");
			status = 0;
		}
	} else switch (ohci->hc_control & OHCI_CTRL_HCFS) {
	case OHCI_USB_SUSPEND:
		ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
		ohci->hc_control |= OHCI_USB_RESUME;
		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
		(void) ohci_readl (ohci, &ohci->regs->control);
		ohci_dbg (ohci, "resume root hub\n");
		break;
	case OHCI_USB_RESUME:
		/* HCFS changes sometime after INTR_RD */
		ohci_info (ohci, "wakeup\n");
		break;
	case OHCI_USB_OPER:
		/* this can happen after resuming a swsusp snapshot */
		ohci_dbg (ohci, "snapshot resume? reinit\n");
		status = -EBUSY;
		break;
	default:		/* RESET, we lost power */
		ohci_dbg (ohci, "lost power\n");
		status = -EBUSY;
	}
	spin_unlock_irqrestore (&ohci->lock, flags);
	if (status == -EBUSY) {
		(void) ohci_init (ohci);
		return ohci_restart (ohci);
	}
	if (status != -EINPROGRESS)
		return status;

	temp = ohci->num_ports;
	enables = 0;
	while (temp--) {
		u32 stat = ohci_readl (ohci,
				       &ohci->regs->roothub.portstatus [temp]);

		/* force global, not selective, resume */
		if (!(stat & RH_PS_PSS))
			continue;
		ohci_writel (ohci, RH_PS_POCI,
				&ohci->regs->roothub.portstatus [temp]);
	}

	/* Some controllers (lucent erratum) need extra-long delays */
	msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);

	temp = ohci_readl (ohci, &ohci->regs->control);
	temp &= OHCI_CTRL_HCFS;
	if (temp != OHCI_USB_RESUME) {
		ohci_err (ohci, "controller won't resume\n");
		return -EBUSY;
	}

	/* disable old schedule state, reinit from scratch */
	ohci_writel (ohci, 0, &ohci->regs->ed_controlhead);
	ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent);
	ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead);
	ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent);
	ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent);
	ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);

	/* Sometimes PCI D3 suspend trashes frame timings ... */
	periodic_reinit (ohci);

	/* interrupts might have been disabled */
	ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
	if (ohci->ed_rm_list)
		ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
			&ohci->regs->intrstatus);

	/* Then re-enable operations */
	ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
	(void) ohci_readl (ohci, &ohci->regs->control);
	msleep (3);

	temp = ohci->hc_control;
	temp &= OHCI_CTRL_RWC;
	temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
	ohci->hc_control = temp;
	ohci_writel (ohci, temp, &ohci->regs->control);
	(void) ohci_readl (ohci, &ohci->regs->control);

	/* TRSMRCY */
	msleep (10);

	/* keep it alive for more than ~5x suspend + resume costs */
	ohci->next_statechange = jiffies + STATECHANGE_DELAY;

	/* maybe turn schedules back on */
	enables = 0;
	temp = 0;
	if (!ohci->ed_rm_list) {
		if (ohci->ed_controltail) {
			ohci_writel (ohci,
					find_head (ohci->ed_controltail)->dma,
					&ohci->regs->ed_controlhead);
			enables |= OHCI_CTRL_CLE;
			temp |= OHCI_CLF;
		}
		if (ohci->ed_bulktail) {
			ohci_writel (ohci, find_head (ohci->ed_bulktail)->dma,
				&ohci->regs->ed_bulkhead);
			enables |= OHCI_CTRL_BLE;
			temp |= OHCI_BLF;
		}
	}
	if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs)
		enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
	if (enables) {
		ohci_dbg (ohci, "restarting schedules ... %08x\n", enables);
		ohci->hc_control |= enables;
		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
		if (temp)
			ohci_writel (ohci, temp, &ohci->regs->cmdstatus);
		(void) ohci_readl (ohci, &ohci->regs->control);
	}

	return 0;
}