diff options
author | JiebingLi <jiebing.li@intel.com> | 2010-08-05 09:18:13 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:21:18 -0400 |
commit | 513b91b688f527766bfe335d1ffd145257ad1624 (patch) | |
tree | de2ee7aeb2a4fa62f27ec09d4d6213b654461d5a /drivers | |
parent | 3eed298ffa94d77901cfda269c4368de83d133fb (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/langwell_udc.c | 92 |
1 files changed, 60 insertions, 32 deletions
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 599ad8a1f5fe..8b92e2208dad 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c | |||
@@ -1159,11 +1159,37 @@ static int langwell_get_frame(struct usb_gadget *_gadget) | |||
1159 | } | 1159 | } |
1160 | 1160 | ||
1161 | 1161 | ||
1162 | /* enter or exit PHY low power state */ | ||
1163 | static void langwell_phy_low_power(struct langwell_udc *dev, bool flag) | ||
1164 | { | ||
1165 | u32 devlc; | ||
1166 | u8 devlc_byte2; | ||
1167 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | ||
1168 | |||
1169 | devlc = readl(&dev->op_regs->devlc); | ||
1170 | dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); | ||
1171 | |||
1172 | if (flag) | ||
1173 | devlc |= LPM_PHCD; | ||
1174 | else | ||
1175 | devlc &= ~LPM_PHCD; | ||
1176 | |||
1177 | /* FIXME: workaround for Langwell A1/A2/A3 sighting */ | ||
1178 | devlc_byte2 = (devlc >> 16) & 0xff; | ||
1179 | writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); | ||
1180 | |||
1181 | devlc = readl(&dev->op_regs->devlc); | ||
1182 | dev_vdbg(&dev->pdev->dev, | ||
1183 | "%s PHY low power suspend, devlc = 0x%08x\n", | ||
1184 | flag ? "enter" : "exit", devlc); | ||
1185 | } | ||
1186 | |||
1187 | |||
1162 | /* tries to wake up the host connected to this gadget */ | 1188 | /* tries to wake up the host connected to this gadget */ |
1163 | static int langwell_wakeup(struct usb_gadget *_gadget) | 1189 | static int langwell_wakeup(struct usb_gadget *_gadget) |
1164 | { | 1190 | { |
1165 | struct langwell_udc *dev; | 1191 | struct langwell_udc *dev; |
1166 | u32 portsc1, devlc; | 1192 | u32 portsc1; |
1167 | unsigned long flags; | 1193 | unsigned long flags; |
1168 | 1194 | ||
1169 | if (!_gadget) | 1195 | if (!_gadget) |
@@ -1186,22 +1212,19 @@ static int langwell_wakeup(struct usb_gadget *_gadget) | |||
1186 | return 0; | 1212 | return 0; |
1187 | } | 1213 | } |
1188 | 1214 | ||
1189 | /* LPM L1 to L0, remote wakeup */ | 1215 | /* LPM L1 to L0 or legacy remote wakeup */ |
1190 | if (dev->lpm && dev->lpm_state == LPM_L1) { | 1216 | if (dev->lpm && dev->lpm_state == LPM_L1) |
1191 | portsc1 |= PORTS_SLP; | 1217 | dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n"); |
1192 | writel(portsc1, &dev->op_regs->portsc1); | 1218 | else |
1193 | } | 1219 | dev_info(&dev->pdev->dev, "device remote wakeup\n"); |
1194 | |||
1195 | /* force port resume */ | ||
1196 | if (dev->usb_state == USB_STATE_SUSPENDED) { | ||
1197 | portsc1 |= PORTS_FPR; | ||
1198 | writel(portsc1, &dev->op_regs->portsc1); | ||
1199 | } | ||
1200 | 1220 | ||
1201 | /* exit PHY low power suspend */ | 1221 | /* exit PHY low power suspend */ |
1202 | devlc = readl(&dev->op_regs->devlc); | 1222 | if (dev->pdev->device != 0x0829) |
1203 | devlc &= ~LPM_PHCD; | 1223 | langwell_phy_low_power(dev, 0); |
1204 | writel(devlc, &dev->op_regs->devlc); | 1224 | |
1225 | /* force port resume */ | ||
1226 | portsc1 |= PORTS_FPR; | ||
1227 | writel(portsc1, &dev->op_regs->portsc1); | ||
1205 | 1228 | ||
1206 | spin_unlock_irqrestore(&dev->lock, flags); | 1229 | spin_unlock_irqrestore(&dev->lock, flags); |
1207 | 1230 | ||
@@ -1331,6 +1354,7 @@ static const struct usb_gadget_ops langwell_ops = { | |||
1331 | static int langwell_udc_reset(struct langwell_udc *dev) | 1354 | static int langwell_udc_reset(struct langwell_udc *dev) |
1332 | { | 1355 | { |
1333 | u32 usbcmd, usbmode, devlc, endpointlistaddr; | 1356 | u32 usbcmd, usbmode, devlc, endpointlistaddr; |
1357 | u8 devlc_byte0, devlc_byte2; | ||
1334 | unsigned long timeout; | 1358 | unsigned long timeout; |
1335 | 1359 | ||
1336 | if (!dev) | 1360 | if (!dev) |
@@ -1375,9 +1399,17 @@ static int langwell_udc_reset(struct langwell_udc *dev) | |||
1375 | /* if support USB LPM, ACK all LPM token */ | 1399 | /* if support USB LPM, ACK all LPM token */ |
1376 | if (dev->lpm) { | 1400 | if (dev->lpm) { |
1377 | devlc = readl(&dev->op_regs->devlc); | 1401 | devlc = readl(&dev->op_regs->devlc); |
1402 | dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); | ||
1403 | /* FIXME: workaround for Langwell A1/A2/A3 sighting */ | ||
1378 | devlc &= ~LPM_STL; /* don't STALL LPM token */ | 1404 | devlc &= ~LPM_STL; /* don't STALL LPM token */ |
1379 | devlc &= ~LPM_NYT_ACK; /* ACK LPM token */ | 1405 | devlc &= ~LPM_NYT_ACK; /* ACK LPM token */ |
1380 | writel(devlc, &dev->op_regs->devlc); | 1406 | devlc_byte0 = devlc & 0xff; |
1407 | devlc_byte2 = (devlc >> 16) & 0xff; | ||
1408 | writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc); | ||
1409 | writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); | ||
1410 | devlc = readl(&dev->op_regs->devlc); | ||
1411 | dev_vdbg(&dev->pdev->dev, | ||
1412 | "ACK LPM token, devlc = 0x%08x\n", devlc); | ||
1381 | } | 1413 | } |
1382 | 1414 | ||
1383 | /* fill endpointlistaddr register */ | 1415 | /* fill endpointlistaddr register */ |
@@ -1871,6 +1903,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1871 | if (unlikely(!driver || !driver->bind || !driver->unbind)) | 1903 | if (unlikely(!driver || !driver->bind || !driver->unbind)) |
1872 | return -EINVAL; | 1904 | return -EINVAL; |
1873 | 1905 | ||
1906 | /* exit PHY low power suspend */ | ||
1907 | if (dev->pdev->device != 0x0829) | ||
1908 | langwell_phy_low_power(dev, 0); | ||
1909 | |||
1874 | /* unbind OTG transceiver */ | 1910 | /* unbind OTG transceiver */ |
1875 | if (dev->transceiver) | 1911 | if (dev->transceiver) |
1876 | (void)otg_set_peripheral(dev->transceiver, 0); | 1912 | (void)otg_set_peripheral(dev->transceiver, 0); |
@@ -2706,7 +2742,6 @@ static void handle_usb_reset(struct langwell_udc *dev) | |||
2706 | /* USB bus suspend/resume interrupt */ | 2742 | /* USB bus suspend/resume interrupt */ |
2707 | static void handle_bus_suspend(struct langwell_udc *dev) | 2743 | static void handle_bus_suspend(struct langwell_udc *dev) |
2708 | { | 2744 | { |
2709 | u32 devlc; | ||
2710 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | 2745 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
2711 | 2746 | ||
2712 | dev->resume_state = dev->usb_state; | 2747 | dev->resume_state = dev->usb_state; |
@@ -2747,9 +2782,8 @@ static void handle_bus_suspend(struct langwell_udc *dev) | |||
2747 | } | 2782 | } |
2748 | 2783 | ||
2749 | /* enter PHY low power suspend */ | 2784 | /* enter PHY low power suspend */ |
2750 | devlc = readl(&dev->op_regs->devlc); | 2785 | if (dev->pdev->device != 0x0829) |
2751 | devlc |= LPM_PHCD; | 2786 | langwell_phy_low_power(dev, 0); |
2752 | writel(devlc, &dev->op_regs->devlc); | ||
2753 | 2787 | ||
2754 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | 2788 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); |
2755 | } | 2789 | } |
@@ -2757,16 +2791,14 @@ static void handle_bus_suspend(struct langwell_udc *dev) | |||
2757 | 2791 | ||
2758 | static void handle_bus_resume(struct langwell_udc *dev) | 2792 | static void handle_bus_resume(struct langwell_udc *dev) |
2759 | { | 2793 | { |
2760 | u32 devlc; | ||
2761 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | 2794 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
2762 | 2795 | ||
2763 | dev->usb_state = dev->resume_state; | 2796 | dev->usb_state = dev->resume_state; |
2764 | dev->resume_state = 0; | 2797 | dev->resume_state = 0; |
2765 | 2798 | ||
2766 | /* exit PHY low power suspend */ | 2799 | /* exit PHY low power suspend */ |
2767 | devlc = readl(&dev->op_regs->devlc); | 2800 | if (dev->pdev->device != 0x0829) |
2768 | devlc &= ~LPM_PHCD; | 2801 | langwell_phy_low_power(dev, 0); |
2769 | writel(devlc, &dev->op_regs->devlc); | ||
2770 | 2802 | ||
2771 | #ifdef OTG_TRANSCEIVER | 2803 | #ifdef OTG_TRANSCEIVER |
2772 | if (dev->lotg->otg.default_a == 0) | 2804 | if (dev->lotg->otg.default_a == 0) |
@@ -3232,7 +3264,6 @@ error: | |||
3232 | static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) | 3264 | static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) |
3233 | { | 3265 | { |
3234 | struct langwell_udc *dev = the_controller; | 3266 | struct langwell_udc *dev = the_controller; |
3235 | u32 devlc; | ||
3236 | 3267 | ||
3237 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | 3268 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
3238 | 3269 | ||
@@ -3251,9 +3282,8 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3251 | pci_set_power_state(pdev, PCI_D3hot); | 3282 | pci_set_power_state(pdev, PCI_D3hot); |
3252 | 3283 | ||
3253 | /* enter PHY low power suspend */ | 3284 | /* enter PHY low power suspend */ |
3254 | devlc = readl(&dev->op_regs->devlc); | 3285 | if (dev->pdev->device != 0x0829) |
3255 | devlc |= LPM_PHCD; | 3286 | langwell_phy_low_power(dev, 1); |
3256 | writel(devlc, &dev->op_regs->devlc); | ||
3257 | 3287 | ||
3258 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); | 3288 | dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); |
3259 | return 0; | 3289 | return 0; |
@@ -3264,14 +3294,12 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3264 | static int langwell_udc_resume(struct pci_dev *pdev) | 3294 | static int langwell_udc_resume(struct pci_dev *pdev) |
3265 | { | 3295 | { |
3266 | struct langwell_udc *dev = the_controller; | 3296 | struct langwell_udc *dev = the_controller; |
3267 | u32 devlc; | ||
3268 | 3297 | ||
3269 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); | 3298 | dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); |
3270 | 3299 | ||
3271 | /* exit PHY low power suspend */ | 3300 | /* exit PHY low power suspend */ |
3272 | devlc = readl(&dev->op_regs->devlc); | 3301 | if (dev->pdev->device != 0x0829) |
3273 | devlc &= ~LPM_PHCD; | 3302 | langwell_phy_low_power(dev, 0); |
3274 | writel(devlc, &dev->op_regs->devlc); | ||
3275 | 3303 | ||
3276 | /* set device D0 power state */ | 3304 | /* set device D0 power state */ |
3277 | pci_set_power_state(pdev, PCI_D0); | 3305 | pci_set_power_state(pdev, PCI_D0); |