Use the device tree voltage regulator information to supply power to the USB
authorkettenis <kettenis@openbsd.org>
Wed, 13 Jul 2016 09:12:46 +0000 (09:12 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 13 Jul 2016 09:12:46 +0000 (09:12 +0000)
bus.  For this only supports "fixed" regulators that are controlled through a
gpio.  But this covers all the case we currently handle with board ID specific
code.  Note that the old code did explicitly remove power first on some boards,
which would reset bus-powered devices/hubs on the bus.  The new code doesn't do
this.  If that causes problems we can revisit the issue.  The boards that would
be affected are sabrelight/nitrogen6x and utilite.

The plan is to evolve this into a generic regulator framework that supports
more complex regulator types as well.

ok jsg@, patrick@

sys/arch/armv7/imx/imxehci.c

index b7abfab..e80ac9d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: imxehci.c,v 1.12 2016/07/12 15:16:00 kettenis Exp $ */
+/*     $OpenBSD: imxehci.c,v 1.13 2016/07/13 09:12:46 kettenis Exp $ */
 /*
  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
  *
 
 #include <armv7/armv7/armv7var.h>
 #include <armv7/imx/imxccmvar.h>
-#include <armv7/imx/imxgpiovar.h>
 #include <armv7/imx/imxiomuxcvar.h>
 
 #include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_gpio.h>
 
 #include <dev/usb/ehcireg.h>
 #include <dev/usb/ehcivar.h>
 #define USBNC_USB_UH1_CTRL_OVER_CUR_POL        (1 << 8)
 #define USBNC_USB_UH1_CTRL_OVER_CUR_DIS        (1 << 7)
 
-/* board specific */
-#define EHCI_HUMMINGBOARD_USB_H1_PWR   0
-#define EHCI_HUMMINGBOARD_USB_OTG_PWR  (2*32+22)
-#define EHCI_NITROGEN6X_USB_HUB_RST    (6*32+12)
-#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);
 
+void   imxehci_enable_vbus(uint32_t);
+
 struct imxehci_softc {
        struct ehci_softc       sc;
        void                    *sc_ih;
@@ -116,6 +111,7 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
        uint32_t phy[1], misc[2];
        uint32_t phy_reg[2];
        uint32_t misc_reg[2];
+       uint32_t vbus;
        int node;
 
        if (faa->fa_nreg < 2 || faa->fa_nintr < 3)
@@ -180,56 +176,13 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
        imxccm_enable_usboh3();
        delay(1000);
 
-       if (misc[1] == 1) {
-               /* enable usb port power */
-               switch (board_id) {
-               case BOARD_ID_IMX6_CUBOXI:
-               case BOARD_ID_IMX6_HUMMINGBOARD:
-                       imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_H1_PWR);
-                       imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_H1_PWR, IMXGPIO_DIR_OUT);
-                       delay(10);
-                       break;
-               case BOARD_ID_IMX6_SABRELITE:
-                       imxgpio_clear_bit(EHCI_NITROGEN6X_USB_HUB_RST);
-                       imxgpio_set_dir(EHCI_NITROGEN6X_USB_HUB_RST, IMXGPIO_DIR_OUT);
-                       delay(1000 * 2);
-                       imxgpio_set_bit(EHCI_NITROGEN6X_USB_HUB_RST);
-                       delay(10);
-                       break;
-               case BOARD_ID_IMX6_SABRESD:
-                       imxgpio_set_bit(EHCI_SABRESD_USB_PWR);
-                       imxgpio_set_dir(EHCI_SABRESD_USB_PWR, IMXGPIO_DIR_OUT);
-                       delay(10);
-                       break;
-               case BOARD_ID_IMX6_UTILITE:
-                       imxgpio_clear_bit(EHCI_UTILITE_USB_HUB_RST);
-                       imxgpio_set_dir(EHCI_UTILITE_USB_HUB_RST, IMXGPIO_DIR_OUT);
-                       delay(10);
-                       imxgpio_set_bit(EHCI_UTILITE_USB_HUB_RST);
-                       delay(1000);
-                       break;
-               }
-
-               /* disable the carger detection, else signal on DP will be poor */
-               imxccm_disable_usb2_chrg_detect();
-               /* power host 1 */
-               imxccm_enable_pll_usb2();
-
-               /* over current and polarity setting */
-               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 (misc[1] == 0) {
-               /* enable usb port power */
-               switch (board_id) {
-               case BOARD_ID_IMX6_CUBOXI:
-               case BOARD_ID_IMX6_HUMMINGBOARD:
-                       imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_OTG_PWR, IMXGPIO_DIR_OUT);
-                       imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_OTG_PWR);
-                       delay(10);
-                       break;
-               }
+       /* enable usb bus power */
+       vbus = OF_getpropint(faa->fa_node, "vbus-supply", 0);
+       if (vbus)
+               imxehci_enable_vbus(vbus);
 
+       switch (misc[1]) {
+       case 0:
                /* disable the carger detection, else signal on DP will be poor */
                imxccm_disable_usb1_chrg_detect();
                /* power host 0 */
@@ -239,6 +192,18 @@ imxehci_attach(struct device *parent, struct device *self, void *aux)
                bus_space_write_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_OTG_CTRL,
                    bus_space_read_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_OTG_CTRL) |
                    (USBNC_USB_OTG_CTRL_OVER_CUR_POL | USBNC_USB_OTG_CTRL_OVER_CUR_DIS));
+               break;
+       case 1:
+               /* disable the carger detection, else signal on DP will be poor */
+               imxccm_disable_usb2_chrg_detect();
+               /* power host 1 */
+               imxccm_enable_pll_usb2();
+
+               /* over current and polarity setting */
+               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));
+               break;
        }
 
        bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR,
@@ -344,3 +309,32 @@ imxehci_detach(struct device *self, int flags)
 
        return (0);
 }
+
+void
+imxehci_enable_vbus(uint32_t phandle)
+{
+       uint32_t gpio[3];
+       int active;
+       int node;
+
+       node = OF_getnodebyphandle(phandle);
+       if (node == 0)
+               return;
+
+       if (!OF_is_compatible(node, "regulator-fixed"))
+               return;
+
+       imxiomuxc_pinctrlbyname(node, "default");
+
+       if (OF_getproplen(node, "enable-active-high") == 0)
+               active = 1;
+       else
+               active = 0;
+
+       if (OF_getpropintarray(node, "gpio", gpio,
+           sizeof(gpio)) != sizeof(gpio))
+               return;
+       
+       gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
+       gpio_controller_set_pin(gpio, active);
+}