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