slhci_intio.c revision 1.9
1/* $NetBSD: slhci_intio.c,v 1.9 2007/10/17 19:58:03 garbled 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * USB part of Nereid Ethernet/USB/Memory board 41 */ 42 43#include <sys/cdefs.h> 44__KERNEL_RCSID(0, "$NetBSD: slhci_intio.c,v 1.9 2007/10/17 19:58:03 garbled Exp $"); 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/device.h> 49 50#include <machine/bus.h> 51#include <machine/cpu.h> 52 53#include <dev/usb/usb.h> 54#include <dev/usb/usbdi.h> 55#include <dev/usb/usbdivar.h> 56 57#include <dev/ic/sl811hsreg.h> 58#include <dev/ic/sl811hsvar.h> 59 60#include <arch/x68k/dev/intiovar.h> 61 62#include <arch/x68k/dev/slhci_intio_var.h> 63 64static int slhci_intio_match(struct device *, struct cfdata *, void *); 65static void slhci_intio_attach(struct device *, struct device *, void *); 66static void slhci_intio_enable_power(void *, enum power_change); 67static void slhci_intio_enable_intr(void *, int); 68 69CFATTACH_DECL(slhci_intio, sizeof(struct slhci_intio_softc), 70 slhci_intio_match, slhci_intio_attach, NULL, NULL); 71 72#define INTR_ON 1 73#define INTR_OFF 0 74 75static int 76slhci_intio_match(struct device *parent, struct cfdata *cf, void *aux) 77{ 78 struct intio_attach_args *ia = aux; 79 bus_space_tag_t iot = ia->ia_bst; 80 bus_space_handle_t ioh; 81 bus_space_handle_t nch; 82 int nc_addr; 83 int nc_size; 84 85 if (ia->ia_addr == INTIOCF_ADDR_DEFAULT) 86 ia->ia_addr = SLHCI_INTIO_ADDR1; 87 if (ia->ia_intr == INTIOCF_INTR_DEFAULT) 88 ia->ia_intr = SLHCI_INTIO_INTR1; 89 90 /* fixed parameters */ 91 if ( !(ia->ia_addr == SLHCI_INTIO_ADDR1 && 92 ia->ia_intr == SLHCI_INTIO_INTR1 ) && 93 !(ia->ia_addr == SLHCI_INTIO_ADDR2 && 94 ia->ia_intr == SLHCI_INTIO_INTR2 ) ) 95 return 0; 96 97 /* Whether the control port is accessible or not */ 98 nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET; 99 nc_size = 0x02; 100 if (badbaddr(INTIO_ADDR(nc_addr))) 101 return 0; 102 103 /* Map two I/O spaces */ 104 ia->ia_size = SL11_PORTSIZE * 2; 105 if (bus_space_map(iot, ia->ia_addr, ia->ia_size, 106 BUS_SPACE_MAP_SHIFTED, &ioh)) 107 return 0; 108 109 if (bus_space_map(iot, nc_addr, nc_size, 110 BUS_SPACE_MAP_SHIFTED, &nch)) 111 return 0; 112 113 bus_space_unmap(iot, ioh, ia->ia_size); 114 bus_space_unmap(iot, nch, nc_size); 115 116 return 1; 117} 118 119static void 120slhci_intio_attach(struct device *parent, struct device *self, void *aux) 121{ 122 struct slhci_intio_softc *sc = (struct slhci_intio_softc *)self; 123 struct intio_attach_args *ia = aux; 124 bus_space_tag_t iot = ia->ia_bst; 125 bus_space_handle_t ioh; 126 int nc_addr; 127 int nc_size; 128 129 printf(": Nereid USB\n"); 130 131 /* Map I/O space */ 132 if (bus_space_map(iot, ia->ia_addr, SL11_PORTSIZE * 2, 133 BUS_SPACE_MAP_SHIFTED, &ioh)) { 134 printf("%s: can't map I/O space\n", 135 sc->sc_sc.sc_bus.bdev.dv_xname); 136 return; 137 } 138 139 nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET; 140 nc_size = 0x02; 141 if (bus_space_map(iot, nc_addr, nc_size, 142 BUS_SPACE_MAP_SHIFTED, &sc->sc_nch)) { 143 printf("%s: can't map I/O control space\n", 144 sc->sc_sc.sc_bus.bdev.dv_xname); 145 return; 146 } 147 148 /* Initialize sc */ 149 slhci_preinit(&sc->sc_sc, slhci_intio_enable_power, iot, ioh, 30, 150 SL11_IDX_DATA); 151 152 /* Establish the interrupt handler */ 153 if (intio_intr_establish(ia->ia_intr, "slhci", slhci_intr, sc)) { 154 printf("%s: can't establish interrupt\n", 155 sc->sc_sc.sc_bus.bdev.dv_xname); 156 return; 157 } 158 159 /* Reset controller */ 160 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, NEREID_CTRL_RESET); 161 delay(40000); 162 163 slhci_intio_enable_intr(sc, INTR_ON); 164 165 /* Attach SL811HS/T */ 166 if (slhci_attach(&sc->sc_sc)) 167 return; 168} 169 170static void 171slhci_intio_enable_power(void *arg, enum power_change mode) 172{ 173 struct slhci_intio_softc *sc = arg; 174 bus_space_tag_t iot = sc->sc_sc.sc_iot; 175 u_int8_t r; 176 177 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 178 if (mode == POWER_ON) 179 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 180 r | NEREID_CTRL_POWER); 181 else 182 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 183 r & ~NEREID_CTRL_POWER); 184} 185 186static void 187slhci_intio_enable_intr(void *arg, int mode) 188{ 189 struct slhci_intio_softc *sc = arg; 190 bus_space_tag_t iot = sc->sc_sc.sc_iot; 191 u_int8_t r; 192 193 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 194 if (mode == INTR_ON) 195 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 196 r | NEREID_CTRL_INTR); 197 else 198 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 199 r & ~NEREID_CTRL_INTR); 200} 201 202