aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/usb/ci13xxx-imx.txt5
-rw-r--r--drivers/usb/chipidea/bits.h16
-rw-r--r--drivers/usb/chipidea/core.c48
-rw-r--r--include/linux/usb/chipidea.h1
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
8Recommended 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
8Optional properties: 13Optional 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
212static 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)