1 1.1 bsh /* 2 1.1 bsh * Copyright (c) 2010 Genetec Corporation. All rights reserved. 3 1.1 bsh * Written by Hiroyuki Bessho for Genetec Corporation. 4 1.1 bsh * 5 1.1 bsh * Redistribution and use in source and binary forms, with or without 6 1.1 bsh * modification, are permitted provided that the following conditions 7 1.1 bsh * are met: 8 1.1 bsh * 1. Redistributions of source code must retain the above copyright 9 1.1 bsh * notice, this list of conditions and the following disclaimer. 10 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 11 1.1 bsh * notice, this list of conditions and the following disclaimer in the 12 1.1 bsh * documentation and/or other materials provided with the distribution. 13 1.1 bsh * 14 1.1 bsh * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 15 1.1 bsh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 1.1 bsh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 1.1 bsh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 18 1.1 bsh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 1.1 bsh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 1.1 bsh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 1.1 bsh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 1.1 bsh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 1.1 bsh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 1.1 bsh * POSSIBILITY OF SUCH DAMAGE. 25 1.1 bsh * 26 1.1 bsh */ 27 1.1 bsh #include <sys/cdefs.h> 28 1.9 andvar __KERNEL_RCSID(0, "$NetBSD: netwalker_usb.c,v 1.9 2024/02/22 23:16:10 andvar Exp $"); 29 1.6 hkenken 30 1.6 hkenken #include "locators.h" 31 1.6 hkenken 32 1.6 hkenken #define _INTR_PRIVATE 33 1.1 bsh 34 1.1 bsh #include <sys/param.h> 35 1.1 bsh #include <sys/systm.h> 36 1.1 bsh #include <sys/conf.h> 37 1.1 bsh #include <sys/kernel.h> 38 1.1 bsh #include <sys/device.h> 39 1.1 bsh #include <sys/intr.h> 40 1.1 bsh #include <sys/bus.h> 41 1.6 hkenken #include <sys/gpio.h> 42 1.1 bsh 43 1.1 bsh #include <dev/usb/usb.h> 44 1.1 bsh #include <dev/usb/usbdi.h> 45 1.1 bsh #include <dev/usb/usbdivar.h> 46 1.1 bsh #include <dev/usb/usb_mem.h> 47 1.1 bsh 48 1.1 bsh #include <dev/usb/ehcireg.h> 49 1.1 bsh #include <dev/usb/ehcivar.h> 50 1.1 bsh 51 1.1 bsh #include <arm/imx/imx51reg.h> 52 1.1 bsh #include <arm/imx/imx51var.h> 53 1.1 bsh #include <arm/imx/imxusbreg.h> 54 1.1 bsh #include <arm/imx/imxusbvar.h> 55 1.1 bsh #include <arm/imx/imx51_iomuxreg.h> 56 1.1 bsh #include <arm/imx/imxgpiovar.h> 57 1.1 bsh 58 1.1 bsh struct netwalker_usbc_softc { 59 1.5 hkenken struct imxusbc_softc sc_imxusbc; /* Must be first */ 60 1.1 bsh }; 61 1.1 bsh 62 1.1 bsh static int imxusbc_match(device_t, cfdata_t, void *); 63 1.1 bsh static void imxusbc_attach(device_t, device_t, void *); 64 1.9 andvar static void netwalker_usb_init(struct imxehci_softc *, uintptr_t); 65 1.1 bsh 66 1.1 bsh static void init_otg(struct imxehci_softc *); 67 1.1 bsh static void init_h1(struct imxehci_softc *); 68 1.1 bsh 69 1.1 bsh extern const struct iomux_conf iomux_usb1_config[]; 70 1.1 bsh 71 1.1 bsh /* attach structures */ 72 1.1 bsh CFATTACH_DECL_NEW(imxusbc_axi, sizeof(struct netwalker_usbc_softc), 73 1.1 bsh imxusbc_match, imxusbc_attach, NULL, NULL); 74 1.1 bsh 75 1.1 bsh static int 76 1.1 bsh imxusbc_match(device_t parent, cfdata_t cf, void *aux) 77 1.1 bsh { 78 1.1 bsh struct axi_attach_args *aa = aux; 79 1.1 bsh 80 1.1 bsh if (aa->aa_addr == USBOH3_BASE) 81 1.1 bsh return 1; 82 1.7 hkenken 83 1.1 bsh return 0; 84 1.1 bsh } 85 1.1 bsh 86 1.1 bsh static void 87 1.1 bsh imxusbc_attach(device_t parent, device_t self, void *aux) 88 1.1 bsh { 89 1.5 hkenken struct imxusbc_softc *sc = device_private(self); 90 1.1 bsh struct axi_attach_args *aa = aux; 91 1.5 hkenken 92 1.7 hkenken aprint_naive("\n"); 93 1.5 hkenken aprint_normal(": Universal Serial Bus Controller\n"); 94 1.5 hkenken 95 1.5 hkenken if (aa->aa_size == AXICF_SIZE_DEFAULT) 96 1.5 hkenken aa->aa_size = USBOH3_SIZE; 97 1.1 bsh 98 1.1 bsh sc->sc_init_md_hook = netwalker_usb_init; 99 1.5 hkenken sc->sc_intr_establish_md_hook = NULL; 100 1.1 bsh sc->sc_setup_md_hook = NULL; 101 1.1 bsh 102 1.5 hkenken imxusbc_attach_common(parent, self, aa->aa_iot, aa->aa_addr, aa->aa_size); 103 1.1 bsh } 104 1.1 bsh 105 1.1 bsh static void 106 1.9 andvar netwalker_usb_init(struct imxehci_softc *sc, uintptr_t data) 107 1.1 bsh { 108 1.1 bsh switch (sc->sc_unit) { 109 1.1 bsh case 0: /* OTG controller */ 110 1.1 bsh init_otg(sc); 111 1.1 bsh break; 112 1.1 bsh case 1: /* EHCI Host 1 */ 113 1.1 bsh init_h1(sc); 114 1.1 bsh break; 115 1.1 bsh default: 116 1.4 khorben aprint_error_dev(sc->sc_hsc.sc_dev, "unit %d not supported\n", 117 1.1 bsh sc->sc_unit); 118 1.1 bsh } 119 1.1 bsh } 120 1.1 bsh 121 1.1 bsh static void 122 1.1 bsh init_otg(struct imxehci_softc *sc) 123 1.1 bsh { 124 1.1 bsh struct imxusbc_softc *usbc = sc->sc_usbc; 125 1.1 bsh uint32_t reg; 126 1.1 bsh 127 1.1 bsh sc->sc_iftype = IMXUSBC_IF_UTMI; 128 1.1 bsh 129 1.1 bsh imxehci_reset(sc); 130 1.1 bsh 131 1.1 bsh reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0); 132 1.1 bsh reg |= PHYCTRL0_OTG_OVER_CUR_DIS; 133 1.1 bsh bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0, reg); 134 1.1 bsh 135 1.1 bsh reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL); 136 1.1 bsh reg &= ~(USBCTRL_OWIR|USBCTRL_OPM); 137 1.1 bsh bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL, reg); 138 1.1 bsh 139 1.1 bsh reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1); 140 1.1 bsh reg = (reg & ~PHYCTRL1_PLLDIVVALUE_MASK) | PHYCTRL1_PLLDIVVALUE_24MHZ; 141 1.1 bsh bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1, reg); 142 1.1 bsh } 143 1.1 bsh 144 1.1 bsh static void 145 1.1 bsh init_h1(struct imxehci_softc *sc) 146 1.1 bsh { 147 1.1 bsh struct imxusbc_softc *usbc = sc->sc_usbc; 148 1.1 bsh uint32_t reg; 149 1.1 bsh 150 1.1 bsh /* output HIGH to USBH1_STP */ 151 1.8 skrll imxgpio_data_write(GPIO_NO(1, 27), GPIO_PIN_HIGH); 152 1.8 skrll imxgpio_set_direction(GPIO_NO(1, 27), GPIO_PIN_OUTPUT); 153 1.1 bsh 154 1.1 bsh iomux_mux_config(iomux_usb1_config); 155 1.1 bsh 156 1.1 bsh delay(100 * 1000); 157 1.1 bsh 158 1.1 bsh /* XXX enable USB clock */ 159 1.1 bsh 160 1.1 bsh imxehci_reset(sc); 161 1.1 bsh 162 1.1 bsh /* select external clock for Host 1 */ 163 1.1 bsh reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, 164 1.1 bsh USBOH3_USBCTRL1); 165 1.1 bsh reg |= USBCTRL1_UH1_EXT_CLK_EN; 166 1.1 bsh bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, 167 1.1 bsh USBOH3_USBCTRL1, reg); 168 1.1 bsh 169 1.1 bsh 170 1.1 bsh /* select ULPI interface for Host 1 */ 171 1.1 bsh sc->sc_iftype = IMXUSBC_IF_ULPI; 172 1.1 bsh 173 1.1 bsh reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, 174 1.1 bsh USBOH3_USBCTRL); 175 1.1 bsh reg &= ~(USBCTRL_H1PM); 176 1.1 bsh reg |= USBCTRL_H1UIE|USBCTRL_H1WIE; 177 1.1 bsh bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, 178 1.1 bsh USBOH3_USBCTRL, reg); 179 1.1 bsh 180 1.2 bsh iomux_set_function(MUX_PIN(USBH1_STP), IOMUX_CONFIG_ALT0); 181 1.1 bsh 182 1.1 bsh 183 1.1 bsh /* HUB RESET release */ 184 1.8 skrll imxgpio_data_write(GPIO_NO(1, 7), GPIO_PIN_HIGH); 185 1.8 skrll imxgpio_set_direction(GPIO_NO(1, 7), GPIO_PIN_OUTPUT); 186 1.1 bsh 187 1.1 bsh /* Drive 26M_OSC_EN line high 3_1 */ 188 1.8 skrll imxgpio_data_write(GPIO_NO(3, 1), GPIO_PIN_HIGH); 189 1.8 skrll imxgpio_set_direction(GPIO_NO(3, 1), GPIO_PIN_OUTPUT); 190 1.1 bsh 191 1.1 bsh /* Drive USB_CLK_EN_B line low 2_1 */ 192 1.8 skrll imxgpio_data_write(GPIO_NO(2, 1), GPIO_PIN_LOW); 193 1.8 skrll imxgpio_set_direction(GPIO_NO(2, 1), GPIO_PIN_INPUT); 194 1.1 bsh 195 1.1 bsh /* MX51_PIN_EIM_D21 - De-assert USB PHY RESETB */ 196 1.1 bsh delay(10 * 1000); 197 1.8 skrll imxgpio_data_write(GPIO_NO(2, 5), GPIO_PIN_HIGH); 198 1.8 skrll imxgpio_set_direction(GPIO_NO(2, 5), GPIO_PIN_OUTPUT); 199 1.2 bsh iomux_set_function(MUX_PIN(EIM_D21), IOMUX_CONFIG_ALT1); 200 1.1 bsh delay(5 * 1000); 201 1.1 bsh } 202 1.1 bsh 203 1.1 bsh /* 204 1.1 bsh * IOMUX setting for USB Host1 205 1.1 bsh * taken from Linux driver 206 1.1 bsh */ 207 1.1 bsh const struct iomux_conf iomux_usb1_config[] = { 208 1.1 bsh 209 1.1 bsh { 210 1.1 bsh /* Initially setup this pin for GPIO, and change to 211 1.1 bsh * USBH1_STP later */ 212 1.2 bsh .pin = MUX_PIN(USBH1_STP), 213 1.1 bsh .mux = IOMUX_CONFIG_ALT2, 214 1.1 bsh .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | 215 1.1 bsh PAD_CTL_KEEPER | PAD_CTL_HYS) 216 1.1 bsh }, 217 1.1 bsh 218 1.1 bsh { 219 1.1 bsh /* Clock */ 220 1.2 bsh .pin = MUX_PIN(USBH1_CLK), 221 1.1 bsh .mux = IOMUX_CONFIG_ALT0, 222 1.2 bsh .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | 223 1.1 bsh PAD_CTL_KEEPER | PAD_CTL_HYS) 224 1.1 bsh }, 225 1.1 bsh { 226 1.1 bsh /* DIR */ 227 1.2 bsh .pin = MUX_PIN(USBH1_DIR), 228 1.1 bsh .mux = IOMUX_CONFIG_ALT0, 229 1.1 bsh .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | 230 1.1 bsh PAD_CTL_KEEPER | PAD_CTL_HYS) 231 1.1 bsh }, 232 1.1 bsh 233 1.1 bsh { 234 1.1 bsh /* NXT */ 235 1.2 bsh .pin = MUX_PIN(USBH1_NXT), 236 1.1 bsh .mux = IOMUX_CONFIG_ALT0, 237 1.1 bsh .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | 238 1.1 bsh PAD_CTL_KEEPER | PAD_CTL_HYS) 239 1.1 bsh }, 240 1.1 bsh 241 1.1 bsh #define USBH1_DATA_CONFIG(n) \ 242 1.1 bsh { \ 243 1.1 bsh /* DATA n */ \ 244 1.2 bsh .pin = MUX_PIN(USBH1_DATA##n), \ 245 1.1 bsh .mux = IOMUX_CONFIG_ALT0, \ 246 1.1 bsh .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | \ 247 1.1 bsh PAD_CTL_KEEPER | PAD_CTL_PUS_100K_PU | \ 248 1.1 bsh PAD_CTL_HYS), \ 249 1.1 bsh /* XXX: what does 100K_PU with KEEPER ? */ \ 250 1.1 bsh } 251 1.1 bsh 252 1.1 bsh USBH1_DATA_CONFIG(0), 253 1.1 bsh USBH1_DATA_CONFIG(1), 254 1.1 bsh USBH1_DATA_CONFIG(2), 255 1.1 bsh USBH1_DATA_CONFIG(3), 256 1.1 bsh USBH1_DATA_CONFIG(4), 257 1.1 bsh USBH1_DATA_CONFIG(5), 258 1.1 bsh USBH1_DATA_CONFIG(6), 259 1.1 bsh USBH1_DATA_CONFIG(7), 260 1.1 bsh 261 1.1 bsh { 262 1.1 bsh /* USB_CLK_EN_B GPIO2[1]*/ 263 1.2 bsh .pin = MUX_PIN(EIM_D17), 264 1.1 bsh .mux = IOMUX_CONFIG_ALT1, 265 1.1 bsh .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE), 266 1.1 bsh }, 267 1.1 bsh 268 1.1 bsh { 269 1.1 bsh /* USB PHY RESETB */ 270 1.2 bsh .pin = MUX_PIN(EIM_D21), 271 1.1 bsh .mux = IOMUX_CONFIG_ALT1, 272 1.1 bsh .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER | 273 1.1 bsh PAD_CTL_PUS_100K_PU | PAD_CTL_SRE) 274 1.1 bsh }, 275 1.1 bsh { 276 1.1 bsh /* USB HUB RESET */ 277 1.2 bsh .pin = MUX_PIN(GPIO1_7), 278 1.1 bsh .mux = IOMUX_CONFIG_ALT0, 279 1.1 bsh .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_SRE), 280 1.1 bsh }, 281 1.3 bsh { 282 1.3 bsh /* 26M_OSC pin settings */ 283 1.3 bsh .pin = MUX_PIN(DI1_PIN12), 284 1.3 bsh .mux = IOMUX_CONFIG_ALT4, 285 1.3 bsh .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER | 286 1.3 bsh PAD_CTL_SRE), 287 1.3 bsh }, 288 1.1 bsh 289 1.1 bsh /* end of table */ 290 1.1 bsh {.pin = IOMUX_CONF_EOT} 291 1.1 bsh }; 292