Home | History | Annotate | Line # | Download | only in netwalker
netwalker_usb.c revision 1.1.6.2
      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.6.2 2011/03/05 20:50:08 rmind 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 
    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  */
    204 const 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 = __CONCAT(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 	/* end of table */
    280 	{.pin = IOMUX_CONF_EOT}
    281 };
    282