Skip to content

Commit

Permalink
usb: chipidea: add PTW, PTS and STS handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael Grzeschik authored and Greg Kroah-Hartman committed Jun 17, 2013
1 parent 1c9af65 commit 40dcd0e
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ Required properties:
- reg: Should contain registers location and length
- interrupts: Should contain controller interrupt

Recommended properies:
- phy_type: the type of the phy connected to the core. Should be one
of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this
property the PORTSC register won't be touched

Optional properties:
- fsl,usbphy: phandler of usb phy that connects to the only one port
- fsl,usbmisc: phandler of non-core register device, with one argument
Expand Down
16 changes: 15 additions & 1 deletion drivers/usb/chipidea/bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,24 @@
#define PORTSC_SUSP BIT(7)
#define PORTSC_HSP BIT(9)
#define PORTSC_PTC (0x0FUL << 16)
/* PTS and PTW for non lpm version only */
#define PORTSC_PTS(d) \
((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0))
#define PORTSC_PTW BIT(28)
#define PORTSC_STS BIT(29)

/* DEVLC */
#define DEVLC_PSPD (0x03UL << 25)
#define DEVLC_PSPD_HS (0x02UL << 25)
#define DEVLC_PSPD_HS (0x02UL << 25)
#define DEVLC_PTW BIT(27)
#define DEVLC_STS BIT(28)
#define DEVLC_PTS(d) (((d) & 0x7) << 29)

/* Encoding for DEVLC_PTS and PORTSC_PTS */
#define PTS_UTMI 0
#define PTS_ULPI 2
#define PTS_SERIAL 3
#define PTS_HSIC 4

/* OTGSC */
#define OTGSC_IDPU BIT(5)
Expand Down
48 changes: 48 additions & 0 deletions drivers/usb/chipidea/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/usb/chipidea.h>
#include <linux/usb/of.h>
#include <linux/phy.h>

#include "ci.h"
#include "udc.h"
Expand Down Expand Up @@ -207,6 +209,45 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
return 0;
}

static void hw_phymode_configure(struct ci13xxx *ci)
{
u32 portsc, lpm, sts;

switch (ci->platdata->phy_mode) {
case USBPHY_INTERFACE_MODE_UTMI:
portsc = PORTSC_PTS(PTS_UTMI);
lpm = DEVLC_PTS(PTS_UTMI);
break;
case USBPHY_INTERFACE_MODE_UTMIW:
portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW;
lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW;
break;
case USBPHY_INTERFACE_MODE_ULPI:
portsc = PORTSC_PTS(PTS_ULPI);
lpm = DEVLC_PTS(PTS_ULPI);
break;
case USBPHY_INTERFACE_MODE_SERIAL:
portsc = PORTSC_PTS(PTS_SERIAL);
lpm = DEVLC_PTS(PTS_SERIAL);
sts = 1;
break;
case USBPHY_INTERFACE_MODE_HSIC:
portsc = PORTSC_PTS(PTS_HSIC);
lpm = DEVLC_PTS(PTS_HSIC);
break;
default:
return;
}

if (ci->hw_bank.lpm) {
hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm);
hw_write(ci, OP_DEVLC, DEVLC_STS, sts);
} else {
hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc);
hw_write(ci, OP_PORTSC, PORTSC_STS, sts);
}
}

/**
* hw_device_reset: resets chip (execute without interruption)
* @ci: the controller
Expand All @@ -223,6 +264,7 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
while (hw_read(ci, OP_USBCMD, USBCMD_RST))
udelay(10); /* not RTOS friendly */

hw_phymode_configure(ci);

if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
Expand Down Expand Up @@ -369,6 +411,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}

if (!dev->of_node && dev->parent)
dev->of_node = dev->parent->of_node;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
Expand Down Expand Up @@ -408,6 +453,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}

if (!ci->platdata->phy_mode)
ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);

/* initialize role(s) before the interrupt is requested */
ret = ci_hdrc_host_init(ci);
if (ret)
Expand Down
1 change: 1 addition & 0 deletions include/linux/usb/chipidea.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct ci13xxx_platform_data {
uintptr_t capoffset;
unsigned power_budget;
struct usb_phy *phy;
enum usb_phy_interface phy_mode;
unsigned long flags;
#define CI13XXX_REGS_SHARED BIT(0)
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
Expand Down

0 comments on commit 40dcd0e

Please sign in to comment.