1/* $Id: njata_cardbus.c,v 1.15 2011/08/01 11:20:28 drochner Exp $ */ 2 3/* 4 * Copyright (c) 2006 ITOH Yasufumi. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: njata_cardbus.c,v 1.14 2011/02/21 02:31:59 itohy Exp $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/kernel.h> 35#include <sys/device.h> 36 37#include <sys/bus.h> 38#include <sys/intr.h> 39 40#include <dev/cardbus/cardbusvar.h> 41#include <dev/pci/pcidevs.h> 42 43#include <dev/ata/atavar.h> 44#include <dev/ic/wdcreg.h> 45#include <dev/ic/wdcvar.h> 46 47#include <dev/ic/ninjaata32reg.h> 48#include <dev/ic/ninjaata32var.h> 49 50#define NJATA32_CARDBUS_BASEADDR_IO PCI_BAR0 51#define NJATA32_CARDBUS_BASEADDR_MEM PCI_BAR1 52 53struct njata32_cardbus_softc { 54 struct njata32_softc sc_njata32; 55 56 /* CardBus-specific goo */ 57 cardbus_devfunc_t sc_ct; /* our CardBus devfuncs */ 58 pcitag_t sc_tag; 59 60 bus_space_handle_t sc_regmaph; 61 bus_size_t sc_regmap_size; 62}; 63 64static const struct njata32_cardbus_product *njata_cardbus_lookup 65 (const struct cardbus_attach_args *); 66static int njata_cardbus_match(device_t, cfdata_t, void *); 67static void njata_cardbus_attach(device_t, device_t, void *); 68static int njata_cardbus_detach(device_t, int); 69 70CFATTACH_DECL_NEW(njata_cardbus, sizeof(struct njata32_cardbus_softc), 71 njata_cardbus_match, njata_cardbus_attach, njata_cardbus_detach, NULL); 72 73static const struct njata32_cardbus_product { 74 pci_vendor_id_t p_vendor; 75 pci_product_id_t p_product; 76 uint8_t p_flags; 77#define NJATA32_FL_IOMAP_ONLY 1 /* registers are only in the I/O map */ 78} njata32_cardbus_products[] = { 79 { PCI_VENDOR_IODATA, PCI_PRODUCT_IODATA_CBIDE2, 80 0 }, 81 { PCI_VENDOR_WORKBIT, PCI_PRODUCT_WORKBIT_NJATA32BI, 82 0 }, 83 { PCI_VENDOR_WORKBIT, PCI_PRODUCT_WORKBIT_NJATA32BI_KME, 84 0 }, 85 { PCI_VENDOR_WORKBIT, PCI_PRODUCT_WORKBIT_NPATA32_CF32A, 86 NJATA32_FL_IOMAP_ONLY }, 87 { PCI_VENDOR_WORKBIT, PCI_PRODUCT_WORKBIT_NPATA32_CF32A_BUFFALO, 88 NJATA32_FL_IOMAP_ONLY }, 89 { PCI_VENDOR_WORKBIT, PCI_PRODUCT_WORKBIT_NPATA32_KME, 90 NJATA32_FL_IOMAP_ONLY }, 91 92 { PCI_VENDOR_INVALID, 0, 93 0 } 94}; 95 96static const struct njata32_cardbus_product * 97njata_cardbus_lookup(const struct cardbus_attach_args *ca) 98{ 99 const struct njata32_cardbus_product *p; 100 101 for (p = njata32_cardbus_products; 102 p->p_vendor != PCI_VENDOR_INVALID; p++) { 103 if (PCI_VENDOR(ca->ca_id) == p->p_vendor && 104 PCI_PRODUCT(ca->ca_id) == p->p_product) 105 return p; 106 } 107 108 return NULL; 109} 110 111static int 112njata_cardbus_match(device_t parent, cfdata_t match, void *aux) 113{ 114 struct cardbus_attach_args *ca = aux; 115 116 if (njata_cardbus_lookup(ca)) 117 return 1; 118 119 return 0; 120} 121 122static void 123njata_cardbus_attach(device_t parent, device_t self, void *aux) 124{ 125 struct cardbus_attach_args *ca = aux; 126 struct njata32_cardbus_softc *csc = device_private(self); 127 struct njata32_softc *sc = &csc->sc_njata32; 128 const struct njata32_cardbus_product *prod; 129 cardbus_devfunc_t ct = ca->ca_ct; 130 pcireg_t reg; 131 int csr; 132 uint8_t latency = 0x20; 133 134 sc->sc_wdcdev.sc_atac.atac_dev = self; 135 if ((prod = njata_cardbus_lookup(ca)) == NULL) 136 panic("njata_cardbus_attach"); 137 138 aprint_normal(": Workbit NinjaATA-32 IDE controller\n"); 139 140 csc->sc_ct = ct; 141 csc->sc_tag = ca->ca_tag; 142 143 /* 144 * Map the device. 145 */ 146 csr = PCI_COMMAND_MASTER_ENABLE; 147 148 /* 149 * Map registers. 150 * Try memory map first, and then try I/O. 151 */ 152 if ((prod->p_flags & NJATA32_FL_IOMAP_ONLY) == 0 && 153 Cardbus_mapreg_map(csc->sc_ct, NJATA32_CARDBUS_BASEADDR_MEM, 154 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, 155 &NJATA32_REGT(sc), &csc->sc_regmaph, NULL, &csc->sc_regmap_size) 156 == 0) { 157 if (bus_space_subregion(NJATA32_REGT(sc), csc->sc_regmaph, 158 NJATA32_MEMOFFSET_REG, NJATA32_REGSIZE, &NJATA32_REGH(sc)) 159 != 0) { 160 /* failed -- undo map and try I/O */ 161 Cardbus_mapreg_unmap(csc->sc_ct, 162 NJATA32_CARDBUS_BASEADDR_MEM, NJATA32_REGT(sc), 163 csc->sc_regmaph, csc->sc_regmap_size); 164 goto try_io; 165 } 166#ifdef NJATA32_DEBUG 167 aprint_normal("%s: memory space mapped, size %u\n", 168 NJATA32NAME(sc), (unsigned)csc->sc_regmap_size); 169#endif 170 csr |= PCI_COMMAND_MEM_ENABLE; 171 sc->sc_flags = NJATA32_MEM_MAPPED; 172 } else { 173 try_io: 174 if (Cardbus_mapreg_map(csc->sc_ct, NJATA32_CARDBUS_BASEADDR_IO, 175 PCI_MAPREG_TYPE_IO, 0, &NJATA32_REGT(sc), 176 &NJATA32_REGH(sc), NULL, &csc->sc_regmap_size) == 0) { 177#ifdef NJATA32_DEBUG 178 aprint_normal("%s: io space mapped, size %u\n", 179 NJATA32NAME(sc), (unsigned)csc->sc_regmap_size); 180#endif 181 csr |= PCI_COMMAND_IO_ENABLE; 182 sc->sc_flags = NJATA32_IO_MAPPED; 183 } else { 184 aprint_error("%s: unable to map device registers\n", 185 NJATA32NAME(sc)); 186 return; 187 } 188 } 189 190 /* Enable the appropriate bits in the PCI CSR. */ 191 reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG); 192 reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE); 193 reg |= csr; 194 Cardbus_conf_write(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg); 195 196 /* 197 * Make sure the latency timer is set to some reasonable 198 * value. 199 */ 200 reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_BHLC_REG); 201 if (PCI_LATTIMER(reg) < latency) { 202 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); 203 reg |= (latency << PCI_LATTIMER_SHIFT); 204 Cardbus_conf_write(ct, ca->ca_tag, PCI_BHLC_REG, reg); 205 } 206 207 sc->sc_dmat = ca->ca_dmat; 208 209 /* 210 * Establish the interrupt. 211 */ 212 sc->sc_ih = Cardbus_intr_establish(ct, IPL_BIO, njata32_intr, sc); 213 if (sc->sc_ih == NULL) { 214 aprint_error("%s: unable to establish interrupt\n", 215 NJATA32NAME(sc)); 216 return; 217 } 218 219 /* attach */ 220 njata32_attach(sc); 221} 222 223static int 224njata_cardbus_detach(device_t self, int flags) 225{ 226 struct njata32_cardbus_softc *csc = device_private(self); 227 struct njata32_softc *sc = &csc->sc_njata32; 228 int rv; 229 230 rv = njata32_detach(sc, flags); 231 if (rv) 232 return rv; 233 234 if (sc->sc_ih) 235 Cardbus_intr_disestablish(csc->sc_ct, sc->sc_ih); 236 237 if (sc->sc_flags & NJATA32_IO_MAPPED) 238 Cardbus_mapreg_unmap(csc->sc_ct, NJATA32_CARDBUS_BASEADDR_IO, 239 NJATA32_REGT(sc), NJATA32_REGH(sc), csc->sc_regmap_size); 240 if (sc->sc_flags & NJATA32_MEM_MAPPED) 241 Cardbus_mapreg_unmap(csc->sc_ct, NJATA32_CARDBUS_BASEADDR_MEM, 242 NJATA32_REGT(sc), csc->sc_regmaph, csc->sc_regmap_size); 243 244 return 0; 245} 246