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