1 /* $NetBSD: sa11x1_pcic.c,v 1.3 2001/09/24 14:29:30 takemura 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 IWAMOTO Toshihiro. 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 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/types.h> 42 #include <sys/conf.h> 43 #include <sys/file.h> 44 #include <sys/device.h> 45 #include <sys/kernel.h> 46 #include <sys/kthread.h> 47 #include <sys/malloc.h> 48 49 #include <machine/bus.h> 50 #ifdef hpcarm 51 #include <machine/platid.h> 52 #include <machine/platid_mask.h> 53 #endif 54 55 #include <dev/pcmcia/pcmciachip.h> 56 #include <dev/pcmcia/pcmciavar.h> 57 #include <arm/sa11x0/sa11x0_reg.h> 58 #include <arm/sa11x0/sa11x0_var.h> 59 #include <arm/sa11x0/sa1111_reg.h> 60 #include <arm/sa11x0/sa1111_var.h> 61 #include <arm/sa11x0/sa11x1_pcicreg.h> 62 #include <arm/sa11x0/sa11xx_pcicvar.h> 63 64 #include "sacpcic.h" 65 66 static int sacpcic_match(struct device *, struct cfdata *, void *); 67 static void sacpcic_attach(struct device *, struct device *, void *); 68 static int sacpcic_print(void *, const char *); 69 static int sacpcic_submatch(struct device *, struct cfdata *, void *); 70 71 static int sacpcic_read(struct sapcic_socket *, int); 72 static void sacpcic_write(struct sapcic_socket *, int, int); 73 static void sacpcic_set_power(struct sapcic_socket *, int); 74 static void sacpcic_clear_intr(int); 75 static void *sacpcic_intr_establish(struct sapcic_socket *, int, 76 int (*)(void *), void *); 77 static void sacpcic_intr_disestablish(struct sapcic_socket *, void *); 78 79 struct sacpcic_softc { 80 struct sapcic_softc sc_pc; 81 bus_space_handle_t sc_ioh; 82 83 struct sapcic_socket sc_socket[2]; 84 }; 85 86 static struct sapcic_tag sacpcic_functions = { 87 sacpcic_read, 88 sacpcic_write, 89 sacpcic_set_power, 90 sacpcic_clear_intr, 91 sacpcic_intr_establish, 92 sacpcic_intr_disestablish 93 }; 94 95 #ifdef hpcarm 96 static int j720_power_capability[] = { 97 SAPCIC_POWER_5V | SAPCIC_POWER_3V, SAPCIC_POWER_3V 98 }; 99 100 static struct platid_data sacpcic_platid_table[] = { 101 { &platid_mask_MACH_HP_JORNADA_720, j720_power_capability }, 102 { &platid_mask_MACH_HP_JORNADA_720JP, j720_power_capability }, 103 { NULL, NULL } 104 }; 105 #endif 106 107 struct cfattach sacpcic_ca = { 108 sizeof(struct sacpcic_softc), sacpcic_match, sacpcic_attach 109 }; 110 111 static int 112 sacpcic_match(parent, cf, aux) 113 struct device *parent; 114 struct cfdata *cf; 115 void *aux; 116 { 117 return (1); 118 } 119 120 static void 121 sacpcic_attach(parent, self, aux) 122 struct device *parent; 123 struct device *self; 124 void *aux; 125 { 126 int i; 127 #ifdef hpcarm 128 int *ip; 129 #endif 130 struct pcmciabus_attach_args paa; 131 struct sacpcic_softc *sc = (struct sacpcic_softc *)self; 132 struct sacc_softc *psc = (struct sacc_softc *)parent; 133 #ifdef hpcarm 134 struct platid_data *p; 135 #endif 136 137 printf("\n"); 138 139 sc->sc_pc.sc_iot = psc->sc_iot; 140 sc->sc_ioh = psc->sc_ioh; 141 #ifdef hpcarm 142 p = platid_search_data(&platid, sacpcic_platid_table); 143 #endif 144 145 for(i = 0; i < 2; i++) { 146 sc->sc_socket[i].sc = (struct sapcic_softc *)sc; 147 sc->sc_socket[i].socket = i; 148 sc->sc_socket[i].pcictag_cookie = psc; 149 sc->sc_socket[i].pcictag = &sacpcic_functions; 150 sc->sc_socket[i].event_thread = NULL; 151 sc->sc_socket[i].event = 0; 152 sc->sc_socket[i].laststatus = SAPCIC_CARD_INVALID; 153 sc->sc_socket[i].shutdown = 0; 154 155 #ifdef hpcarm 156 if (p == NULL) { 157 sc->sc_socket[i].power_capability = SAPCIC_POWER_5V; 158 } else { 159 ip = (int *)p->data; 160 sc->sc_socket[i].power_capability = ip[i]; 161 } 162 #else 163 /* XXX */ 164 sc->sc_socket[i].power_capability = SAPCIC_POWER_5V; 165 #endif 166 167 paa.paa_busname = "pcmcia"; 168 paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions; 169 paa.pch = (pcmcia_chipset_handle_t)&sc->sc_socket[i]; 170 paa.iobase = 0; 171 paa.iosize = 0x4000000; 172 173 sc->sc_socket[i].pcmcia = 174 (struct device *)config_found_sm(&sc->sc_pc.sc_dev, 175 &paa, sacpcic_print, sacpcic_submatch); 176 177 sacc_intr_establish((sacc_chipset_tag_t)psc, 178 i ? IRQ_S1_CDVALID : IRQ_S0_CDVALID, 179 IST_EDGE_RAISE, IPL_BIO, sapcic_intr, 180 &sc->sc_socket[i]); 181 182 /* schedule kthread creation */ 183 kthread_create(sapcic_kthread_create, &sc->sc_socket[i]); 184 185 #if 0 /* XXX */ 186 /* establish_intr should be after creating the kthread */ 187 config_interrupt(&sc->sc_socket[i], sacpcic_config_intr); 188 #endif 189 } 190 } 191 192 static int 193 sacpcic_print(aux, name) 194 void *aux; 195 const char *name; 196 { 197 return (UNCONF); 198 } 199 200 static int 201 sacpcic_submatch(parent, cf, aux) 202 struct device *parent; 203 struct cfdata *cf; 204 void *aux; 205 { 206 return (*cf->cf_attach->ca_match)(parent, cf, aux); 207 } 208 209 210 static int 211 sacpcic_read(so, reg) 212 struct sapcic_socket *so; 213 int reg; 214 { 215 int cr, bit; 216 struct sacpcic_softc *sc = (struct sacpcic_softc *)so->sc; 217 218 cr = bus_space_read_4(sc->sc_pc.sc_iot, sc->sc_ioh, SACPCIC_SR); 219 220 switch (reg) { 221 case SAPCIC_STATUS_CARD: 222 bit = (so->socket ? SR_S1_CARDDETECT : SR_S0_CARDDETECT) & cr; 223 if (bit) 224 return SAPCIC_CARD_INVALID; 225 else 226 return SAPCIC_CARD_VALID; 227 228 case SAPCIC_STATUS_VS1: 229 bit = (so->socket ? SR_S1_VS1 : SR_S0_VS1); 230 return (bit & cr); 231 232 case SAPCIC_STATUS_VS2: 233 bit = (so->socket ? SR_S1_VS2 : SR_S0_VS2); 234 return (bit & cr); 235 236 case SAPCIC_STATUS_READY: 237 bit = (so->socket ? SR_S1_READY : SR_S0_READY); 238 return (bit & cr); 239 240 default: 241 panic("sacpcic_read: bogus register\n"); 242 } 243 } 244 245 static void 246 sacpcic_write(so, reg, arg) 247 struct sapcic_socket *so; 248 int reg; 249 int arg; 250 { 251 int s, oldvalue, newvalue, mask; 252 struct sacpcic_softc *sc = (struct sacpcic_softc *)so->sc; 253 254 s = splhigh(); 255 oldvalue = bus_space_read_4(sc->sc_pc.sc_iot, sc->sc_ioh, SACPCIC_CR); 256 257 switch (reg) { 258 case SAPCIC_CONTROL_RESET: 259 mask = so->socket ? CR_S1_RST : CR_S0_RST; 260 261 newvalue = (oldvalue & ~mask) | (arg ? mask : 0); 262 break; 263 264 case SAPCIC_CONTROL_LINEENABLE: 265 mask = so->socket ? CR_S1_FLT : CR_S0_FLT; 266 267 newvalue = (oldvalue & ~mask) | (arg ? mask : 0); 268 break; 269 270 case SAPCIC_CONTROL_WAITENABLE: 271 mask = so->socket ? CR_S1_PWAITEN : CR_S0_PWAITEN; 272 273 newvalue = (oldvalue & ~mask) | (arg ? mask : 0); 274 break; 275 276 case SAPCIC_CONTROL_POWERSELECT: 277 mask = so->socket ? CR_S1_PSE : CR_S0_PSE; 278 newvalue = oldvalue & ~mask; 279 280 switch (arg) { 281 case SAPCIC_POWER_3V: 282 break; 283 case SAPCIC_POWER_5V: 284 newvalue |= mask; 285 break; 286 default: 287 splx(s); 288 panic("sacpcic_write: bogus arg"); 289 } 290 break; 291 292 default: 293 splx(s); 294 panic("sacpcic_write: bogus register"); 295 } 296 bus_space_write_4(sc->sc_pc.sc_iot, sc->sc_ioh, SACPCIC_CR, newvalue); 297 splx(s); 298 } 299 300 static void 301 sacpcic_set_power(so, arg) 302 struct sapcic_socket *so; 303 int arg; 304 { 305 /* XXX this should go to dev/jornada720.c */ 306 int newval, oldval, s; 307 struct sacc_softc *sc = so->pcictag_cookie; 308 309 /* XXX this isn't well confirmed. DANGER DANGER */ 310 switch (arg) { 311 case SAPCIC_POWER_OFF: 312 newval = 0; 313 break; 314 case SAPCIC_POWER_3V: 315 newval = 2; 316 break; 317 case SAPCIC_POWER_5V: 318 newval = 1; 319 break; 320 default: 321 panic("sacpcic_set_power: bogus arg\n"); 322 } 323 324 s = splbio(); 325 oldval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 326 SACCGPIOA_DVR); 327 switch (so->socket) { 328 case 0: 329 newval = newval | (oldval & 0xc); 330 break; 331 case 1: 332 newval = (newval << 2) | (oldval & 3); 333 break; 334 default: 335 splx(s); 336 panic("sacpcic_set_power\n"); 337 } 338 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCGPIOA_DVR, newval); 339 splx(s); 340 } 341 342 static void 343 sacpcic_clear_intr(arg) 344 { 345 /* sacc_intr_dispatch takes care of intr status */ 346 } 347 348 static void * 349 sacpcic_intr_establish(so, level, ih_fun, ih_arg) 350 struct sapcic_socket *so; 351 int level; 352 int (*ih_fun)(void *); 353 void *ih_arg; 354 { 355 int irq; 356 357 irq = so->socket ? IRQ_S1_READY : IRQ_S0_READY; 358 return (sacc_intr_establish((sacc_chipset_tag_t)so->pcictag_cookie, irq, 359 IST_EDGE_FALL, level, ih_fun, ih_arg)); 360 } 361 362 static void 363 sacpcic_intr_disestablish(so, ih) 364 struct sapcic_socket *so; 365 void *ih; 366 { 367 sacc_intr_disestablish((sacc_chipset_tag_t)so->pcictag_cookie, ih); 368 } 369