aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Grzeschik <m.grzeschik@pengutronix.de>2013-06-13 10:59:56 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-17 16:47:09 -0400
commit40dcd0e8067b35e247f74409d79443634daf35ac (patch)
tree91b9e6678ad1b2bd72e45d3e35a9266aaefa016f
parent1c9af65357a309b60d78a442bd61d27cad458d00 (diff)
usb: chipidea: add PTW, PTS and STS handling
This patch makes it possible to configure the PTW, PTS and STS bits inside the portsc register for host and device mode before the driver starts and the phy can be addressed as hardware implementation is designed. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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)