diff options
-rw-r--r-- | Documentation/devicetree/bindings/usb/ci13xxx-imx.txt | 5 | ||||
-rw-r--r-- | drivers/usb/chipidea/bits.h | 16 | ||||
-rw-r--r-- | drivers/usb/chipidea/core.c | 48 | ||||
-rw-r--r-- | include/linux/usb/chipidea.h | 1 |
4 files changed, 69 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt index 1c04a4c9515f..184a8e0f26dc 100644 --- a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt +++ b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt | |||
@@ -5,6 +5,11 @@ Required properties: | |||
5 | - reg: Should contain registers location and length | 5 | - reg: Should contain registers location and length |
6 | - interrupts: Should contain controller interrupt | 6 | - interrupts: Should contain controller interrupt |
7 | 7 | ||
8 | Recommended properies: | ||
9 | - phy_type: the type of the phy connected to the core. Should be one | ||
10 | of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this | ||
11 | property the PORTSC register won't be touched | ||
12 | |||
8 | Optional properties: | 13 | Optional properties: |
9 | - fsl,usbphy: phandler of usb phy that connects to the only one port | 14 | - fsl,usbphy: phandler of usb phy that connects to the only one port |
10 | - fsl,usbmisc: phandler of non-core register device, with one argument | 15 | - fsl,usbmisc: phandler of non-core register device, with one argument |
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h index 050de8562a04..aefa0261220c 100644 --- a/drivers/usb/chipidea/bits.h +++ b/drivers/usb/chipidea/bits.h | |||
@@ -48,10 +48,24 @@ | |||
48 | #define PORTSC_SUSP BIT(7) | 48 | #define PORTSC_SUSP BIT(7) |
49 | #define PORTSC_HSP BIT(9) | 49 | #define PORTSC_HSP BIT(9) |
50 | #define PORTSC_PTC (0x0FUL << 16) | 50 | #define PORTSC_PTC (0x0FUL << 16) |
51 | /* PTS and PTW for non lpm version only */ | ||
52 | #define PORTSC_PTS(d) \ | ||
53 | ((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0)) | ||
54 | #define PORTSC_PTW BIT(28) | ||
55 | #define PORTSC_STS BIT(29) | ||
51 | 56 | ||
52 | /* DEVLC */ | 57 | /* DEVLC */ |
53 | #define DEVLC_PSPD (0x03UL << 25) | 58 | #define DEVLC_PSPD (0x03UL << 25) |
54 | #define DEVLC_PSPD_HS (0x02UL << 25) | 59 | #define DEVLC_PSPD_HS (0x02UL << 25) |
60 | #define DEVLC_PTW BIT(27) | ||
61 | #define DEVLC_STS BIT(28) | ||
62 | #define DEVLC_PTS(d) (((d) & 0x7) << 29) | ||
63 | |||
64 | /* Encoding for DEVLC_PTS and PORTSC_PTS */ | ||
65 | #define PTS_UTMI 0 | ||
66 | #define PTS_ULPI 2 | ||
67 | #define PTS_SERIAL 3 | ||
68 | #define PTS_HSIC 4 | ||
55 | 69 | ||
56 | /* OTGSC */ | 70 | /* OTGSC */ |
57 | #define OTGSC_IDPU BIT(5) | 71 | #define OTGSC_IDPU BIT(5) |
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index a40e944401d2..a25f6b68550f 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -63,6 +63,8 @@ | |||
63 | #include <linux/usb/gadget.h> | 63 | #include <linux/usb/gadget.h> |
64 | #include <linux/usb/otg.h> | 64 | #include <linux/usb/otg.h> |
65 | #include <linux/usb/chipidea.h> | 65 | #include <linux/usb/chipidea.h> |
66 | #include <linux/usb/of.h> | ||
67 | #include <linux/phy.h> | ||
66 | 68 | ||
67 | #include "ci.h" | 69 | #include "ci.h" |
68 | #include "udc.h" | 70 | #include "udc.h" |
@@ -207,6 +209,45 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base) | |||
207 | return 0; | 209 | return 0; |
208 | } | 210 | } |
209 | 211 | ||
212 | static void hw_phymode_configure(struct ci13xxx *ci) | ||
213 | { | ||
214 | u32 portsc, lpm, sts; | ||
215 | |||
216 | switch (ci->platdata->phy_mode) { | ||
217 | case USBPHY_INTERFACE_MODE_UTMI: | ||
218 | portsc = PORTSC_PTS(PTS_UTMI); | ||
219 | lpm = DEVLC_PTS(PTS_UTMI); | ||
220 | break; | ||
221 | case USBPHY_INTERFACE_MODE_UTMIW: | ||
222 | portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW; | ||
223 | lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW; | ||
224 | break; | ||
225 | case USBPHY_INTERFACE_MODE_ULPI: | ||
226 | portsc = PORTSC_PTS(PTS_ULPI); | ||
227 | lpm = DEVLC_PTS(PTS_ULPI); | ||
228 | break; | ||
229 | case USBPHY_INTERFACE_MODE_SERIAL: | ||
230 | portsc = PORTSC_PTS(PTS_SERIAL); | ||
231 | lpm = DEVLC_PTS(PTS_SERIAL); | ||
232 | sts = 1; | ||
233 | break; | ||
234 | case USBPHY_INTERFACE_MODE_HSIC: | ||
235 | portsc = PORTSC_PTS(PTS_HSIC); | ||
236 | lpm = DEVLC_PTS(PTS_HSIC); | ||
237 | break; | ||
238 | default: | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | if (ci->hw_bank.lpm) { | ||
243 | hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm); | ||
244 | hw_write(ci, OP_DEVLC, DEVLC_STS, sts); | ||
245 | } else { | ||
246 | hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc); | ||
247 | hw_write(ci, OP_PORTSC, PORTSC_STS, sts); | ||
248 | } | ||
249 | } | ||
250 | |||
210 | /** | 251 | /** |
211 | * hw_device_reset: resets chip (execute without interruption) | 252 | * hw_device_reset: resets chip (execute without interruption) |
212 | * @ci: the controller | 253 | * @ci: the controller |
@@ -223,6 +264,7 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) | |||
223 | while (hw_read(ci, OP_USBCMD, USBCMD_RST)) | 264 | while (hw_read(ci, OP_USBCMD, USBCMD_RST)) |
224 | udelay(10); /* not RTOS friendly */ | 265 | udelay(10); /* not RTOS friendly */ |
225 | 266 | ||
267 | hw_phymode_configure(ci); | ||
226 | 268 | ||
227 | if (ci->platdata->notify_event) | 269 | if (ci->platdata->notify_event) |
228 | ci->platdata->notify_event(ci, | 270 | ci->platdata->notify_event(ci, |
@@ -369,6 +411,9 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
369 | return -ENODEV; | 411 | return -ENODEV; |
370 | } | 412 | } |
371 | 413 | ||
414 | if (!dev->of_node && dev->parent) | ||
415 | dev->of_node = dev->parent->of_node; | ||
416 | |||
372 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 417 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
373 | base = devm_ioremap_resource(dev, res); | 418 | base = devm_ioremap_resource(dev, res); |
374 | if (IS_ERR(base)) | 419 | if (IS_ERR(base)) |
@@ -408,6 +453,9 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
408 | return -ENODEV; | 453 | return -ENODEV; |
409 | } | 454 | } |
410 | 455 | ||
456 | if (!ci->platdata->phy_mode) | ||
457 | ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); | ||
458 | |||
411 | /* initialize role(s) before the interrupt is requested */ | 459 | /* initialize role(s) before the interrupt is requested */ |
412 | ret = ci_hdrc_host_init(ci); | 460 | ret = ci_hdrc_host_init(ci); |
413 | if (ret) | 461 | if (ret) |
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 544825dde823..1a2aa1848804 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h | |||
@@ -14,6 +14,7 @@ struct ci13xxx_platform_data { | |||
14 | uintptr_t capoffset; | 14 | uintptr_t capoffset; |
15 | unsigned power_budget; | 15 | unsigned power_budget; |
16 | struct usb_phy *phy; | 16 | struct usb_phy *phy; |
17 | enum usb_phy_interface phy_mode; | ||
17 | unsigned long flags; | 18 | unsigned long flags; |
18 | #define CI13XXX_REGS_SHARED BIT(0) | 19 | #define CI13XXX_REGS_SHARED BIT(0) |
19 | #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) | 20 | #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) |