Update Exynos5 XHCI attach code after r276717.

MFC after:	3 days
This commit is contained in:
Hans Petter Selasky 2015-03-02 20:38:17 +00:00
parent 7d69783ae4
commit ee1e767596

View File

@ -89,9 +89,9 @@ __FBSDID("$FreeBSD$");
#define GUSB3PIPECTL_SUSPHY (1 << 17)
/* Forward declarations */
static int exynos_xhci_attach(device_t dev);
static int exynos_xhci_detach(device_t dev);
static int exynos_xhci_probe(device_t dev);
static device_attach_t exynos_xhci_attach;
static device_detach_t exynos_xhci_detach;
static device_probe_t exynos_xhci_probe;
struct exynos_xhci_softc {
device_t dev;
@ -152,13 +152,10 @@ exynos_xhci_probe(device_t dev)
static int
dwc3_init(struct exynos_xhci_softc *esc)
{
struct xhci_softc *sc;
int hwparams1;
int rev;
int reg;
sc = &esc->base;
rev = READ4(esc, GSNPSID);
if ((rev & GSNPSID_MASK) != 0x55330000) {
printf("It is not DWC3 controller\n");
@ -210,32 +207,21 @@ dwc3_init(struct exynos_xhci_softc *esc)
static int
exynos_xhci_attach(device_t dev)
{
struct exynos_xhci_softc *esc;
struct xhci_softc *sc;
struct exynos_xhci_softc *esc = device_get_softc(dev);
bus_space_handle_t bsh;
int err;
esc = device_get_softc(dev);
esc->dev = dev;
sc = &esc->base;
if (xhci_init(sc, dev)) {
device_printf(dev, "Could not initialize softc\n");
return (ENXIO);
}
if (bus_alloc_resources(dev, exynos_xhci_spec, esc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_mtx, 0);
/* XHCI registers */
sc->sc_io_tag = rman_get_bustag(esc->res[0]);
esc->base.sc_io_tag = rman_get_bustag(esc->res[0]);
bsh = rman_get_bushandle(esc->res[0]);
sc->sc_io_size = rman_get_size(esc->res[0]);
esc->base.sc_io_size = rman_get_size(esc->res[0]);
/* DWC3 ctrl registers */
esc->bst = rman_get_bustag(esc->res[1]);
@ -245,95 +231,89 @@ exynos_xhci_attach(device_t dev)
* Set handle to USB related registers subregion used by
* generic XHCI driver.
*/
err = bus_space_subregion(sc->sc_io_tag, bsh, 0x0,
sc->sc_io_size, &sc->sc_io_hdl);
if (err != 0)
err = bus_space_subregion(esc->base.sc_io_tag, bsh, 0x0,
esc->base.sc_io_size, &esc->base.sc_io_hdl);
if (err != 0) {
device_printf(dev, "Subregion failed\n");
bus_release_resources(dev, exynos_xhci_spec, esc->res);
return (ENXIO);
}
if (xhci_init(&esc->base, dev)) {
device_printf(dev, "Could not initialize softc\n");
bus_release_resources(dev, exynos_xhci_spec, esc->res);
return (ENXIO);
}
/* Setup interrupt handler */
err = bus_setup_intr(dev, esc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
NULL, (driver_intr_t *)xhci_interrupt, sc,
&sc->sc_intr_hdl);
NULL, (driver_intr_t *)xhci_interrupt, &esc->base,
&esc->base.sc_intr_hdl);
if (err) {
device_printf(dev, "Could not setup irq, %d\n", err);
return (1);
esc->base.sc_intr_hdl = NULL;
goto error;
}
/* Add USB device */
sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
if (!sc->sc_bus.bdev) {
esc->base.sc_bus.bdev = device_add_child(dev, "usbus", -1);
if (esc->base.sc_bus.bdev == NULL) {
device_printf(dev, "Could not add USB device\n");
err = bus_teardown_intr(dev, esc->res[2],
sc->sc_intr_hdl);
if (err)
device_printf(dev, "Could not tear down irq,"
" %d\n", err);
return (1);
goto error;
}
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
strlcpy(sc->sc_vendor, "Samsung", sizeof(sc->sc_vendor));
device_set_ivars(esc->base.sc_bus.bdev, &esc->base.sc_bus);
strlcpy(esc->base.sc_vendor, "Samsung", sizeof(esc->base.sc_vendor));
dwc3_init(esc);
err = xhci_halt_controller(sc);
err = xhci_halt_controller(&esc->base);
if (err == 0) {
device_printf(dev, "Starting controller\n");
err = xhci_start_controller(sc);
err = xhci_start_controller(&esc->base);
}
if (err == 0) {
device_printf(dev, "Controller started\n");
err = device_probe_and_attach(sc->sc_bus.bdev);
}
if (err == 0) {
device_printf(dev, "Attached success\n");
} else {
device_printf(dev, "USB 3.0 init failed err=%d\n", err);
device_delete_child(dev, sc->sc_bus.bdev);
sc->sc_bus.bdev = NULL;
err = bus_teardown_intr(dev, esc->res[2],
sc->sc_intr_hdl);
if (err)
device_printf(dev, "Could not tear down irq,"
" %d\n", err);
return (1);
err = device_probe_and_attach(esc->base.sc_bus.bdev);
}
if (err != 0)
goto error;
return (0);
error:
exynos_xhci_detach(dev);
return (ENXIO);
}
static int
exynos_xhci_detach(device_t dev)
{
struct exynos_xhci_softc *esc;
struct xhci_softc *sc;
struct exynos_xhci_softc *esc = device_get_softc(dev);
device_t bdev;
int err;
esc = device_get_softc(dev);
sc = &esc->base;
if (esc->res[2] && sc->sc_intr_hdl) {
err = bus_teardown_intr(dev, esc->res[2],
sc->sc_intr_hdl);
if (err) {
device_printf(dev, "Could not tear down irq,"
" %d\n", err);
return (err);
}
sc->sc_intr_hdl = NULL;
if (esc->base.sc_bus.bdev != NULL) {
bdev = esc->base.sc_bus.bdev;
device_detach(bdev);
device_delete_child(dev, bdev);
}
if (sc->sc_bus.bdev) {
device_delete_child(dev, sc->sc_bus.bdev);
sc->sc_bus.bdev = NULL;
}
/* During module unload there are lots of children leftover */
device_delete_children(dev);
xhci_halt_controller(&esc->base);
if (esc->res[2] && esc->base.sc_intr_hdl) {
err = bus_teardown_intr(dev, esc->res[2],
esc->base.sc_intr_hdl);
if (err) {
device_printf(dev, "Could not tear down IRQ,"
" %d\n", err);
return (err);
}
}
bus_release_resources(dev, exynos_xhci_spec, esc->res);
xhci_uninit(&esc->base);
return (0);
}