1*54fbbda3Sjsg /* $OpenBSD: imxehci.c,v 1.7 2024/09/01 03:08:56 jsg Exp $ */ 2831bc68bSpatrick /* 3831bc68bSpatrick * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> 4831bc68bSpatrick * 5831bc68bSpatrick * Permission to use, copy, modify, and distribute this software for any 6831bc68bSpatrick * purpose with or without fee is hereby granted, provided that the above 7831bc68bSpatrick * copyright notice and this permission notice appear in all copies. 8831bc68bSpatrick * 9831bc68bSpatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10831bc68bSpatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11831bc68bSpatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12831bc68bSpatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13831bc68bSpatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14831bc68bSpatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15831bc68bSpatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16831bc68bSpatrick */ 17831bc68bSpatrick 18831bc68bSpatrick #include <sys/param.h> 19831bc68bSpatrick #include <sys/systm.h> 20831bc68bSpatrick #include <sys/device.h> 21831bc68bSpatrick #include <sys/kernel.h> 22831bc68bSpatrick #include <sys/rwlock.h> 23831bc68bSpatrick #include <sys/timeout.h> 24831bc68bSpatrick 25831bc68bSpatrick #include <machine/intr.h> 26831bc68bSpatrick #include <machine/bus.h> 27831bc68bSpatrick #include <machine/fdt.h> 28831bc68bSpatrick 29831bc68bSpatrick #include <dev/usb/usb.h> 30831bc68bSpatrick #include <dev/usb/usbdi.h> 31831bc68bSpatrick #include <dev/usb/usbdivar.h> 32831bc68bSpatrick #include <dev/usb/usb_mem.h> 33831bc68bSpatrick 34831bc68bSpatrick #include <dev/ofw/openfirm.h> 35831bc68bSpatrick #include <dev/ofw/ofw_clock.h> 36831bc68bSpatrick #include <dev/ofw/ofw_gpio.h> 37831bc68bSpatrick #include <dev/ofw/ofw_misc.h> 38831bc68bSpatrick #include <dev/ofw/ofw_pinctrl.h> 39cdce981fSpatrick #include <dev/ofw/ofw_power.h> 40831bc68bSpatrick #include <dev/ofw/ofw_regulator.h> 41831bc68bSpatrick #include <dev/ofw/fdt.h> 42831bc68bSpatrick 43831bc68bSpatrick #include <dev/usb/ehcireg.h> 44831bc68bSpatrick #include <dev/usb/ehcivar.h> 45831bc68bSpatrick 46831bc68bSpatrick /* usb phy */ 47831bc68bSpatrick #define USBPHY_PWD 0x00 48831bc68bSpatrick #define USBPHY_CTRL 0x30 49831bc68bSpatrick #define USBPHY_CTRL_SET 0x34 50831bc68bSpatrick #define USBPHY_CTRL_CLR 0x38 51831bc68bSpatrick #define USBPHY_CTRL_TOG 0x3c 52831bc68bSpatrick 53831bc68bSpatrick #define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) 54831bc68bSpatrick #define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) 55831bc68bSpatrick #define USBPHY_CTRL_CLKGATE (1 << 30) 56831bc68bSpatrick #define USBPHY_CTRL_SFTRST (1U << 31) 57831bc68bSpatrick 58831bc68bSpatrick /* ehci */ 59831bc68bSpatrick #define USB_EHCI_OFFSET 0x100 60831bc68bSpatrick 61831bc68bSpatrick #define EHCI_PS_PTS_UTMI_MASK ((1 << 25) | (3 << 30)) 62831bc68bSpatrick 63831bc68bSpatrick /* usb non-core */ 64831bc68bSpatrick #define USBNC_USB_OTG_CTRL 0x00 65831bc68bSpatrick #define USBNC_USB_UH1_CTRL 0x04 66831bc68bSpatrick 672b724d3dSpatrick #define USBNC_USB_CTRL_PWR_POL (1 << 9) 682b724d3dSpatrick #define USBNC_USB_CTRL_OVER_CUR_POL (1 << 8) 692b724d3dSpatrick #define USBNC_USB_CTRL_OVER_CUR_DIS (1 << 7) 702b724d3dSpatrick #define USBNC_USB_CTRL_NON_BURST (1 << 1) 71831bc68bSpatrick 72831bc68bSpatrick /* anatop */ 73831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT 0x1b0 74831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT_SET 0x1b4 75831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT_CLR 0x1b8 76831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B (1 << 19) 77831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT_EN_B (1 << 20) 78831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT 0x210 79831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT_SET 0x214 80831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT_CLR 0x218 81831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B (1 << 19) 82831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT_EN_B (1 << 20) 83831bc68bSpatrick 84831bc68bSpatrick int imxehci_match(struct device *, void *, void *); 85831bc68bSpatrick void imxehci_attach(struct device *, struct device *, void *); 86831bc68bSpatrick int imxehci_detach(struct device *, int); 87831bc68bSpatrick 88831bc68bSpatrick struct imxehci_softc { 89831bc68bSpatrick struct ehci_softc sc; 90831bc68bSpatrick void *sc_ih; 91831bc68bSpatrick bus_space_handle_t uh_ioh; 92831bc68bSpatrick bus_space_handle_t ph_ioh; 93831bc68bSpatrick bus_space_handle_t nc_ioh; 94831bc68bSpatrick uint32_t sc_unit; 95831bc68bSpatrick }; 96831bc68bSpatrick 97471aeecfSnaddy const struct cfattach imxehci_ca = { 98831bc68bSpatrick sizeof (struct imxehci_softc), imxehci_match, imxehci_attach, 99831bc68bSpatrick imxehci_detach 100831bc68bSpatrick }; 101831bc68bSpatrick 102831bc68bSpatrick struct cfdriver imxehci_cd = { 103831bc68bSpatrick NULL, "imxehci", DV_DULL 104831bc68bSpatrick }; 105831bc68bSpatrick 106831bc68bSpatrick void imxehci_init_phy(struct imxehci_softc *, uint32_t *); 107831bc68bSpatrick 108831bc68bSpatrick int 109831bc68bSpatrick imxehci_match(struct device *parent, void *match, void *aux) 110831bc68bSpatrick { 111831bc68bSpatrick struct fdt_attach_args *faa = aux; 112831bc68bSpatrick 1134c4c1cbeSpatrick return (OF_is_compatible(faa->fa_node, "fsl,imx27-usb") || 1144c4c1cbeSpatrick OF_is_compatible(faa->fa_node, "fsl,imx7d-usb")); 115831bc68bSpatrick } 116831bc68bSpatrick 117831bc68bSpatrick void 118831bc68bSpatrick imxehci_attach(struct device *parent, struct device *self, void *aux) 119831bc68bSpatrick { 120831bc68bSpatrick struct imxehci_softc *sc = (struct imxehci_softc *)self; 121831bc68bSpatrick struct fdt_attach_args *faa = aux; 122831bc68bSpatrick usbd_status r; 123831bc68bSpatrick char *devname = sc->sc.sc_bus.bdev.dv_xname; 124831bc68bSpatrick uint32_t phy[1], misc[2]; 125831bc68bSpatrick uint32_t misc_reg[2]; 1262b724d3dSpatrick uint32_t off, reg; 127831bc68bSpatrick uint32_t vbus; 128831bc68bSpatrick int misc_node; 129831bc68bSpatrick 130831bc68bSpatrick if (faa->fa_nreg < 1) 131831bc68bSpatrick return; 132831bc68bSpatrick 13389fbac9fSpatrick if (OF_getpropintarray(faa->fa_node, "phys", 13489fbac9fSpatrick phy, sizeof(phy)) != sizeof(phy)) { 135831bc68bSpatrick if (OF_getpropintarray(faa->fa_node, "fsl,usbphy", 136831bc68bSpatrick phy, sizeof(phy)) != sizeof(phy)) 137831bc68bSpatrick return; 13889fbac9fSpatrick } 139831bc68bSpatrick 140831bc68bSpatrick if (OF_getpropintarray(faa->fa_node, "fsl,usbmisc", 141831bc68bSpatrick misc, sizeof(misc)) != sizeof(misc)) 142831bc68bSpatrick return; 143831bc68bSpatrick 144831bc68bSpatrick misc_node = OF_getnodebyphandle(misc[0]); 145831bc68bSpatrick if (misc_node == 0) 146831bc68bSpatrick return; 147831bc68bSpatrick 148831bc68bSpatrick if (OF_getpropintarray(misc_node, "reg", misc_reg, 149831bc68bSpatrick sizeof(misc_reg)) != sizeof(misc_reg)) 150831bc68bSpatrick return; 151831bc68bSpatrick 152831bc68bSpatrick sc->sc.iot = faa->fa_iot; 153831bc68bSpatrick sc->sc.sc_bus.dmatag = faa->fa_dmat; 154831bc68bSpatrick sc->sc.sc_size = faa->fa_reg[0].size - USB_EHCI_OFFSET; 155831bc68bSpatrick sc->sc.sc_flags = EHCIF_USBMODE; 156831bc68bSpatrick sc->sc_unit = misc[1]; 157831bc68bSpatrick 158831bc68bSpatrick /* Map I/O space */ 159831bc68bSpatrick if (bus_space_map(sc->sc.iot, faa->fa_reg[0].addr, 160831bc68bSpatrick faa->fa_reg[0].size, 0, &sc->uh_ioh)) { 161831bc68bSpatrick printf(": cannot map mem space\n"); 162831bc68bSpatrick goto out; 163831bc68bSpatrick } 164831bc68bSpatrick if (bus_space_subregion(sc->sc.iot, sc->uh_ioh, USB_EHCI_OFFSET, 165831bc68bSpatrick sc->sc.sc_size, &sc->sc.ioh)) { 166831bc68bSpatrick printf(": cannot map mem space\n"); 167831bc68bSpatrick goto mem0; 168831bc68bSpatrick } 169831bc68bSpatrick 170831bc68bSpatrick if (bus_space_map(sc->sc.iot, misc_reg[0], 171831bc68bSpatrick misc_reg[1], 0, &sc->nc_ioh)) { 172831bc68bSpatrick printf(": cannot map mem space\n"); 173831bc68bSpatrick goto mem1; 174831bc68bSpatrick } 175831bc68bSpatrick 176831bc68bSpatrick printf("\n"); 177831bc68bSpatrick 178831bc68bSpatrick pinctrl_byname(faa->fa_node, "default"); 179cdce981fSpatrick power_domain_enable(faa->fa_node); 180cdce981fSpatrick clock_set_assigned(faa->fa_node); 181831bc68bSpatrick clock_enable(faa->fa_node, NULL); 182831bc68bSpatrick delay(1000); 183831bc68bSpatrick 184831bc68bSpatrick /* over current and polarity setting */ 185831bc68bSpatrick switch (misc[1]) { 186831bc68bSpatrick case 0: 1872b724d3dSpatrick off = USBNC_USB_OTG_CTRL; 188831bc68bSpatrick break; 189831bc68bSpatrick case 1: 1902b724d3dSpatrick off = USBNC_USB_UH1_CTRL; 191831bc68bSpatrick break; 1922b724d3dSpatrick default: 1932b724d3dSpatrick printf("%s: invalid usbmisc property\n", devname); 1942b724d3dSpatrick return; 195831bc68bSpatrick } 196831bc68bSpatrick 1972b724d3dSpatrick reg = bus_space_read_4(sc->sc.iot, sc->nc_ioh, off); 1982b724d3dSpatrick reg &= ~USBNC_USB_CTRL_OVER_CUR_DIS; 1992b724d3dSpatrick if (OF_getproplen(faa->fa_node, "disable-over-current") == 0) 2002b724d3dSpatrick reg |= USBNC_USB_CTRL_OVER_CUR_DIS; 2012b724d3dSpatrick if (OF_getproplen(faa->fa_node, "over-current-active-low") == 0) 2022b724d3dSpatrick reg |= USBNC_USB_CTRL_OVER_CUR_POL; 2032b724d3dSpatrick else if (OF_getproplen(faa->fa_node, "over-current-active-high") == 0) 2042b724d3dSpatrick reg &= ~USBNC_USB_CTRL_OVER_CUR_POL; 2052b724d3dSpatrick if (OF_getproplen(faa->fa_node, "power-active-high") == 0) 2062b724d3dSpatrick reg |= USBNC_USB_CTRL_PWR_POL; 2072b724d3dSpatrick reg |= USBNC_USB_CTRL_NON_BURST; 2082b724d3dSpatrick bus_space_write_4(sc->sc.iot, sc->nc_ioh, off, reg); 2092b724d3dSpatrick 210831bc68bSpatrick /* enable usb bus power */ 211831bc68bSpatrick vbus = OF_getpropint(faa->fa_node, "vbus-supply", 0); 212831bc68bSpatrick if (vbus) 213831bc68bSpatrick regulator_enable(vbus); 214831bc68bSpatrick 215831bc68bSpatrick /* Disable interrupts, so we don't get any spurious ones. */ 216831bc68bSpatrick sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); 217831bc68bSpatrick EOWRITE2(&sc->sc, EHCI_USBINTR, 0); 218831bc68bSpatrick 219831bc68bSpatrick /* Stop then Reset */ 220831bc68bSpatrick uint32_t val = EOREAD4(&sc->sc, EHCI_USBCMD); 221831bc68bSpatrick val &= ~EHCI_CMD_RS; 222831bc68bSpatrick EOWRITE4(&sc->sc, EHCI_USBCMD, val); 223831bc68bSpatrick 224831bc68bSpatrick while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_RS) 225831bc68bSpatrick ; 226831bc68bSpatrick 227831bc68bSpatrick val = EOREAD4(&sc->sc, EHCI_USBCMD); 228831bc68bSpatrick val |= EHCI_CMD_HCRESET; 229831bc68bSpatrick EOWRITE4(&sc->sc, EHCI_USBCMD, val); 230831bc68bSpatrick 231831bc68bSpatrick while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_HCRESET) 232831bc68bSpatrick ; 233831bc68bSpatrick 234831bc68bSpatrick /* power up PHY */ 235831bc68bSpatrick imxehci_init_phy(sc, phy); 236831bc68bSpatrick 237831bc68bSpatrick /* set host mode */ 238831bc68bSpatrick EOWRITE4(&sc->sc, EHCI_USBMODE, 239831bc68bSpatrick EOREAD4(&sc->sc, EHCI_USBMODE) | EHCI_USBMODE_CM_HOST); 240831bc68bSpatrick 241831bc68bSpatrick /* set to UTMI mode */ 242831bc68bSpatrick EOWRITE4(&sc->sc, EHCI_PORTSC(1), 243831bc68bSpatrick EOREAD4(&sc->sc, EHCI_PORTSC(1)) & ~EHCI_PS_PTS_UTMI_MASK); 244831bc68bSpatrick 245831bc68bSpatrick sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_USB, 246831bc68bSpatrick ehci_intr, &sc->sc, devname); 247831bc68bSpatrick if (sc->sc_ih == NULL) { 248831bc68bSpatrick printf(": unable to establish interrupt\n"); 249831bc68bSpatrick goto mem2; 250831bc68bSpatrick } 251831bc68bSpatrick 252831bc68bSpatrick strlcpy(sc->sc.sc_vendor, "i.MX", sizeof(sc->sc.sc_vendor)); 253831bc68bSpatrick r = ehci_init(&sc->sc); 254831bc68bSpatrick if (r != USBD_NORMAL_COMPLETION) { 255831bc68bSpatrick printf("%s: init failed, error=%d\n", devname, r); 256831bc68bSpatrick goto intr; 257831bc68bSpatrick } 258831bc68bSpatrick 259831bc68bSpatrick config_found(self, &sc->sc.sc_bus, usbctlprint); 260831bc68bSpatrick 261831bc68bSpatrick goto out; 262831bc68bSpatrick 263831bc68bSpatrick intr: 264831bc68bSpatrick fdt_intr_disestablish(sc->sc_ih); 265831bc68bSpatrick sc->sc_ih = NULL; 266831bc68bSpatrick mem2: 267831bc68bSpatrick bus_space_unmap(sc->sc.iot, sc->nc_ioh, misc_reg[1]); 268831bc68bSpatrick mem1: 269831bc68bSpatrick mem0: 270831bc68bSpatrick bus_space_unmap(sc->sc.iot, sc->sc.ioh, faa->fa_reg[0].size); 271831bc68bSpatrick sc->sc.sc_size = 0; 272831bc68bSpatrick out: 273831bc68bSpatrick return; 274831bc68bSpatrick } 275831bc68bSpatrick 276831bc68bSpatrick int 277831bc68bSpatrick imxehci_detach(struct device *self, int flags) 278831bc68bSpatrick { 279831bc68bSpatrick struct imxehci_softc *sc = (struct imxehci_softc *)self; 280831bc68bSpatrick int rv; 281831bc68bSpatrick 282831bc68bSpatrick rv = ehci_detach(self, flags); 283831bc68bSpatrick if (rv) 284831bc68bSpatrick return (rv); 285831bc68bSpatrick 286831bc68bSpatrick if (sc->sc_ih != NULL) { 287831bc68bSpatrick fdt_intr_disestablish(sc->sc_ih); 288831bc68bSpatrick sc->sc_ih = NULL; 289831bc68bSpatrick } 290831bc68bSpatrick 291831bc68bSpatrick if (sc->sc.sc_size) { 292831bc68bSpatrick bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); 293831bc68bSpatrick sc->sc.sc_size = 0; 294831bc68bSpatrick } 295831bc68bSpatrick 296831bc68bSpatrick return (0); 297831bc68bSpatrick } 298831bc68bSpatrick 299831bc68bSpatrick /* 300831bc68bSpatrick * PHY initialization. 301831bc68bSpatrick */ 302831bc68bSpatrick 303831bc68bSpatrick struct imxehci_phy { 304831bc68bSpatrick const char *compat; 305831bc68bSpatrick void (*init)(struct imxehci_softc *, uint32_t *); 306831bc68bSpatrick }; 307831bc68bSpatrick 308831bc68bSpatrick void imx23_usb_init(struct imxehci_softc *, uint32_t *); 309831bc68bSpatrick static void nop_xceiv_init(struct imxehci_softc *, uint32_t *); 310831bc68bSpatrick 311831bc68bSpatrick struct imxehci_phy imxehci_phys[] = { 312831bc68bSpatrick { "fsl,imx23-usbphy", imx23_usb_init }, 313831bc68bSpatrick { "usb-nop-xceiv", nop_xceiv_init }, 314831bc68bSpatrick }; 315831bc68bSpatrick 316831bc68bSpatrick void 317831bc68bSpatrick imxehci_init_phy(struct imxehci_softc *sc, uint32_t *cells) 318831bc68bSpatrick { 319831bc68bSpatrick int node; 320831bc68bSpatrick int i; 321831bc68bSpatrick 322831bc68bSpatrick node = OF_getnodebyphandle(cells[0]); 323831bc68bSpatrick if (node == 0) 324831bc68bSpatrick return; 325831bc68bSpatrick 326831bc68bSpatrick for (i = 0; i < nitems(imxehci_phys); i++) { 327831bc68bSpatrick if (OF_is_compatible(node, imxehci_phys[i].compat)) { 328831bc68bSpatrick imxehci_phys[i].init(sc, cells); 329831bc68bSpatrick return; 330831bc68bSpatrick } 331831bc68bSpatrick } 332831bc68bSpatrick } 333831bc68bSpatrick 334831bc68bSpatrick /* 335831bc68bSpatrick * i.MX5/6 PHYs. 336831bc68bSpatrick */ 337831bc68bSpatrick 338831bc68bSpatrick void 339831bc68bSpatrick imx23_usb_init(struct imxehci_softc *sc, uint32_t *cells) 340831bc68bSpatrick { 341831bc68bSpatrick struct regmap *rm = NULL; 342831bc68bSpatrick uint32_t phy_reg[2]; 343831bc68bSpatrick uint32_t anatop[1]; 344831bc68bSpatrick int node; 345831bc68bSpatrick 346831bc68bSpatrick node = OF_getnodebyphandle(cells[0]); 347831bc68bSpatrick KASSERT(node != 0); 348831bc68bSpatrick 349831bc68bSpatrick if (OF_getpropintarray(node, "reg", phy_reg, 350831bc68bSpatrick sizeof(phy_reg)) != sizeof(phy_reg)) 351831bc68bSpatrick return; 352831bc68bSpatrick 353831bc68bSpatrick if (bus_space_map(sc->sc.iot, phy_reg[0], 354831bc68bSpatrick phy_reg[1], 0, &sc->ph_ioh)) { 355831bc68bSpatrick printf("%s: can't map PHY registers\n", 356831bc68bSpatrick sc->sc.sc_bus.bdev.dv_xname); 357831bc68bSpatrick return; 358831bc68bSpatrick } 359831bc68bSpatrick 360831bc68bSpatrick if (OF_getpropintarray(node, "fsl,anatop", 361831bc68bSpatrick anatop, sizeof(anatop)) == sizeof(anatop)) 362831bc68bSpatrick rm = regmap_byphandle(anatop[0]); 363831bc68bSpatrick 364*54fbbda3Sjsg /* Disable the charger detection, else signal on DP will be poor */ 365831bc68bSpatrick switch (sc->sc_unit) { 366831bc68bSpatrick case 0: 367831bc68bSpatrick if (rm != NULL) 368831bc68bSpatrick regmap_write_4(rm, ANALOG_USB1_CHRG_DETECT_SET, 369831bc68bSpatrick ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B | 370831bc68bSpatrick ANALOG_USB1_CHRG_DETECT_EN_B); 371831bc68bSpatrick break; 372831bc68bSpatrick case 1: 373831bc68bSpatrick if (rm != NULL) 374831bc68bSpatrick regmap_write_4(rm, ANALOG_USB2_CHRG_DETECT_SET, 375831bc68bSpatrick ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B | 376831bc68bSpatrick ANALOG_USB2_CHRG_DETECT_EN_B); 377831bc68bSpatrick break; 378831bc68bSpatrick } 379831bc68bSpatrick 380831bc68bSpatrick clock_enable(node, NULL); 381831bc68bSpatrick 382831bc68bSpatrick /* Reset USBPHY module */ 383831bc68bSpatrick bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, 384831bc68bSpatrick USBPHY_CTRL_SFTRST); 385831bc68bSpatrick 386831bc68bSpatrick delay(10); 387831bc68bSpatrick 388831bc68bSpatrick /* Remove CLKGATE and SFTRST */ 389831bc68bSpatrick bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR, 390831bc68bSpatrick USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); 391831bc68bSpatrick 392831bc68bSpatrick delay(10); 393831bc68bSpatrick 394831bc68bSpatrick /* Power up the PHY */ 395831bc68bSpatrick bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_PWD, 0); 396831bc68bSpatrick 397831bc68bSpatrick /* enable FS/LS device */ 398831bc68bSpatrick bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, 399831bc68bSpatrick USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); 400831bc68bSpatrick } 401831bc68bSpatrick 402831bc68bSpatrick /* 403831bc68bSpatrick * i.MX7 PHYs. 404831bc68bSpatrick */ 405831bc68bSpatrick 406831bc68bSpatrick static void 407831bc68bSpatrick nop_xceiv_init(struct imxehci_softc *sc, uint32_t *cells) 408831bc68bSpatrick { 409831bc68bSpatrick int node; 410831bc68bSpatrick 411831bc68bSpatrick node = OF_getnodebyphandle(cells[0]); 412831bc68bSpatrick KASSERT(node != 0); 413831bc68bSpatrick 414cdce981fSpatrick clock_set_assigned(node); 415831bc68bSpatrick clock_enable(node, NULL); 416831bc68bSpatrick } 417