Home | History | Annotate | Line # | Download | only in netwalker
netwalker_usb.c revision 1.6
      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.6 2019/07/24 12:33:18 hkenken Exp $");
     29 
     30 #include "locators.h"
     31 
     32 #define	_INTR_PRIVATE
     33 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/conf.h>
     37 #include <sys/kernel.h>
     38 #include <sys/device.h>
     39 #include <sys/intr.h>
     40 #include <sys/bus.h>
     41 #include <sys/gpio.h>
     42 
     43 #include <dev/usb/usb.h>
     44 #include <dev/usb/usbdi.h>
     45 #include <dev/usb/usbdivar.h>
     46 #include <dev/usb/usb_mem.h>
     47 
     48 #include <dev/usb/ehcireg.h>
     49 #include <dev/usb/ehcivar.h>
     50 
     51 #include <arm/imx/imx51reg.h>
     52 #include <arm/imx/imx51var.h>
     53 #include <arm/imx/imxusbreg.h>
     54 #include <arm/imx/imxusbvar.h>
     55 #include <arm/imx/imx51_iomuxreg.h>
     56 #include <arm/imx/imxgpiovar.h>
     57 
     58 struct netwalker_usbc_softc {
     59 	struct imxusbc_softc sc_imxusbc; /* Must be first */
     60 };
     61 
     62 static int	imxusbc_match(device_t, cfdata_t, void *);
     63 static void	imxusbc_attach(device_t, device_t, void *);
     64 static void	netwalker_usb_init(struct imxehci_softc *);
     65 
     66 static void	init_otg(struct imxehci_softc *);
     67 static void	init_h1(struct imxehci_softc *);
     68 
     69 extern const struct iomux_conf iomux_usb1_config[];
     70 
     71 /* attach structures */
     72 CFATTACH_DECL_NEW(imxusbc_axi, sizeof(struct netwalker_usbc_softc),
     73     imxusbc_match, imxusbc_attach, NULL, NULL);
     74 
     75 static int
     76 imxusbc_match(device_t parent, cfdata_t cf, void *aux)
     77 {
     78 	struct axi_attach_args *aa = aux;
     79 
     80 	printf("%s\n", __func__);
     81 
     82 	if (aa->aa_addr == USBOH3_BASE)
     83 		return 1;
     84 	return 0;
     85 }
     86 
     87 static void
     88 imxusbc_attach(device_t parent, device_t self, void *aux)
     89 {
     90 	struct imxusbc_softc *sc = device_private(self);
     91 	struct axi_attach_args *aa = aux;
     92 
     93 	aprint_normal("\n");
     94 	aprint_normal(": Universal Serial Bus Controller\n");
     95 
     96 	if (aa->aa_size == AXICF_SIZE_DEFAULT)
     97 		aa->aa_size = USBOH3_SIZE;
     98 
     99 	sc->sc_init_md_hook = netwalker_usb_init;
    100 	sc->sc_intr_establish_md_hook = NULL;
    101 	sc->sc_setup_md_hook = NULL;
    102 
    103 	imxusbc_attach_common(parent, self, aa->aa_iot, aa->aa_addr, aa->aa_size);
    104 }
    105 
    106 static void
    107 netwalker_usb_init(struct imxehci_softc *sc)
    108 {
    109 	switch (sc->sc_unit) {
    110 	case 0:	/* OTG controller */
    111 		init_otg(sc);
    112 		break;
    113 	case 1:	/* EHCI Host 1 */
    114 		init_h1(sc);
    115 		break;
    116 	default:
    117 		aprint_error_dev(sc->sc_hsc.sc_dev, "unit %d not supported\n",
    118 		    sc->sc_unit);
    119 	}
    120 }
    121 
    122 static void
    123 init_otg(struct imxehci_softc *sc)
    124 {
    125 	struct imxusbc_softc *usbc = sc->sc_usbc;
    126 	uint32_t reg;
    127 
    128 	sc->sc_iftype = IMXUSBC_IF_UTMI;
    129 
    130 	imxehci_reset(sc);
    131 
    132 	reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0);
    133 	reg |= PHYCTRL0_OTG_OVER_CUR_DIS;
    134 	bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0, reg);
    135 
    136 	reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL);
    137 	reg &= ~(USBCTRL_OWIR|USBCTRL_OPM);
    138 	bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL, reg);
    139 
    140 	reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1);
    141 	reg = (reg & ~PHYCTRL1_PLLDIVVALUE_MASK) | PHYCTRL1_PLLDIVVALUE_24MHZ;
    142 	bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1, reg);
    143 }
    144 
    145 static void
    146 init_h1(struct imxehci_softc *sc)
    147 {
    148 	struct imxusbc_softc *usbc = sc->sc_usbc;
    149 	uint32_t reg;
    150 
    151 	/* output HIGH to USBH1_STP */
    152 	gpio_data_write(GPIO_NO(1, 27), GPIO_PIN_HIGH);
    153 	gpio_set_direction(GPIO_NO(1, 27), GPIO_PIN_OUTPUT);
    154 
    155 	iomux_mux_config(iomux_usb1_config);
    156 
    157 	delay(100 * 1000);
    158 
    159 	/* XXX enable USB clock */
    160 
    161 	imxehci_reset(sc);
    162 
    163 	/* select external clock for Host 1 */
    164 	reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh,
    165 			       USBOH3_USBCTRL1);
    166 	reg |= USBCTRL1_UH1_EXT_CLK_EN;
    167 	bus_space_write_4(usbc->sc_iot, usbc->sc_ioh,
    168 			  USBOH3_USBCTRL1, reg);
    169 
    170 
    171 	/* select ULPI interface for Host 1 */
    172 	sc->sc_iftype = IMXUSBC_IF_ULPI;
    173 
    174 	reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh,
    175 			       USBOH3_USBCTRL);
    176 	reg &= ~(USBCTRL_H1PM);
    177 	reg |= USBCTRL_H1UIE|USBCTRL_H1WIE;
    178 	bus_space_write_4(usbc->sc_iot, usbc->sc_ioh,
    179 			  USBOH3_USBCTRL, reg);
    180 
    181 	iomux_set_function(MUX_PIN(USBH1_STP), IOMUX_CONFIG_ALT0);
    182 
    183 
    184 	/* HUB RESET release */
    185 	gpio_data_write(GPIO_NO(1, 7), GPIO_PIN_HIGH);
    186 	gpio_set_direction(GPIO_NO(1, 7), GPIO_PIN_OUTPUT);
    187 
    188 	/* Drive 26M_OSC_EN line high 3_1 */
    189 	gpio_data_write(GPIO_NO(3, 1), GPIO_PIN_HIGH);
    190 	gpio_set_direction(GPIO_NO(3, 1), GPIO_PIN_OUTPUT);
    191 
    192 	/* Drive USB_CLK_EN_B line low  2_1 */
    193 	gpio_data_write(GPIO_NO(2, 1), GPIO_PIN_LOW);
    194 	gpio_set_direction(GPIO_NO(2, 1), GPIO_PIN_INPUT);
    195 
    196 	/* MX51_PIN_EIM_D21 - De-assert USB PHY RESETB */
    197 	delay(10 * 1000);
    198 	gpio_data_write(GPIO_NO(2, 5), GPIO_PIN_HIGH);
    199 	gpio_set_direction(GPIO_NO(2, 5), GPIO_PIN_OUTPUT);
    200 	iomux_set_function(MUX_PIN(EIM_D21), IOMUX_CONFIG_ALT1);
    201 	delay(5 * 1000);
    202 }
    203 
    204 /*
    205  * IOMUX setting for USB Host1
    206  * taken from Linux driver
    207  */
    208 const struct iomux_conf iomux_usb1_config[] = {
    209 
    210 	{
    211 		/* Initially setup this pin for GPIO, and change to
    212 		 * USBH1_STP later */
    213 		.pin = MUX_PIN(USBH1_STP),
    214 		.mux = IOMUX_CONFIG_ALT2,
    215 		.pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
    216 		    PAD_CTL_KEEPER | PAD_CTL_HYS)
    217 	},
    218 
    219 	{
    220 		/* Clock */
    221 		.pin = MUX_PIN(USBH1_CLK),
    222 		.mux = IOMUX_CONFIG_ALT0,
    223 		.pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
    224 		    PAD_CTL_KEEPER | PAD_CTL_HYS)
    225 	},
    226 	{
    227 		/* DIR */
    228 		.pin = MUX_PIN(USBH1_DIR),
    229 		.mux = IOMUX_CONFIG_ALT0,
    230 		.pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
    231 		    PAD_CTL_KEEPER | PAD_CTL_HYS)
    232 	},
    233 
    234 	{
    235 		/* NXT */
    236 		.pin = MUX_PIN(USBH1_NXT),
    237 		.mux = IOMUX_CONFIG_ALT0,
    238 		.pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
    239 		    PAD_CTL_KEEPER | PAD_CTL_HYS)
    240 	},
    241 
    242 #define	USBH1_DATA_CONFIG(n)					\
    243 	{							\
    244 		/* DATA n */					\
    245 		.pin = MUX_PIN(USBH1_DATA##n),			\
    246 		.mux = IOMUX_CONFIG_ALT0,			\
    247 		.pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |	\
    248 		    PAD_CTL_KEEPER | PAD_CTL_PUS_100K_PU |	\
    249 		    PAD_CTL_HYS),				\
    250 		/* XXX: what does 100K_PU with KEEPER ? */	\
    251 	}
    252 
    253 	USBH1_DATA_CONFIG(0),
    254 	USBH1_DATA_CONFIG(1),
    255 	USBH1_DATA_CONFIG(2),
    256 	USBH1_DATA_CONFIG(3),
    257 	USBH1_DATA_CONFIG(4),
    258 	USBH1_DATA_CONFIG(5),
    259 	USBH1_DATA_CONFIG(6),
    260 	USBH1_DATA_CONFIG(7),
    261 
    262 	{
    263 		/* USB_CLK_EN_B  GPIO2[1]*/
    264 		.pin = MUX_PIN(EIM_D17),
    265 		.mux = IOMUX_CONFIG_ALT1,
    266 		.pad = (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE),
    267 	},
    268 
    269 	{
    270 		/* USB PHY RESETB */
    271 		.pin = MUX_PIN(EIM_D21),
    272 		.mux = IOMUX_CONFIG_ALT1,
    273 		.pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER |
    274 		    PAD_CTL_PUS_100K_PU | PAD_CTL_SRE)
    275 	},
    276 	{
    277 		/* USB HUB RESET */
    278 		.pin = MUX_PIN(GPIO1_7),
    279 		.mux = IOMUX_CONFIG_ALT0,
    280 		.pad = (PAD_CTL_DSE_HIGH | PAD_CTL_SRE),
    281 	},
    282 	{
    283 		/* 26M_OSC pin settings */
    284 		.pin = MUX_PIN(DI1_PIN12),
    285 		.mux = IOMUX_CONFIG_ALT4,
    286 		.pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER |
    287 		    PAD_CTL_SRE),
    288 	},
    289 
    290 	/* end of table */
    291 	{.pin = IOMUX_CONF_EOT}
    292 };
    293