1 /* $NetBSD: gb225_slhci.c,v 1.8 2012/11/12 18:00:38 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tetsuya Isaki. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * SL811HS USB host controller for GB-225 Option board of G4250EBX. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/device.h> 39 40 #include <sys/bus.h> 41 #include <machine/cpu.h> 42 43 #include <dev/usb/usb.h> 44 #include <dev/usb/usbdi.h> 45 #include <dev/usb/usbdivar.h> 46 47 #include <dev/ic/sl811hsreg.h> 48 #include <dev/ic/sl811hsvar.h> 49 50 #include <arch/arm/xscale/pxa2x0reg.h> 51 #include <arch/arm/xscale/pxa2x0var.h> 52 #include <arch/evbarm/g42xxeb/g42xxeb_reg.h> 53 #include <arch/evbarm/g42xxeb/g42xxeb_var.h> 54 #include <arch/evbarm/g42xxeb/gb225reg.h> 55 #include <arch/evbarm/g42xxeb/gb225var.h> 56 57 struct slhci_opio_softc { 58 struct slhci_softc sc_sc; 59 60 void *sc_ih; 61 }; 62 63 static int slhci_opio_match(device_t, cfdata_t, void *); 64 static void slhci_opio_attach(device_t, device_t, void *); 65 static void slhci_opio_enable_power(void *, int); 66 static void slhci_opio_enable_intr(void *, int); 67 static int slhci_opio_intr(void *); 68 69 CFATTACH_DECL_NEW(slhci_opio, sizeof(struct slhci_opio_softc), 70 slhci_opio_match, slhci_opio_attach, NULL, NULL); 71 72 #define PORTSIZE (SL11_PORTSIZE*4) 73 74 static int 75 slhci_opio_match(device_t parent, cfdata_t cf, void *aux) 76 { 77 struct obio_attach_args *oba = aux; 78 bus_space_tag_t iot = &pxa2x0_a4x_bs_tag; /* Use special BS funcs */ 79 bus_space_handle_t ioh; 80 struct obio_softc *bsc = device_private(device_parent(parent)); 81 struct pxa2x0_softc *psc; 82 int type; 83 uint32_t reg; 84 85 struct slhci_softc sc; 86 87 obio_peripheral_reset(bsc, 2, 0); 88 psc = device_private(device_parent(bsc->sc_dev)); 89 90 reg = bus_space_read_4(psc->saip.sc_iot, psc->sc_memctl_ioh, 91 MEMCTL_MSC2); 92 #if 0 93 bus_space_write_4(psc->saip.sc_iot, psc->sc_memctl_ioh, MEMCTL_MSC2,xxx) 94 #endif 95 96 97 oba->oba_iot = iot; 98 if (oba->oba_addr == OBIOCF_ADDR_DEFAULT) 99 oba->oba_addr = PXA2X0_CS5_START; 100 if (oba->oba_intr == OBIOCF_INTR_DEFAULT) 101 oba->oba_intr = G4250EBX_INT_EXT2; 102 103 if (bus_space_map(iot, oba->oba_addr, PORTSIZE, 0, &ioh)) 104 return 0; 105 106 /* construct fake softc to call sl811hs */ 107 sc.sc_iot = iot; 108 sc.sc_ioh = ioh; 109 type = sl811hs_find(&sc); 110 111 bus_space_unmap(iot, ioh, PORTSIZE); 112 113 return type >= 0; 114 } 115 116 static void 117 slhci_opio_attach(device_t parent, device_t self, void *aux) 118 { 119 struct slhci_opio_softc *sc = device_private(self); 120 struct obio_attach_args *oba = aux; 121 struct opio_softc *psc = 122 device_private(device_parent(self)); 123 struct obio_softc *bsc = 124 device_private(device_parent(psc->sc_dev)); 125 bus_space_tag_t iot = oba->oba_iot; 126 bus_space_handle_t ioh; 127 128 printf("\n"); 129 130 /* Map I/O space */ 131 if (bus_space_map(iot, oba->oba_addr, PORTSIZE, 0, &ioh)) { 132 aprint_error_dev(self, "can't map I/O space\n"); 133 return; 134 } 135 136 /* Initialize sc */ 137 sc->sc_sc.sc_iot = iot; 138 sc->sc_sc.sc_ioh = ioh; 139 sc->sc_sc.sc_dmat = &pxa2x0_bus_dma_tag; /* XXX */ 140 sc->sc_sc.sc_enable_power = slhci_opio_enable_power; 141 sc->sc_sc.sc_enable_intr = slhci_opio_enable_intr; 142 sc->sc_sc.sc_arg = sc; 143 144 /* Establish the interrupt handler */ 145 sc->sc_ih = obio_intr_establish(bsc, oba->oba_intr, IPL_BIO, 146 IST_LEVEL_HIGH, slhci_opio_intr, sc); 147 if( sc->sc_ih == NULL) { 148 aprint_error_dev(self, "can't establish interrupt\n"); 149 return; 150 } 151 152 #if 0 153 /* Reset controller */ 154 obio_peripheral_reset(bsc, 2, 1); 155 delay(100); 156 obio_peripheral_reset(bsc, 2, 0); 157 delay(40000); 158 #endif 159 160 bus_space_write_1(iot, ioh, SL11_IDX_ADDR, SL11_CTRL); 161 bus_space_write_1(iot, ioh, SL11_IDX_DATA, 0x01); 162 163 /* Attach SL811HS/T */ 164 if (slhci_attach(&sc->sc_sc, self)) 165 return; 166 } 167 168 static void 169 slhci_opio_enable_power(void *arg, int mode) 170 { 171 #if 0 172 struct slhci_opio_softc *sc = arg; 173 bus_space_tag_t iot = sc->sc_sc.sc_iot; 174 uint8_t r; 175 176 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 177 if (mode == POWER_ON) 178 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 179 r | NEREID_CTRL_POWER); 180 else 181 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 182 r & ~NEREID_CTRL_POWER); 183 #endif 184 } 185 186 static void 187 slhci_opio_enable_intr(void *arg, int mode) 188 { 189 struct slhci_opio_softc *sc = arg; 190 struct obio_softc *bsc; 191 192 bsc = device_private(device_parent( 193 device_parent(sc->sc_sc.sc_bus.bdev))); 194 195 if (mode == INTR_ON) 196 obio_intr_unmask(bsc, sc->sc_ih); 197 else 198 obio_intr_mask(bsc, sc->sc_ih); 199 } 200 201 static int 202 slhci_opio_intr(void *arg) 203 { 204 struct slhci_opio_softc *sc = arg; 205 206 return slhci_intr(&sc->sc_sc); 207 } 208