11414Scindi/* $NetBSD: slhci_intio.c,v 1.13 2010/05/08 02:48:31 isaki Exp $ */ 21414Scindi 31414Scindi/* 41414Scindi * Copyright (c) 2001 The NetBSD Foundation, Inc. 51414Scindi * All rights reserved. 61414Scindi * 71414Scindi * This code is derived from software contributed to The NetBSD Foundation 81414Scindi * by Tetsuya Isaki. 91414Scindi * 101414Scindi * Redistribution and use in source and binary forms, with or without 111414Scindi * modification, are permitted provided that the following conditions 121414Scindi * are met: 131414Scindi * 1. Redistributions of source code must retain the above copyright 141414Scindi * notice, this list of conditions and the following disclaimer. 151414Scindi * 2. Redistributions in binary form must reproduce the above copyright 161414Scindi * notice, this list of conditions and the following disclaimer in the 171414Scindi * documentation and/or other materials provided with the distribution. 181414Scindi * 191414Scindi * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201414Scindi * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211414Scindi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221414Scindi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231414Scindi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241414Scindi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251414Scindi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261414Scindi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271414Scindi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281539Scindi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291414Scindi * POSSIBILITY OF SUCH DAMAGE. 301414Scindi */ 311414Scindi 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 SL811 port is accessible or not */ 91 if (badaddr((void *)IIOV(ia->ia_addr))) 92 return 0; 93 94 /* Whether the control port is accessible or not */ 95 nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET; 96 nc_size = 0x02; 97 if (badbaddr((void *)IIOV(nc_addr))) 98 return 0; 99 100 /* Map two I/O spaces */ 101 ia->ia_size = SL11_PORTSIZE * 2; 102 if (bus_space_map(iot, ia->ia_addr, ia->ia_size, 103 BUS_SPACE_MAP_SHIFTED, &ioh)) 104 return 0; 105 106 if (bus_space_map(iot, nc_addr, nc_size, 107 BUS_SPACE_MAP_SHIFTED, &nch)) 108 return 0; 109 110 bus_space_unmap(iot, ioh, ia->ia_size); 111 bus_space_unmap(iot, nch, nc_size); 112 113 return 1; 114} 115 116static void 117slhci_intio_attach(device_t parent, device_t self, void *aux) 118{ 119 struct slhci_intio_softc *isc = device_private(self); 120 struct slhci_softc *sc = &isc->sc_sc; 121 struct intio_attach_args *ia = aux; 122 bus_space_tag_t iot = ia->ia_bst; 123 bus_space_handle_t ioh; 124 int nc_addr; 125 int nc_size; 126 127 sc->sc_dev = self; 128 sc->sc_bus.hci_private = sc; 129 130 printf(": Nereid USB\n"); 131 132 /* Map I/O space */ 133 if (bus_space_map(iot, ia->ia_addr, SL11_PORTSIZE * 2, 134 BUS_SPACE_MAP_SHIFTED, &ioh)) { 135 printf("%s: can't map I/O space\n", 136 device_xname(self)); 137 return; 138 } 139 140 nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET; 141 nc_size = 0x02; 142 if (bus_space_map(iot, nc_addr, nc_size, 143 BUS_SPACE_MAP_SHIFTED, &isc->sc_nch)) { 144 printf("%s: can't map I/O control space\n", 145 device_xname(self)); 146 return; 147 } 148 149 /* Initialize sc */ 150 slhci_preinit(sc, slhci_intio_enable_power, iot, ioh, 30, 151 SL11_IDX_DATA); 152 153 /* Establish the interrupt handler */ 154 if (intio_intr_establish(ia->ia_intr, "slhci", slhci_intr, sc)) { 155 printf("%s: can't establish interrupt\n", 156 device_xname(self)); 157 return; 158 } 159 160 /* Reset controller */ 161 bus_space_write_1(iot, isc->sc_nch, NEREID_CTRL, NEREID_CTRL_RESET); 162 delay(40000); 163 164 slhci_intio_enable_intr(sc, INTR_ON); 165 166 /* Attach SL811HS/T */ 167 if (slhci_attach(sc)) 168 return; 169} 170 171static void 172slhci_intio_enable_power(void *arg, enum power_change mode) 173{ 174 struct slhci_intio_softc *sc = arg; 175 bus_space_tag_t iot = sc->sc_sc.sc_iot; 176 u_int8_t r; 177 178 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 179 if (mode == POWER_ON) 180 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 181 r | NEREID_CTRL_POWER); 182 else 183 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 184 r & ~NEREID_CTRL_POWER); 185} 186 187static void 188slhci_intio_enable_intr(void *arg, int mode) 189{ 190 struct slhci_intio_softc *sc = arg; 191 bus_space_tag_t iot = sc->sc_sc.sc_iot; 192 u_int8_t r; 193 194 r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL); 195 if (mode == INTR_ON) 196 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 197 r | NEREID_CTRL_INTR); 198 else 199 bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, 200 r & ~NEREID_CTRL_INTR); 201} 202 203