summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-11-20 10:00:04 +0100
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-11-20 10:00:04 +0100
commita39ae1c004b797d5047f97914a288d106121a10f (patch)
tree3bf35be86d5f61dd63eb5d89b064ed05fa83c314 /drivers
parentb7e977a36ee2b1ab1a55238761fe8d63df9bc638 (diff)
colibri_t20: USB: allow forcing full speed only
Allow limiting externally accessible USB OTG and host port to full speed only in order to be compatible with older carrier boards (e.g. old Colibri Evaluation Board v2.1c, Orchid or Protea). The following kernel argument can be set to either 0 meaning false or 1 meaning true: usb_high_speed
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/tegra_udc.c15
-rw-r--r--drivers/usb/host/ehci-tegra.c40
2 files changed, 55 insertions, 0 deletions
diff --git a/drivers/usb/gadget/tegra_udc.c b/drivers/usb/gadget/tegra_udc.c
index ddf9c602dc89..1dd2cceb741b 100644
--- a/drivers/usb/gadget/tegra_udc.c
+++ b/drivers/usb/gadget/tegra_udc.c
@@ -94,6 +94,11 @@ static const u8 tegra_udc_test_packet[53] = {
0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e
};
+#ifdef CONFIG_MACH_COLIBRI_T20
+/* To limit the speed of USB to full speed */
+extern int g_usb_high_speed;
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
static struct tegra_udc *the_udc;
#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
@@ -252,6 +257,16 @@ static int dr_controller_reset(struct tegra_udc *udc)
cpu_relax();
}
+#ifdef CONFIG_MACH_COLIBRI_T20
+ /* To limit the speed of USB to full speed */
+ if (!g_usb_high_speed) {
+ tmp = udc_readl(udc, PORTSCX_REG_OFFSET);
+ tmp |= PORTSCX_PORT_FORCE_FULL_SPEED;
+ udc_writel(udc, tmp, PORTSCX_REG_OFFSET);
+ tmp = udc_readl(udc, PORTSCX_REG_OFFSET);
+ }
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
DBG("%s(%d) END\n", __func__, __LINE__);
return 0;
}
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 1800a38f48ec..f183349fd8d1 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -31,6 +31,8 @@
#define EHCI_DBG(stuff...) do {} while (0)
#endif
+#define TEGRA_USB_PORTSC1_PFSC (1 << 24)
+
static const char driver_name[] = "tegra-ehci";
#define TEGRA_USB_DMA_ALIGN 32
@@ -53,6 +55,21 @@ struct dma_align_buffer {
u8 data[0];
};
+#ifdef CONFIG_MACH_COLIBRI_T20
+/* To limit the speed of USB to full speed */
+int g_usb_high_speed = 0;
+
+/* To limit the speed of USB to full speed */
+static int __init enable_usb_high_speed(char *s)
+{
+ if (!(*s) || !strcmp(s, "1"))
+ g_usb_high_speed = 1;
+
+ return 0;
+}
+__setup("usb_high_speed=", enable_usb_high_speed);
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
static void free_align_buffer(struct urb *urb)
{
struct dma_align_buffer *temp = container_of(urb->transfer_buffer,
@@ -268,6 +285,29 @@ static int tegra_ehci_hub_control(
int retval = 0;
u32 __iomem *status_reg;
+#ifdef CONFIG_MACH_COLIBRI_T20
+ u32 temp;
+
+ /* To limit the speed of USB to full speed */
+ if (!g_usb_high_speed) {
+ /* Check whether port is not 2nd one internally connected to
+ ASIX Ethernet chip, set PFSC (Port Force Full Speed) only
+ for externally accessible OTG and host port */
+ if (tegra->phy->inst != 1) {
+ status_reg = &ehci->regs->port_status[(wIndex & 0xff)
+ - 1];
+ temp = ehci_readl(ehci, status_reg);
+ /* Check whether PFSC bit is already set or not */
+ if (!(temp & TEGRA_USB_PORTSC1_PFSC)) {
+ ehci_writel(ehci, (temp |
+ TEGRA_USB_PORTSC1_PFSC),
+ status_reg);
+ temp = ehci_readl(ehci, status_reg);
+ }
+ }
+ }
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
if (!tegra_usb_phy_hw_accessible(tegra->phy)) {
if (buf)
memset(buf, 0, wLength);