Dynamically attach i.MX6 ehci(4) using the FDT.
authorkettenis <kettenis@openbsd.org>
Sat, 9 Jul 2016 12:32:50 +0000 (12:32 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 9 Jul 2016 12:32:50 +0000 (12:32 +0000)
ok jsg@

sys/arch/armv7/conf/GENERIC
sys/arch/armv7/conf/RAMDISK
sys/arch/armv7/imx/files.imx
sys/arch/armv7/imx/imx.c
sys/arch/armv7/imx/imxehci.c

index 9176c20..1ddd24f 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.27 2016/06/28 04:41:37 jmatthew Exp $
+#      $OpenBSD: GENERIC,v 1.28 2016/07/09 12:32:50 kettenis Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -52,7 +52,7 @@ iic*          at imxiic?
 imxesdhc*      at fdt?                 # SDHC controller
 sdmmc*         at imxesdhc?            # SD/MMC bus
 ahci*          at fdt?                 # AHCI/SATA
-ehci*          at imx?                 # EHCI (shim)
+ehci*          at fdt?                 # EHCI (shim)
 usb*           at ehci?
 
 # OMAP3xxx/OMAP4xxx SoC
index 53585e5..ecf7a2d 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: RAMDISK,v 1.24 2016/06/28 04:41:37 jmatthew Exp $
+#      $OpenBSD: RAMDISK,v 1.25 2016/07/09 12:32:50 kettenis Exp $
 
 machine                armv7 arm
 
@@ -51,7 +51,7 @@ iic*          at imxiic?
 imxesdhc*      at fdt?                 # SDHC controller
 sdmmc*         at imxesdhc?            # SD/MMC bus
 ahci*          at fdt?                 # AHCI/SATA
-ehci*          at imx?                 # EHCI (shim)
+ehci*          at fdt?                 # EHCI (shim)
 usb*           at ehci?
 
 # OMAP3xxx/OMAP4xxx SoC
index b38221d..ac30e0f 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.imx,v 1.11 2016/06/13 23:43:58 kettenis Exp $
+#      $OpenBSD: files.imx,v 1.12 2016/07/09 12:32:50 kettenis Exp $
 
 define imx {}
 device imx: imx
@@ -40,7 +40,7 @@ device fec: ether, ifnet, mii, ifmedia
 attach fec at fdt
 file   arch/armv7/imx/if_fec.c         fec
 
-attach ehci at imx with imxehci
+attach ehci at fdt with imxehci
 file   arch/armv7/imx/imxehci.c                imxehci
 
 device imxesdhc: sdmmcbus
index 56b6743..59b57a6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: imx.c,v 1.20 2016/06/13 23:43:58 kettenis Exp $ */
+/* $OpenBSD: imx.c,v 1.21 2016/07/09 12:32:50 kettenis Exp $ */
 /*
  * Copyright (c) 2005,2008 Dale Rahn <drahn@openbsd.com>
  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
@@ -47,8 +47,6 @@ struct board_dev hummingboard_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
-       { "ehci",       1 },
        { NULL,         0 }
 };
 
@@ -63,7 +61,6 @@ struct board_dev sabrelite_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
        { NULL,         0 }
 };
 
@@ -79,7 +76,6 @@ struct board_dev sabresd_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
        { NULL,         0 }
 };
 
@@ -94,7 +90,6 @@ struct board_dev udoo_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
        { NULL,         0 }
 };
 
@@ -109,7 +104,6 @@ struct board_dev utilite_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
        { NULL,         0 }
 };
 
@@ -124,7 +118,6 @@ struct board_dev novena_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
        { NULL,         0 }
 };
 
@@ -139,7 +132,6 @@ struct board_dev wandboard_devs[] = {
        { "imxgpio",    4 },
        { "imxgpio",    5 },
        { "imxgpio",    6 },
-       { "ehci",       0 },
        { NULL,         0 }
 };
 
index b85a181..cc216cf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: imxehci.c,v 1.9 2016/05/19 09:54:18 jsg Exp $ */
+/*     $OpenBSD: imxehci.c,v 1.10 2016/07/09 12:32:50 kettenis Exp $ */
 /*
  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
  *
@@ -24,6 +24,7 @@
 
 #include <machine/intr.h>
 #include <machine/bus.h>
+#include <machine/fdt.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -34,6 +35,8 @@
 #include <armv7/imx/imxccmvar.h>
 #include <armv7/imx/imxgpiovar.h>
 
+#include <dev/ofw/openfirm.h>
+
 #include <dev/usb/ehcireg.h>
 #include <dev/usb/ehcivar.h>
 
@@ -50,6 +53,8 @@
 #define USBPHY_CTRL_SFTRST             (1U << 31)
 
 /* ehci */
+#define USB_EHCI_OFFSET                        0x100
+
 #define EHCI_USBMODE                   0xa8
 
 #define EHCI_USBMODE_HOST              (3 << 0)
 #define USBNC_USB_UH1_CTRL_OVER_CUR_POL        (1 << 8)
 #define USBNC_USB_UH1_CTRL_OVER_CUR_DIS        (1 << 7)
 
-/* port specific addresses */
-#define USBOTG_EHCI_ADDR       0x02184100
-#define USBUH1_EHCI_ADDR       0x02184300
-#define USBUH2_EHCI_ADDR       0x02184500
-#define USBUH3_EHCI_ADDR       0x02184700
-
 /* board specific */
 #define EHCI_HUMMINGBOARD_USB_H1_PWR   0
 #define EHCI_HUMMINGBOARD_USB_OTG_PWR  (2*32+22)
@@ -77,6 +76,7 @@
 #define EHCI_SABRESD_USB_PWR           (0*32+29)
 #define EHCI_UTILITE_USB_HUB_RST       (6*32+8)
 
+int    imxehci_match(struct device *, void *, void *);
 void   imxehci_attach(struct device *, struct device *, void *);
 int    imxehci_detach(struct device *, int);
 
@@ -89,43 +89,81 @@ struct imxehci_softc {
 };
 
 struct cfattach imxehci_ca = {
-       sizeof (struct imxehci_softc), NULL, imxehci_attach,
-       imxehci_detach, NULL
+       sizeof (struct imxehci_softc), imxehci_match, imxehci_attach,
+       imxehci_detach
 };
 
+int
+imxehci_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       return OF_is_compatible(faa->fa_node, "fsl,imx27-usb");
+}
+
 void
 imxehci_attach(struct device *parent, struct device *self, void *aux)
 {
-       struct imxehci_softc    *sc = (struct imxehci_softc *)self;
-       struct armv7_attach_args *aa = aux;
-       usbd_status             r;
+       struct imxehci_softc *sc = (struct imxehci_softc *)self;
+       struct fdt_attach_args *faa = aux;
+       usbd_status r;
        char *devname = sc->sc.sc_bus.bdev.dv_xname;
+       uint32_t phy[1], misc[2];
+       uint32_t phy_reg[2];
+       uint32_t misc_reg[2];
+       int node;
 
-       sc->sc.iot = aa->aa_iot;
-       sc->sc.sc_bus.dmatag = aa->aa_dmat;
-       sc->sc.sc_size = aa->aa_dev->mem[0].size;
+       if (faa->fa_nreg < 2 || faa->fa_nintr < 3)
+               return;
+
+       if (OF_getpropintarray(faa->fa_node, "fsl,usbphy",
+           phy, sizeof(phy)) != sizeof(phy))
+               return;
+
+       if (OF_getpropintarray(faa->fa_node, "fsl,usbmisc",
+           misc, sizeof(misc)) != sizeof(misc))
+               return;
+
+       node = OF_getnodebyphandle(phy[0]);
+       if (node == 0)
+               return;
+
+       if (OF_getpropintarray(node, "reg", phy_reg,
+           sizeof(phy_reg)) != sizeof(phy_reg))
+               return;
+
+       node = OF_getnodebyphandle(misc[0]);
+       if (node == 0)
+               return;
+
+       if (OF_getpropintarray(node, "reg", misc_reg,
+           sizeof(misc_reg)) != sizeof(misc_reg))
+               return;
+
+       sc->sc.iot = faa->fa_iot;
+       sc->sc.sc_bus.dmatag = faa->fa_dmat;
+       sc->sc.sc_size = faa->fa_reg[1] - USB_EHCI_OFFSET;
 
        /* Map I/O space */
-       if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[0].addr,
-               aa->aa_dev->mem[0].size, 0, &sc->sc.ioh)) {
+       if (bus_space_map(sc->sc.iot, faa->fa_reg[0],
+           faa->fa_reg[1], 0, &sc->uh_ioh)) {
                printf(": cannot map mem space\n");
                goto out;
        }
-
-       if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[1].addr,
-               aa->aa_dev->mem[1].size, 0, &sc->uh_ioh)) {
+       if (bus_space_subregion(sc->sc.iot, sc->uh_ioh, USB_EHCI_OFFSET,
+           sc->sc.sc_size, &sc->sc.ioh)) {
                printf(": cannot map mem space\n");
                goto mem0;
        }
 
-       if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[2].addr,
-               aa->aa_dev->mem[2].size, 0, &sc->ph_ioh)) {
+       if (bus_space_map(sc->sc.iot, phy_reg[0],
+           phy_reg[1], 0, &sc->ph_ioh)) {
                printf(": cannot map mem space\n");
                goto mem1;
        }
 
-       if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[3].addr,
-               aa->aa_dev->mem[3].size, 0, &sc->nc_ioh)) {
+       if (bus_space_map(sc->sc.iot, misc_reg[0],
+           misc_reg[1], 0, &sc->nc_ioh)) {
                printf(": cannot map mem space\n");
                goto mem2;
        }
@@ -135,10 +173,9 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
        imxccm_enable_usboh3();
        delay(1000);
 
-       if (aa->aa_dev->mem[0].addr == USBUH1_EHCI_ADDR) {
+       if (misc[1] == 1) {
                /* enable usb port power */
-               switch (board_id)
-               {
+               switch (board_id) {
                case BOARD_ID_IMX6_CUBOXI:
                case BOARD_ID_IMX6_HUMMINGBOARD:
                        imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_H1_PWR);
@@ -175,10 +212,9 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
                bus_space_write_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_UH1_CTRL,
                    bus_space_read_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_UH1_CTRL) |
                    (USBNC_USB_UH1_CTRL_OVER_CUR_POL | USBNC_USB_UH1_CTRL_OVER_CUR_DIS));
-       } else if (aa->aa_dev->mem[0].addr == USBOTG_EHCI_ADDR) {
+       } else if (misc[1] == 0) {
                /* enable usb port power */
-               switch (board_id)
-               {
+               switch (board_id) {
                case BOARD_ID_IMX6_CUBOXI:
                case BOARD_ID_IMX6_HUMMINGBOARD:
                        imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_OTG_PWR, IMXGPIO_DIR_OUT);
@@ -246,7 +282,7 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
        EOWRITE4(&sc->sc, EHCI_PORTSC(1),
            EOREAD4(&sc->sc, EHCI_PORTSC(1)) & ~EHCI_PS_PTS_UTMI_MASK);
 
-       sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_USB,
+       sc->sc_ih = arm_intr_establish(faa->fa_intr[1], IPL_USB,
            ehci_intr, &sc->sc, devname);
        if (sc->sc_ih == NULL) {
                printf(": unable to establish interrupt\n");
@@ -268,13 +304,12 @@ intr:
        arm_intr_disestablish(sc->sc_ih);
        sc->sc_ih = NULL;
 mem3:
-       bus_space_unmap(sc->sc.iot, sc->nc_ioh, aa->aa_dev->mem[3].addr);
+       bus_space_unmap(sc->sc.iot, sc->nc_ioh, misc_reg[1]);
 mem2:
-       bus_space_unmap(sc->sc.iot, sc->ph_ioh, aa->aa_dev->mem[2].addr);
+       bus_space_unmap(sc->sc.iot, sc->ph_ioh, phy_reg[1]);
 mem1:
-       bus_space_unmap(sc->sc.iot, sc->uh_ioh, aa->aa_dev->mem[1].addr);
 mem0:
-       bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+       bus_space_unmap(sc->sc.iot, sc->sc.ioh, faa->fa_reg[1]);
        sc->sc.sc_size = 0;
 out:
        return;