slhci_intio.c revision 1.13
1/* $NetBSD: slhci_intio.c,v 1.13 2010/05/08 02:48:31 isaki 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 * USB part of Nereid Ethernet/USB/Memory board 34 */ 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: slhci_intio.c,v 1.13 2010/05/08 02:48:31 isaki Exp $"); 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/device.h> 42 43#include <machine/bus.h> 44#include <machine/cpu.h> 45 46#include <dev/usb/usb.h> 47#include <dev/usb/usbdi.h> 48#include <dev/usb/usbdivar.h> 49 50#include <dev/ic/sl811hsreg.h> 51#include <dev/ic/sl811hsvar.h> 52 53#include <arch/x68k/dev/intiovar.h> 54 55#include <arch/x68k/dev/slhci_intio_var.h> 56 57static int slhci_intio_match(device_t, cfdata_t, void *); 58static void slhci_intio_attach(device_t, device_t, void *); 59static void slhci_intio_enable_power(void *, enum power_change); 60static void slhci_intio_enable_intr(void *, int); 61 62CFATTACH_DECL_NEW(slhci_intio, sizeof(struct slhci_intio_softc), 63 slhci_intio_match, slhci_intio_attach, NULL, NULL); 64 65#define INTR_ON 1 66#define INTR_OFF 0 67 68static int 69slhci_intio_match(device_t parent, cfdata_t cf, void *aux) 70{ 71 struct intio_attach_args *ia = aux; 72 bus_space_tag_t iot = ia->ia_bst; 73 bus_space_handle_t ioh; 74 bus_space_handle_t nch; 75 int nc_addr; 76 int nc_size; 77 78 if (ia->ia_addr == INTIOCF_ADDR_DEFAULT) 79 ia->ia_addr = SLHCI_INTIO_ADDR1; 80 if (ia->ia_intr == INTIOCF_INTR_DEFAULT) 81 ia->ia_intr = SLHCI_INTIO_INTR1; 82 83 /* fixed parameters */ 84 if ( !(ia->ia_addr == SLHCI_INTIO_ADDR1 && 85 ia->ia_intr == SLHCI_INTIO_INTR1 ) && 86 !(ia->ia_addr == SLHCI_INTIO_ADDR2 && 87 ia->ia_intr == SLHCI_INTIO_INTR2 ) ) 88 return 0; 89 90 /* Whether the control port is accessible or not */ 91 nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET; 92 nc_size = 0x02; 93 if (badbaddr((void *)IIOV(nc_addr))) 94 return 0; 95 96 /* Map two I/O spaces */ 97 ia->ia_size = SL11_PORTSIZE * 2; 98 if (bus_space_map(iot, ia->ia_addr, ia->ia_size, 99 BUS_SPACE_MAP_SHIFTED, &ioh)) 100 return 0; 101 102 if (bus_space_map(iot, nc_addr, nc_size, 103 BUS_SPACE_MAP_SHIFTED, &nch)) 104 return 0; 105 106 bus_space_unmap(iot, ioh, ia->ia_size); 107 bus_space_unmap(iot, nch, nc_size); 108 109 return 1; 110} 111 112static void 113slhci_intio_attach(device_t parent, device_t self, void *aux) 114{ 115 struct slhci_intio_softc *isc = device_private(self); 116 struct slhci_softc *sc = &isc->sc_sc; 117 struct intio_attach_args *ia = aux; 118 bus_space_tag_t iot = ia->ia_bst; 119 bus_space_handle_t ioh; 120 int nc_addr; 121 int nc_size; 122 123 sc->sc_dev = self; 124 sc->sc_bus.hci_private = sc; 125 126 printf(": Nereid USB\n"); 127 128 /* Map I/O space */ 129 if (bus_space_map(iot, ia->ia_addr, SL11_PORTSIZE * 2, 130 BUS_SPACE_MAP_SHIFTED, &ioh)) { 131 printf("%s: can't map I/O space\n", 132 device_xname(self)); 133 return; 134 } 135 136 nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET; 137 nc_size = 0x02; 138 if (bus_space_map(iot, nc_addr, nc_size, 139 BUS_SPACE_MAP_SHIFTED, &isc->sc_nch)) { 140 printf("%s: can't map I/O control space\n", 141 device_xname(self)); 142 return; 143 } 144 145 /* Initialize sc */ 146 slhci_preinit(sc, slhci_intio_enable_power, iot, ioh, 30, 147 SL11_IDX_DATA); 148 149 /* Establish the interrupt handler */ 150 if (intio_intr_establish(ia->ia_intr, "slhci", slhci_intr, sc)) { 151 printf("%s: can't establish interrupt\n", 152 device_xname(self)); 153 return; 154 } 155 156 /* Reset controller */ 157 bus_space_write_1(iot, isc->sc_nch, NEREID_CTRL, NEREID_CTRL_RESET); 158 delay(40000); 159 160 slhci_intio_enable_intr(sc, INTR_ON); 161 162 /* Attach SL811HS/T */ 163 if (slhci_attach(sc)) 164 return; 165} 166 167static void 168slhci_intio_enable_power(void *arg, enum power_change mode) 169{ 170 struct slhci_intio_softc *sc = arg; 171 bus_space_tag_t iot = sc->sc_sc.sc_iot; 172 u_int8_t r; 173 174 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 175 if (mode == POWER_ON) 176 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 177 r | NEREID_CTRL_POWER); 178 else 179 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 180 r & ~NEREID_CTRL_POWER); 181} 182 183static void 184slhci_intio_enable_intr(void *arg, int mode) 185{ 186 struct slhci_intio_softc *sc = arg; 187 bus_space_tag_t iot = sc->sc_sc.sc_iot; 188 u_int8_t r; 189 190 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 191 if (mode == INTR_ON) 192 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 193 r | NEREID_CTRL_INTR); 194 else 195 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 196 r & ~NEREID_CTRL_INTR); 197} 198 199