Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110452116
D5088.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D5088.diff
View Options
Index: head/sys/arm/freescale/vybrid/vf_ehci.c
===================================================================
--- head/sys/arm/freescale/vybrid/vf_ehci.c
+++ head/sys/arm/freescale/vybrid/vf_ehci.c
@@ -169,6 +169,18 @@
DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
MODULE_DEPEND(ehci, usb, 1, 1, 1);
+static void
+vybrid_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
/*
* Public methods
*/
@@ -343,8 +355,10 @@
reg |= 0x3;
bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8, reg);
- /* Set flags */
- sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_NORESTERM;
+ /* Set flags and callbacks*/
+ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_post_reset = vybrid_ehci_post_reset;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
err = ehci_init(sc);
if (!err) {
Index: head/sys/arm/xilinx/zy7_ehci.c
===================================================================
--- head/sys/arm/xilinx/zy7_ehci.c
+++ head/sys/arm/xilinx/zy7_ehci.c
@@ -138,6 +138,18 @@
#define EHCI_REG_OFFSET ZY7_USB_CAPLENGTH_HCIVERSION
#define EHCI_REG_SIZE 0x100
+static void
+zy7_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
zy7_phy_config(device_t dev, bus_space_tag_t io_tag, bus_space_handle_t bsh)
{
@@ -275,8 +287,9 @@
}
/* Customization. */
- sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_TT |
- EHCI_SCFLG_NORESTERM;
+ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_post_reset = zy7_ehci_post_reset;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
/* Modify FIFO burst threshold from 2 to 8. */
bus_space_write_4(sc->sc_io_tag, bsh,
Index: head/sys/dev/usb/controller/ehci.h
===================================================================
--- head/sys/dev/usb/controller/ehci.h
+++ head/sys/dev/usb/controller/ehci.h
@@ -337,11 +337,8 @@
uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT];
uint16_t sc_id_vendor; /* vendor ID for root hub */
uint16_t sc_flags; /* chip specific flags */
-#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init */
-#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed */
#define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */
#define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */
-#define EHCI_SCFLG_BIGEMMIO 0x0010 /* big-endian byte order MMIO */
#define EHCI_SCFLG_TT 0x0020 /* transaction translator present */
#define EHCI_SCFLG_LOSTINTRBUG 0x0040 /* workaround for VIA / ATI chipsets */
#define EHCI_SCFLG_IAADBUG 0x0080 /* workaround for nVidia chipsets */
@@ -358,6 +355,10 @@
char sc_vendor[16]; /* vendor string for root hub */
+ void (*sc_vendor_post_reset)(struct ehci_softc *sc);
+ uint16_t (*sc_vendor_get_port_speed)(struct ehci_softc *sc,
+ uint16_t index);
+
} ehci_softc_t;
#define EREAD1(sc, a) bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
@@ -446,5 +447,7 @@
usb_error_t ehci_init(ehci_softc_t *sc);
void ehci_detach(struct ehci_softc *sc);
void ehci_interrupt(ehci_softc_t *sc);
+uint16_t ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index);
+uint16_t ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index);
#endif /* _EHCI_H_ */
Index: head/sys/dev/usb/controller/ehci.c
===================================================================
--- head/sys/dev/usb/controller/ehci.c
+++ head/sys/dev/usb/controller/ehci.c
@@ -189,24 +189,8 @@
usb_pause_mtx(NULL, hz / 128);
hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
if (!hcr) {
- if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) {
- /*
- * Force USBMODE as requested. Controllers
- * may have multiple operating modes.
- */
- uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE);
- if (sc->sc_flags & EHCI_SCFLG_SETMODE) {
- usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST;
- device_printf(sc->sc_bus.bdev,
- "set host controller mode\n");
- }
- if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) {
- usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE;
- device_printf(sc->sc_bus.bdev,
- "set big-endian mode\n");
- }
- EOWRITE4(sc, EHCI_USBMODE, usbmode);
- }
+ if (sc->sc_vendor_post_reset != NULL)
+ sc->sc_vendor_post_reset(sc);
return (0);
}
}
@@ -3066,6 +3050,36 @@
.bDescriptorType = UDESC_HUB,
};
+uint16_t
+ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index)
+{
+ uint32_t v;
+
+ v = EOREAD4(sc, EHCI_PORTSC(index));
+ v = (v >> EHCI_PORTSC_PSPD_SHIFT) & EHCI_PORTSC_PSPD_MASK;
+
+ if (v == EHCI_PORT_SPEED_HIGH)
+ return (UPS_HIGH_SPEED);
+ if (v == EHCI_PORT_SPEED_LOW)
+ return (UPS_LOW_SPEED);
+ return (0);
+}
+
+uint16_t
+ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index)
+{
+ uint32_t v;
+
+ v = EOREAD4(sc, EHCI_HOSTC(index));
+ v = (v >> EHCI_HOSTC_PSPD_SHIFT) & EHCI_HOSTC_PSPD_MASK;
+
+ if (v == EHCI_PORT_SPEED_HIGH)
+ return (UPS_HIGH_SPEED);
+ if (v == EHCI_PORT_SPEED_LOW)
+ return (UPS_LOW_SPEED);
+ return (0);
+}
+
static void
ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed)
{
@@ -3330,13 +3344,15 @@
}
v = EOREAD4(sc, EHCI_PORTSC(index));
DPRINTFN(9, "port status=0x%04x\n", v);
- if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) {
- if ((v & 0xc000000) == 0x8000000)
+ if (sc->sc_flags & EHCI_SCFLG_TT) {
+ if (sc->sc_vendor_get_port_speed != NULL) {
+ i = sc->sc_vendor_get_port_speed(sc, index);
+ } else {
+ device_printf(sc->sc_bus.bdev,
+ "EHCI_SCFLG_TT quirk is set but "
+ "sc_vendor_get_hub_speed() is NULL\n");
i = UPS_HIGH_SPEED;
- else if ((v & 0xc000000) == 0x4000000)
- i = UPS_LOW_SPEED;
- else
- i = 0;
+ }
} else {
i = UPS_HIGH_SPEED;
}
Index: head/sys/dev/usb/controller/ehci_ixp4xx.c
===================================================================
--- head/sys/dev/usb/controller/ehci_ixp4xx.c
+++ head/sys/dev/usb/controller/ehci_ixp4xx.c
@@ -86,6 +86,19 @@
static uint32_t ehci_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
static void ehci_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, uint32_t);
+static void
+ehci_ixp_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode, select big-endian mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ usbmode |= EHCI_UM_ES_BE;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
ehci_ixp_probe(device_t self)
{
@@ -173,20 +186,21 @@
}
/*
- * Arrange to force Host mode, select big-endian byte alignment,
- * and arrange to not terminate reset operations (the adapter
- * will ignore it if we do but might as well save a reg write).
- * Also, the controller has an embedded Transaction Translator
- * which means port speed must be read from the Port Status
- * register following a port enable.
+ * Select big-endian byte alignment and arrange to not terminate
+ * reset operations (the adapter will ignore it if we do but might
+ * as well save a reg write). Also, the controller has an embedded
+ * Transaction Translator which means port speed must be read from
+ * the Port Status register following a port enable.
*/
sc->sc_flags |= EHCI_SCFLG_TT
- | EHCI_SCFLG_SETMODE
| EHCI_SCFLG_BIGEDESC
- | EHCI_SCFLG_BIGEMMIO
| EHCI_SCFLG_NORESTERM
;
+ /* Setup callbacks. */
+ sc->sc_vendor_post_reset = ehci_ixp_post_reset;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
+
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
Index: head/sys/dev/usb/controller/ehci_mv.c
===================================================================
--- head/sys/dev/usb/controller/ehci_mv.c
+++ head/sys/dev/usb/controller/ehci_mv.c
@@ -105,6 +105,18 @@
{NULL, false}
};
+static void
+mv_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
mv_ehci_probe(device_t self)
{
@@ -226,13 +238,13 @@
* Refer to errata document MV-S500832-00D.pdf (p. 5.24 GL USB-2) for
* details.
*/
- sc->sc_flags |= EHCI_SCFLG_SETMODE;
+ sc->sc_vendor_post_reset = mv_ehci_post_reset;
if (bootverbose)
device_printf(self, "5.24 GL USB-2 workaround enabled\n");
/* XXX all MV chips need it? */
- sc->sc_flags |= EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_NORESTERM;
-
+ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
Index: head/sys/dev/usb/controller/ehcireg.h
===================================================================
--- head/sys/dev/usb/controller/ehcireg.h
+++ head/sys/dev/usb/controller/ehcireg.h
@@ -157,7 +157,17 @@
#define EHCI_PS_CS 0x00000001 /* RO connect status */
#define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
-#define EHCI_USBMODE 0x68 /* RW USB Device mode register */
+#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
+
+/*
+ * Registers not covered by EHCI specification
+ *
+ *
+ * EHCI_USBMODE register offset is different for cores with LPM support,
+ * bits are equal
+ */
+#define EHCI_USBMODE_NOLPM 0x68 /* RW USB Device mode reg (no LPM) */
+#define EHCI_USBMODE_LPM 0xA8 /* RW USB Device mode reg (LPM) */
#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
#define EHCI_UM_CM_IDLE 0x0 /* Idle */
#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
@@ -166,6 +176,18 @@
#define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */
#define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */
-#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
-
+/*
+ * Actual port speed bits depends on EHCI_HOSTC(n) registers presence,
+ * speed encoding is equal
+ */
+#define EHCI_HOSTC(n) (0x80+(4*(n))) /* RO, RW Host mode control reg */
+#define EHCI_HOSTC_PSPD_SHIFT 25
+#define EHCI_HOSTC_PSPD_MASK 0x3
+
+#define EHCI_PORTSC_PSPD_SHIFT 26
+#define EHCI_PORTSC_PSPD_MASK 0x3
+
+#define EHCI_PORT_SPEED_FULL 0
+#define EHCI_PORT_SPEED_LOW 1
+#define EHCI_PORT_SPEED_HIGH 2
#endif /* _EHCIREG_H_ */
Index: head/sys/mips/atheros/ar71xx_ehci.c
===================================================================
--- head/sys/mips/atheros/ar71xx_ehci.c
+++ head/sys/mips/atheros/ar71xx_ehci.c
@@ -61,6 +61,10 @@
#define EHCI_HC_DEVSTR "AR71XX Integrated USB 2.0 controller"
+#define EHCI_USBMODE 0x68 /* USB Device mode register */
+#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
+#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
+
struct ar71xx_ehci_softc {
ehci_softc_t base; /* storage for EHCI code */
};
@@ -71,6 +75,18 @@
bs_r_1_proto(reversed);
bs_w_1_proto(reversed);
+static void
+ar71xx_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
ar71xx_ehci_probe(device_t self)
{
@@ -161,7 +177,8 @@
* which means port speed must be read from the Port Status
* register following a port enable.
*/
- sc->sc_flags = EHCI_SCFLG_SETMODE;
+ sc->sc_flags = 0;
+ sc->sc_vendor_post_reset = ar71xx_ehci_post_reset;
switch (ar71xx_soc) {
case AR71XX_SOC_AR7241:
@@ -178,6 +195,8 @@
case AR71XX_SOC_QCA9556:
case AR71XX_SOC_QCA9558:
sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_get_port_speed =
+ ehci_get_port_speed_portsc;
break;
default:
/* fallthrough */
Index: head/sys/powerpc/ps3/ehci_ps3.c
===================================================================
--- head/sys/powerpc/ps3/ehci_ps3.c
+++ head/sys/powerpc/ps3/ehci_ps3.c
@@ -69,6 +69,17 @@
struct bus_space tag;
};
+static void
+ehci_ps3_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Select big-endian mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode |= EHCI_UM_ES_BE;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
ehci_ps3_probe(device_t dev)
{
@@ -135,7 +146,7 @@
goto error;
}
- sc->sc_flags |= EHCI_SCFLG_BIGEMMIO;
+ sc->sc_vendor_post_reset = ehci_ps3_post_reset;
err = ehci_init(sc);
if (err) {
device_printf(dev, "USB init failed err=%d\n", err);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 19, 3:51 PM (16 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16723425
Default Alt Text
D5088.diff (12 KB)
Attached To
Mode
D5088: EHCI: Make core reset and port speed reading more generic.
Attached
Detach File
Event Timeline
Log In to Comment