USB: langwell: USB Client PHY low power mode setting

PHY low power mode setting with a static function

Signed-off-by: JiebingLi <jiebing.li@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
JiebingLi 2010-08-05 14:18:13 +01:00 committed by Greg Kroah-Hartman
parent 3eed298ffa
commit 513b91b688
1 changed files with 60 additions and 32 deletions

View File

@ -1159,11 +1159,37 @@ static int langwell_get_frame(struct usb_gadget *_gadget)
} }
/* enter or exit PHY low power state */
static void langwell_phy_low_power(struct langwell_udc *dev, bool flag)
{
u32 devlc;
u8 devlc_byte2;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
devlc = readl(&dev->op_regs->devlc);
dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
if (flag)
devlc |= LPM_PHCD;
else
devlc &= ~LPM_PHCD;
/* FIXME: workaround for Langwell A1/A2/A3 sighting */
devlc_byte2 = (devlc >> 16) & 0xff;
writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
devlc = readl(&dev->op_regs->devlc);
dev_vdbg(&dev->pdev->dev,
"%s PHY low power suspend, devlc = 0x%08x\n",
flag ? "enter" : "exit", devlc);
}
/* tries to wake up the host connected to this gadget */ /* tries to wake up the host connected to this gadget */
static int langwell_wakeup(struct usb_gadget *_gadget) static int langwell_wakeup(struct usb_gadget *_gadget)
{ {
struct langwell_udc *dev; struct langwell_udc *dev;
u32 portsc1, devlc; u32 portsc1;
unsigned long flags; unsigned long flags;
if (!_gadget) if (!_gadget)
@ -1186,22 +1212,19 @@ static int langwell_wakeup(struct usb_gadget *_gadget)
return 0; return 0;
} }
/* LPM L1 to L0, remote wakeup */ /* LPM L1 to L0 or legacy remote wakeup */
if (dev->lpm && dev->lpm_state == LPM_L1) { if (dev->lpm && dev->lpm_state == LPM_L1)
portsc1 |= PORTS_SLP; dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n");
writel(portsc1, &dev->op_regs->portsc1); else
} dev_info(&dev->pdev->dev, "device remote wakeup\n");
/* force port resume */
if (dev->usb_state == USB_STATE_SUSPENDED) {
portsc1 |= PORTS_FPR;
writel(portsc1, &dev->op_regs->portsc1);
}
/* exit PHY low power suspend */ /* exit PHY low power suspend */
devlc = readl(&dev->op_regs->devlc); if (dev->pdev->device != 0x0829)
devlc &= ~LPM_PHCD; langwell_phy_low_power(dev, 0);
writel(devlc, &dev->op_regs->devlc);
/* force port resume */
portsc1 |= PORTS_FPR;
writel(portsc1, &dev->op_regs->portsc1);
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
@ -1331,6 +1354,7 @@ static const struct usb_gadget_ops langwell_ops = {
static int langwell_udc_reset(struct langwell_udc *dev) static int langwell_udc_reset(struct langwell_udc *dev)
{ {
u32 usbcmd, usbmode, devlc, endpointlistaddr; u32 usbcmd, usbmode, devlc, endpointlistaddr;
u8 devlc_byte0, devlc_byte2;
unsigned long timeout; unsigned long timeout;
if (!dev) if (!dev)
@ -1375,9 +1399,17 @@ static int langwell_udc_reset(struct langwell_udc *dev)
/* if support USB LPM, ACK all LPM token */ /* if support USB LPM, ACK all LPM token */
if (dev->lpm) { if (dev->lpm) {
devlc = readl(&dev->op_regs->devlc); devlc = readl(&dev->op_regs->devlc);
dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
/* FIXME: workaround for Langwell A1/A2/A3 sighting */
devlc &= ~LPM_STL; /* don't STALL LPM token */ devlc &= ~LPM_STL; /* don't STALL LPM token */
devlc &= ~LPM_NYT_ACK; /* ACK LPM token */ devlc &= ~LPM_NYT_ACK; /* ACK LPM token */
writel(devlc, &dev->op_regs->devlc); devlc_byte0 = devlc & 0xff;
devlc_byte2 = (devlc >> 16) & 0xff;
writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc);
writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
devlc = readl(&dev->op_regs->devlc);
dev_vdbg(&dev->pdev->dev,
"ACK LPM token, devlc = 0x%08x\n", devlc);
} }
/* fill endpointlistaddr register */ /* fill endpointlistaddr register */
@ -1871,6 +1903,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (unlikely(!driver || !driver->bind || !driver->unbind)) if (unlikely(!driver || !driver->bind || !driver->unbind))
return -EINVAL; return -EINVAL;
/* exit PHY low power suspend */
if (dev->pdev->device != 0x0829)
langwell_phy_low_power(dev, 0);
/* unbind OTG transceiver */ /* unbind OTG transceiver */
if (dev->transceiver) if (dev->transceiver)
(void)otg_set_peripheral(dev->transceiver, 0); (void)otg_set_peripheral(dev->transceiver, 0);
@ -2706,7 +2742,6 @@ static void handle_usb_reset(struct langwell_udc *dev)
/* USB bus suspend/resume interrupt */ /* USB bus suspend/resume interrupt */
static void handle_bus_suspend(struct langwell_udc *dev) static void handle_bus_suspend(struct langwell_udc *dev)
{ {
u32 devlc;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
dev->resume_state = dev->usb_state; dev->resume_state = dev->usb_state;
@ -2747,9 +2782,8 @@ static void handle_bus_suspend(struct langwell_udc *dev)
} }
/* enter PHY low power suspend */ /* enter PHY low power suspend */
devlc = readl(&dev->op_regs->devlc); if (dev->pdev->device != 0x0829)
devlc |= LPM_PHCD; langwell_phy_low_power(dev, 0);
writel(devlc, &dev->op_regs->devlc);
dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
} }
@ -2757,16 +2791,14 @@ static void handle_bus_suspend(struct langwell_udc *dev)
static void handle_bus_resume(struct langwell_udc *dev) static void handle_bus_resume(struct langwell_udc *dev)
{ {
u32 devlc;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
dev->usb_state = dev->resume_state; dev->usb_state = dev->resume_state;
dev->resume_state = 0; dev->resume_state = 0;
/* exit PHY low power suspend */ /* exit PHY low power suspend */
devlc = readl(&dev->op_regs->devlc); if (dev->pdev->device != 0x0829)
devlc &= ~LPM_PHCD; langwell_phy_low_power(dev, 0);
writel(devlc, &dev->op_regs->devlc);
#ifdef OTG_TRANSCEIVER #ifdef OTG_TRANSCEIVER
if (dev->lotg->otg.default_a == 0) if (dev->lotg->otg.default_a == 0)
@ -3232,7 +3264,6 @@ error:
static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct langwell_udc *dev = the_controller; struct langwell_udc *dev = the_controller;
u32 devlc;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
@ -3251,9 +3282,8 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
pci_set_power_state(pdev, PCI_D3hot); pci_set_power_state(pdev, PCI_D3hot);
/* enter PHY low power suspend */ /* enter PHY low power suspend */
devlc = readl(&dev->op_regs->devlc); if (dev->pdev->device != 0x0829)
devlc |= LPM_PHCD; langwell_phy_low_power(dev, 1);
writel(devlc, &dev->op_regs->devlc);
dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
return 0; return 0;
@ -3264,14 +3294,12 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
static int langwell_udc_resume(struct pci_dev *pdev) static int langwell_udc_resume(struct pci_dev *pdev)
{ {
struct langwell_udc *dev = the_controller; struct langwell_udc *dev = the_controller;
u32 devlc;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
/* exit PHY low power suspend */ /* exit PHY low power suspend */
devlc = readl(&dev->op_regs->devlc); if (dev->pdev->device != 0x0829)
devlc &= ~LPM_PHCD; langwell_phy_low_power(dev, 0);
writel(devlc, &dev->op_regs->devlc);
/* set device D0 power state */ /* set device D0 power state */
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);