summaryrefslogtreecommitdiff
path: root/arch/arm/plat-omap/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/usb.c')
-rw-r--r--arch/arm/plat-omap/usb.c199
1 files changed, 159 insertions, 40 deletions
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 7e8096809be2..25489aafb113 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -37,9 +37,27 @@
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
+#ifdef CONFIG_ARCH_OMAP1
+
+#define INT_USB_IRQ_GEN IH2_BASE + 20
+#define INT_USB_IRQ_NISO IH2_BASE + 30
+#define INT_USB_IRQ_ISO IH2_BASE + 29
+#define INT_USB_IRQ_HGEN INT_USB_HHC_1
+#define INT_USB_IRQ_OTG IH2_BASE + 8
+
+#else
+
+#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN
+#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO
+#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO
+#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN
+#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG
+
+#endif
+
+
/* These routines should handle the standard chip-specific modes
* for usb0/1/2 ports, covering basic mux and transceiver setup.
- * Call omap_usb_init() once, from INIT_MACHINE().
*
* Some board-*.c files will need to set up additional mux options,
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
@@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
{
u32 syscon1 = 0;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL);
+
if (nwires == 0) {
- if (!cpu_is_omap15xx()) {
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
/* pulldown D+/D- */
USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
}
return 0;
}
- if (is_device)
- omap_cfg_reg(W4_USB_PUEN);
+ if (is_device) {
+ if (cpu_is_omap24xx())
+ omap_cfg_reg(J20_24XX_USB0_PUEN);
+ else
+ omap_cfg_reg(W4_USB_PUEN);
+ }
- /* internal transceiver */
- if (nwires == 2) {
+ /* internal transceiver (unavailable on 17xx, 24xx) */
+ if (!cpu_class_is_omap2() && nwires == 2) {
// omap_cfg_reg(P9_USB_DP);
// omap_cfg_reg(R8_USB_DM);
@@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
return 0;
}
- omap_cfg_reg(V6_USB0_TXD);
- omap_cfg_reg(W9_USB0_TXEN);
- omap_cfg_reg(W5_USB0_SE0);
+ if (cpu_is_omap24xx()) {
+ omap_cfg_reg(K18_24XX_USB0_DAT);
+ omap_cfg_reg(K19_24XX_USB0_TXEN);
+ omap_cfg_reg(J14_24XX_USB0_SE0);
+ if (nwires != 3)
+ omap_cfg_reg(J18_24XX_USB0_RCV);
+ } else {
+ omap_cfg_reg(V6_USB0_TXD);
+ omap_cfg_reg(W9_USB0_TXEN);
+ omap_cfg_reg(W5_USB0_SE0);
+ if (nwires != 3)
+ omap_cfg_reg(Y5_USB0_RCV);
+ }
- /* NOTE: SPEED and SUSP aren't configured here */
+ /* NOTE: SPEED and SUSP aren't configured here. OTG hosts
+ * may be able to use I2C requests to set those bits along
+ * with VBUS switching and overcurrent detction.
+ */
- if (nwires != 3)
- omap_cfg_reg(Y5_USB0_RCV);
- if (nwires != 6)
+ if (cpu_class_is_omap1() && nwires != 6)
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
switch (nwires) {
case 3:
syscon1 = 2;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
break;
case 4:
syscon1 = 1;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
break;
case 6:
syscon1 = 3;
- omap_cfg_reg(AA9_USB0_VP);
- omap_cfg_reg(R9_USB0_VM);
- USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+ if (cpu_is_omap24xx()) {
+ omap_cfg_reg(J19_24XX_USB0_VP);
+ omap_cfg_reg(K20_24XX_USB0_VM);
+ CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR);
+ } else {
+ omap_cfg_reg(AA9_USB0_VP);
+ omap_cfg_reg(R9_USB0_VM);
+ USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+ }
break;
default:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
@@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires)
{
u32 syscon1 = 0;
- if (nwires != 6 && !cpu_is_omap15xx())
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL);
+
if (nwires == 0)
return 0;
/* external transceiver */
- omap_cfg_reg(USB1_TXD);
- omap_cfg_reg(USB1_TXEN);
+ if (cpu_class_is_omap1()) {
+ omap_cfg_reg(USB1_TXD);
+ omap_cfg_reg(USB1_TXEN);
+ if (nwires != 3)
+ omap_cfg_reg(USB1_RCV);
+ }
+
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB1_SEO);
omap_cfg_reg(USB1_SPEED);
@@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires)
} else if (cpu_is_omap1710()) {
omap_cfg_reg(R13_1710_USB1_SE0);
// SUSP
+ } else if (cpu_is_omap24xx()) {
+ /* NOTE: board-specific code must set up pin muxing for usb1,
+ * since each signal could come out on either of two balls.
+ */
} else {
- pr_debug("usb unrecognized\n");
+ pr_debug("usb%d cpu unrecognized\n", 1);
+ return 0;
}
- if (nwires != 3)
- omap_cfg_reg(USB1_RCV);
switch (nwires) {
+ case 2:
+ if (!cpu_is_omap24xx())
+ goto bad;
+ /* NOTE: board-specific code must override this setting if
+ * this TLL link is not using DP/DM
+ */
+ syscon1 = 1;
+ CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL);
+ break;
case 3:
syscon1 = 2;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
break;
case 4:
syscon1 = 1;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
break;
case 6:
+ if (cpu_is_omap24xx())
+ goto bad;
syscon1 = 3;
omap_cfg_reg(USB1_VP);
omap_cfg_reg(USB1_VM);
@@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires)
USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
break;
default:
+bad:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
1, nwires);
}
@@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
{
u32 syscon1 = 0;
- /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */
+ if (cpu_is_omap24xx()) {
+ CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL)
+ | USBT2TLL5PI);
+ alt_pingroup = 0;
+ }
+
+ /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */
if (alt_pingroup || nwires == 0)
return 0;
- if (nwires != 6 && !cpu_is_omap15xx())
+
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
/* external transceiver */
@@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
if (nwires != 3)
omap_cfg_reg(Y5_USB2_RCV);
// FIXME omap_cfg_reg(USB2_SPEED);
+ } else if (cpu_is_omap24xx()) {
+ omap_cfg_reg(Y11_24XX_USB2_DAT);
+ omap_cfg_reg(AA10_24XX_USB2_SE0);
+ if (nwires > 2)
+ omap_cfg_reg(AA12_24XX_USB2_TXEN);
+ if (nwires > 3)
+ omap_cfg_reg(AA6_24XX_USB2_RCV);
} else {
- pr_debug("usb unrecognized\n");
+ pr_debug("usb%d cpu unrecognized\n", 1);
+ return 0;
}
- // omap_cfg_reg(USB2_SUSP);
+ // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP);
switch (nwires) {
+ case 2:
+ if (!cpu_is_omap24xx())
+ goto bad;
+ /* NOTE: board-specific code must override this setting if
+ * this TLL link is not using DP/DM
+ */
+ syscon1 = 1;
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL);
+ break;
case 3:
syscon1 = 2;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
break;
case 4:
syscon1 = 1;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
+ break;
+ case 5:
+ if (!cpu_is_omap24xx())
+ goto bad;
+ omap_cfg_reg(AA4_24XX_USB2_TLLSE0);
+ /* NOTE: board-specific code must override this setting if
+ * this TLL link is not using DP/DM. Something must also
+ * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED}
+ */
+ syscon1 = 3;
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL)
+ | USBT2TLL5PI;
break;
case 6:
+ if (cpu_is_omap24xx())
+ goto bad;
syscon1 = 3;
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB2_VP);
@@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
}
break;
default:
+bad:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
2, nwires);
}
@@ -294,13 +410,13 @@ static struct resource udc_resources[] = {
.end = UDC_BASE + 0xff,
.flags = IORESOURCE_MEM,
}, { /* general IRQ */
- .start = IH2_BASE + 20,
+ .start = INT_USB_IRQ_GEN,
.flags = IORESOURCE_IRQ,
}, { /* PIO IRQ */
- .start = IH2_BASE + 30,
+ .start = INT_USB_IRQ_NISO,
.flags = IORESOURCE_IRQ,
}, { /* SOF IRQ */
- .start = IH2_BASE + 29,
+ .start = INT_USB_IRQ_ISO,
.flags = IORESOURCE_IRQ,
},
};
@@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0;
static struct resource ohci_resources[] = {
{
.start = OMAP_OHCI_BASE,
- .end = OMAP_OHCI_BASE + 4096 - 1,
+ .end = OMAP_OHCI_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
{
- .start = INT_USB_HHC_1,
+ .start = INT_USB_IRQ_HGEN,
.flags = IORESOURCE_IRQ,
},
};
@@ -361,7 +477,7 @@ static struct resource otg_resources[] = {
.end = OTG_BASE + 0xff,
.flags = IORESOURCE_MEM,
}, {
- .start = IH2_BASE + 8,
+ .start = INT_USB_IRQ_OTG,
.flags = IORESOURCE_IRQ,
},
};
@@ -385,7 +501,7 @@ static struct platform_device otg_device = {
// FIXME correct answer depends on hmc_mode,
-// as does any nonzero value for config->otg port number
+// as does (on omap1) any nonzero value for config->otg port number
#ifdef CONFIG_USB_GADGET_OMAP
#define is_usb0_device(config) 1
#else
@@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config)
if (config->otg)
syscon |= OTG_EN;
#endif
- pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
+ if (cpu_class_is_omap1())
+ pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
OTG_SYSCON_2_REG = syscon;
printk("USB: hmc %d", config->hmc_mode);
- if (alt_pingroup)
+ if (!alt_pingroup)
printk(", usb2 alt %d wires", config->pins[2]);
else if (config->pins[0])
printk(", usb0 %d wires%s", config->pins[0],
@@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config)
printk(", Mini-AB on usb%d", config->otg - 1);
printk("\n");
- /* leave USB clocks/controllers off until needed */
- ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
- ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
- ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
+ if (cpu_class_is_omap1()) {
+ /* leave USB clocks/controllers off until needed */
+ ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
+ ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
+ ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
+ }
syscon = OTG_SYSCON_1_REG;
syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
@@ -585,7 +704,7 @@ omap_usb_init(void)
}
platform_data = *config;
- if (cpu_is_omap730() || cpu_is_omap16xx())
+ if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx())
omap_otg_init(&platform_data);
else if (cpu_is_omap15xx())
omap_1510_usb_init(&platform_data);