summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2016-07-13 09:12:47 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2016-07-13 09:12:47 +0000
commite6defae17257817c76fe597382d3a02b6dce578c (patch)
tree2566b118023036c84cde96585033b38835be2758
parentf32428ef3ea79eefd8eb2d483c7a452aff5be8aa (diff)
Use the device tree voltage regulator information to supply power to the USB
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@
-rw-r--r--sys/arch/armv7/imx/imxehci.c110
1 files changed, 52 insertions, 58 deletions
diff --git a/sys/arch/armv7/imx/imxehci.c b/sys/arch/armv7/imx/imxehci.c
index b7abfab6daf..e80ac9d2502 100644
--- a/sys/arch/armv7/imx/imxehci.c
+++ b/sys/arch/armv7/imx/imxehci.c
@@ -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>
*
@@ -33,10 +33,10 @@
#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>
@@ -70,17 +70,12 @@
#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);
+}