diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-06-11 09:22:51 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-06-11 09:22:51 +0000 |
commit | aaae9b45642835fed798668dffd00c4d2dc6266e (patch) | |
tree | 6f1f9475d66d084e7f58ed91ccdfdffc8b58ac56 /sys/arch/armv7 | |
parent | 43a724b7cebf709af92bd12581f943e5eda589fa (diff) |
Split out the PHY initialization code and add a "no-op" implementation for
i.MX7.
ok patrick@
Diffstat (limited to 'sys/arch/armv7')
-rw-r--r-- | sys/arch/armv7/imx/imxehci.c | 207 |
1 files changed, 134 insertions, 73 deletions
diff --git a/sys/arch/armv7/imx/imxehci.c b/sys/arch/armv7/imx/imxehci.c index 328d89f6106..759a0eab3c8 100644 --- a/sys/arch/armv7/imx/imxehci.c +++ b/sys/arch/armv7/imx/imxehci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxehci.c,v 1.24 2018/04/02 16:32:22 patrick Exp $ */ +/* $OpenBSD: imxehci.c,v 1.25 2018/06/11 09:22:50 kettenis Exp $ */ /* * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> * @@ -90,6 +90,7 @@ struct imxehci_softc { bus_space_handle_t uh_ioh; bus_space_handle_t ph_ioh; bus_space_handle_t nc_ioh; + uint32_t sc_unit; }; struct cfattach imxehci_ca = { @@ -101,6 +102,8 @@ struct cfdriver imxehci_cd = { NULL, "imxehci", DV_DULL }; +void imxehci_init_phy(struct imxehci_softc *, uint32_t *); + int imxehci_match(struct device *parent, void *match, void *aux) { @@ -114,16 +117,12 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) { struct imxehci_softc *sc = (struct imxehci_softc *)self; struct fdt_attach_args *faa = aux; - struct regmap *rm = NULL; 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]; - uint32_t anatop[1]; uint32_t vbus; int misc_node; - int phy_node; if (faa->fa_nreg < 1) return; @@ -136,18 +135,6 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) misc, sizeof(misc)) != sizeof(misc)) return; - phy_node = OF_getnodebyphandle(phy[0]); - if (phy_node == 0) - return; - - if (OF_getpropintarray(phy_node, "reg", phy_reg, - sizeof(phy_reg)) != sizeof(phy_reg)) - return; - - if (OF_getpropintarray(phy_node, "fsl,anatop", - anatop, sizeof(anatop)) == sizeof(anatop)) - rm = regmap_byphandle(anatop[0]); - misc_node = OF_getnodebyphandle(misc[0]); if (misc_node == 0) return; @@ -160,6 +147,7 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) sc->sc.sc_bus.dmatag = faa->fa_dmat; sc->sc.sc_size = faa->fa_reg[0].size - USB_EHCI_OFFSET; sc->sc.sc_flags = EHCIF_USBMODE; + sc->sc_unit = misc[1]; /* Map I/O space */ if (bus_space_map(sc->sc.iot, faa->fa_reg[0].addr, @@ -173,16 +161,10 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) goto mem0; } - 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, misc_reg[0], misc_reg[1], 0, &sc->nc_ioh)) { printf(": cannot map mem space\n"); - goto mem2; + goto mem1; } printf("\n"); @@ -191,46 +173,24 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) clock_enable(faa->fa_node, NULL); delay(1000); - /* enable usb bus power */ - vbus = OF_getpropint(faa->fa_node, "vbus-supply", 0); - if (vbus) - regulator_enable(vbus); - + /* over current and polarity setting */ switch (misc[1]) { case 0: - /* disable the carger detection, else signal on DP will be poor */ - if (rm != NULL) - regmap_write_4(rm, ANALOG_USB1_CHRG_DETECT_SET, - ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B | - ANALOG_USB1_CHRG_DETECT_EN_B); - - /* power host 0 */ - clock_enable(phy_node, NULL); - - /* over current and polarity setting */ 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 */ - if (rm != NULL) - regmap_write_4(rm, ANALOG_USB2_CHRG_DETECT_SET, - ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B | - ANALOG_USB2_CHRG_DETECT_EN_B); - - /* power host 1 */ - clock_enable(phy_node, NULL); - - /* 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, - USBPHY_CTRL_CLKGATE); + /* enable usb bus power */ + vbus = OF_getpropint(faa->fa_node, "vbus-supply", 0); + if (vbus) + regulator_enable(vbus); /* Disable interrupts, so we don't get any spurious ones. */ sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); @@ -251,23 +211,8 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_HCRESET) ; - /* Reset USBPHY module */ - bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, USBPHY_CTRL_SFTRST); - - delay(10); - - /* Remove CLKGATE and SFTRST */ - bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR, - USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); - - delay(10); - - /* Power up the PHY */ - bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_PWD, 0); - - /* enable FS/LS device */ - bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, - USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); + /* power up PHY */ + imxehci_init_phy(sc, phy); /* set host mode */ EOWRITE4(&sc->sc, EHCI_USBMODE, @@ -281,10 +226,10 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) ehci_intr, &sc->sc, devname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt\n"); - goto mem3; + goto mem2; } - strlcpy(sc->sc.sc_vendor, "i.MX6", sizeof(sc->sc.sc_vendor)); + strlcpy(sc->sc.sc_vendor, "i.MX", sizeof(sc->sc.sc_vendor)); r = ehci_init(&sc->sc); if (r != USBD_NORMAL_COMPLETION) { printf("%s: init failed, error=%d\n", devname, r); @@ -298,10 +243,8 @@ imxehci_attach(struct device *parent, struct device *self, void *aux) intr: arm_intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; -mem3: - bus_space_unmap(sc->sc.iot, sc->nc_ioh, misc_reg[1]); mem2: - bus_space_unmap(sc->sc.iot, sc->ph_ioh, phy_reg[1]); + bus_space_unmap(sc->sc.iot, sc->nc_ioh, misc_reg[1]); mem1: mem0: bus_space_unmap(sc->sc.iot, sc->sc.ioh, faa->fa_reg[0].size); @@ -332,3 +275,121 @@ imxehci_detach(struct device *self, int flags) return (0); } + +/* + * PHY initialization. + */ + +struct imxehci_phy { + const char *compat; + void (*init)(struct imxehci_softc *, uint32_t *); +}; + +void imx23_usb_init(struct imxehci_softc *, uint32_t *); +static void nop_xceiv_init(struct imxehci_softc *, uint32_t *); + +struct imxehci_phy imxehci_phys[] = { + { "fsl,imx23-usbphy", imx23_usb_init }, + { "usb-nop-xceiv", nop_xceiv_init }, +}; + +void +imxehci_init_phy(struct imxehci_softc *sc, uint32_t *cells) +{ + int node; + int i; + + node = OF_getnodebyphandle(cells[0]); + if (node == 0) + return; + + for (i = 0; i < nitems(imxehci_phys); i++) { + if (OF_is_compatible(node, imxehci_phys[i].compat)) { + imxehci_phys[i].init(sc, cells); + return; + } + } +} + +/* + * i.MX5/6 PHYs. + */ + +void +imx23_usb_init(struct imxehci_softc *sc, uint32_t *cells) +{ + struct regmap *rm = NULL; + uint32_t phy_reg[2]; + uint32_t anatop[1]; + int node; + + node = OF_getnodebyphandle(cells[0]); + KASSERT(node != 0); + + if (OF_getpropintarray(node, "reg", phy_reg, + sizeof(phy_reg)) != sizeof(phy_reg)) + return; + + if (bus_space_map(sc->sc.iot, phy_reg[0], + phy_reg[1], 0, &sc->ph_ioh)) { + printf("%s: can't map PHY registers\n", + sc->sc.sc_bus.bdev.dv_xname); + return; + } + + if (OF_getpropintarray(node, "fsl,anatop", + anatop, sizeof(anatop)) == sizeof(anatop)) + rm = regmap_byphandle(anatop[0]); + + /* Disable the carger detection, else signal on DP will be poor */ + switch (sc->sc_unit) { + case 0: + if (rm != NULL) + regmap_write_4(rm, ANALOG_USB1_CHRG_DETECT_SET, + ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B | + ANALOG_USB1_CHRG_DETECT_EN_B); + break; + case 1: + if (rm != NULL) + regmap_write_4(rm, ANALOG_USB2_CHRG_DETECT_SET, + ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B | + ANALOG_USB2_CHRG_DETECT_EN_B); + break; + } + + clock_enable(node, NULL); + + /* Reset USBPHY module */ + bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, + USBPHY_CTRL_SFTRST); + + delay(10); + + /* Remove CLKGATE and SFTRST */ + bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR, + USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); + + delay(10); + + /* Power up the PHY */ + bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_PWD, 0); + + /* enable FS/LS device */ + bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, + USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); +} + +/* + * i.MX7 PHYs. + */ + +static void +nop_xceiv_init(struct imxehci_softc *sc, uint32_t *cells) +{ + int node; + + node = OF_getnodebyphandle(cells[0]); + KASSERT(node != 0); + + clock_enable(node, NULL); +} |