1 /* 2 * Copyright (c) 2002, 2003, 2005 Genetec corp. All rights reserved. 3 * 4 * PCMCIA/CF support for TWINTAIL (G4255EB) 5 * Written by Hiroyuki Bessho for Genetec corp. 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 * 3. The name of Genetec corp. may not be used to endorse 16 * or promote products derived from this software without specific prior 17 * written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND 20 * 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 GENETEC CORP. 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 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/device.h> 36 #include <sys/callout.h> 37 #include <sys/kernel.h> 38 #include <sys/kthread.h> 39 #include <uvm/uvm.h> 40 41 #include <sys/bus.h> 42 #include <machine/intr.h> 43 44 #include <dev/pcmcia/pcmciareg.h> 45 #include <dev/pcmcia/pcmciavar.h> 46 #include <dev/pcmcia/pcmciachip.h> 47 48 #include <arch/arm/xscale/pxa2x0var.h> 49 #include <arch/arm/xscale/pxa2x0reg.h> 50 #include <arch/arm/sa11x0/sa11xx_pcicvar.h> 51 #include <arch/evbarm/g42xxeb/g42xxeb_reg.h> 52 #include <arch/evbarm/g42xxeb/g42xxeb_var.h> 53 #include <arch/evbarm/g42xxeb/gb225reg.h> 54 #include <arch/evbarm/g42xxeb/gb225var.h> 55 56 57 //#define DONT_USE_CARD_DETECT_INTR 58 59 #define PCMCIA_INT G42XXEB_INT_EXT1 60 #define CF_INT G42XXEB_INT_EXT0 61 62 #ifdef DEBUG 63 #define DPRINTF(arg) printf arg 64 #else 65 #define DPRINTF(arg) 66 #endif 67 68 struct opcic_softc; 69 70 struct opcic_socket { 71 struct sapcic_socket ss; /* inherit socket for sa11x0 pcic */ 72 73 #if 0 74 int voltage; /* card power voltage selected by 75 upper layer */ 76 #endif 77 }; 78 79 struct opcic_softc { 80 struct sapcic_softc sc_pc; /* inherit SA11xx pcic */ 81 82 struct opcic_socket sc_socket[2]; 83 int sc_cards; 84 bus_space_handle_t sc_memctl_ioh; 85 }; 86 87 static int opcic_match(device_t, cfdata_t, void *); 88 static void opcic_attach(device_t, device_t, void *); 89 static int opcic_print(void *, const char *); 90 91 static int opcic_read(struct sapcic_socket *, int); 92 static void opcic_write(struct sapcic_socket *, int, int); 93 static void opcic_set_power(struct sapcic_socket *, int); 94 static void opcic_clear_intr(int); 95 static void *opcic_intr_establish(struct sapcic_socket *, int, 96 int (*)(void *), void *); 97 static void opcic_intr_disestablish(struct sapcic_socket *, void *); 98 #ifndef DONT_USE_CARD_DETECT_INTR 99 static int opcic_card_detect(void *, int); 100 #endif 101 102 CFATTACH_DECL_NEW(opcic, sizeof(struct opcic_softc), 103 opcic_match, opcic_attach, NULL, NULL); 104 105 static struct sapcic_tag opcic_tag = { 106 opcic_read, 107 opcic_write, 108 opcic_set_power, 109 opcic_clear_intr, 110 opcic_intr_establish, 111 opcic_intr_disestablish, 112 }; 113 114 115 #define HAVE_CARD(r) (((r)&CARDDET_DET)==0) 116 117 static inline uint8_t 118 opcic_read_card_status(struct opcic_socket *so) 119 { 120 struct opcic_softc *sc = (struct opcic_softc *)(so->ss.sc); 121 struct opio_softc *osc = 122 device_private(device_parent(sc->sc_pc.sc_dev)); 123 124 return bus_space_read_1(osc->sc_iot, osc->sc_ioh, 125 GB225_CFDET + 2 * so->ss.socket); 126 127 } 128 129 static int 130 opcic_match(device_t parent, cfdata_t cf, void *aux) 131 { 132 return 1; 133 } 134 135 static void 136 opcic_attach(device_t parent, device_t self, void *aux) 137 { 138 int i; 139 struct pcmciabus_attach_args paa; 140 struct opcic_softc *sc = device_private(self); 141 struct opio_softc *psc = device_private(parent); 142 struct obio_softc *bsd = device_private(device_parent(parent)); 143 bus_space_handle_t memctl_ioh = bsd->sc_memctl_ioh; 144 bus_space_tag_t iot = psc->sc_iot; 145 146 printf("\n"); 147 148 /* tell PXA2X0 that we have two sockets */ 149 #if 0 150 bus_space_write_4(iot, memctl_ioh, MEMCTL_MECR, MECR_NOS); 151 #else 152 bus_space_write_4(iot, memctl_ioh, MEMCTL_MECR, MECR_CIT|MECR_NOS); 153 #endif 154 sc->sc_pc.sc_iot = psc->sc_iot; 155 sc->sc_memctl_ioh = memctl_ioh; 156 157 sc->sc_cards = 0; 158 159 for(i = 0; i < 2; i++) { 160 sc->sc_socket[i].ss.sc = &sc->sc_pc; 161 sc->sc_socket[i].ss.socket = i; 162 sc->sc_socket[i].ss.pcictag_cookie = NULL; 163 sc->sc_socket[i].ss.pcictag = &opcic_tag; 164 sc->sc_socket[i].ss.event_thread = NULL; 165 sc->sc_socket[i].ss.event = 0; 166 sc->sc_socket[i].ss.laststatus = CARDDET_NOCARD; 167 sc->sc_socket[i].ss.shutdown = 0; 168 169 sc->sc_socket[i].ss.power_capability = 170 (SAPCIC_POWER_5V|SAPCIC_POWER_3V); 171 172 bus_space_write_4(iot, memctl_ioh, MEMCTL_MCIO(i), 173 MC_TIMING_VAL(1,1,1)); 174 #if 0 175 bus_space_write_4(iot, memctl_ioh, MEMCTL_MCATT(i), 176 MC_TIMING_VAL(31,31,31)); 177 #endif 178 179 paa.paa_busname = "pcmcia"; 180 paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions; 181 paa.pch = (pcmcia_chipset_handle_t)&sc->sc_socket[i].ss; 182 183 sc->sc_socket[i].ss.pcmcia = 184 config_found(sc->sc_pc.sc_dev, &paa, opcic_print, 185 CFARGS_NONE); 186 187 #ifndef DONT_USE_CARD_DETECT_INTR 188 /* interrupt for card insertion/removal */ 189 opio_intr_establish(psc, 190 i==0 ? OPIO_INTR_CF_INSERT : OPIO_INTR_PCMCIA_INSERT, 191 IPL_BIO, opcic_card_detect, &sc->sc_socket[i]); 192 #else 193 bus_space_write_4(iot, ioh, MEMCTL_MECR, MECR_NOS | MECR_CIT); 194 195 #endif 196 197 /* schedule kthread creation */ 198 sapcic_kthread_create(&sc->sc_socket[i].ss); 199 } 200 201 } 202 203 static int 204 opcic_print(void *aux, const char *name) 205 { 206 return (UNCONF); 207 } 208 209 #ifndef DONT_USE_CARD_DETECT_INTR 210 static int 211 opcic_card_detect(void *arg, int val) 212 { 213 struct opcic_socket *socket = arg; 214 struct opcic_softc *sc = (struct opcic_softc *)socket->ss.sc; 215 bus_space_tag_t iot = sc->sc_pc.sc_iot; 216 bus_space_handle_t memctl_ioh = sc->sc_memctl_ioh; 217 int sock_no = socket->ss.socket; 218 int last, s; 219 220 s = splbio(); 221 last = sc->sc_cards; 222 if (HAVE_CARD(val)) { 223 sc->sc_cards |= 1<<sock_no; 224 /* if it is the first card, turn on expansion memory 225 * control. */ 226 if (last == 0) 227 bus_space_write_4(iot, memctl_ioh, MEMCTL_MECR, 228 MECR_NOS | MECR_CIT); 229 } 230 else { 231 sc->sc_cards &= ~(1<<sock_no); 232 /* if we loast all cards, turn off expansion memory 233 * control. */ 234 #if 0 235 if (sc->sc_cards == 0) 236 bus_space_write_4(iot, memctl_ioh, 237 MEMCTL_MECR, MECR_NOS); 238 #endif 239 } 240 splx(s); 241 242 DPRINTF(("%s: card %d %s\n", device_xname(sc->sc_pc.sc_dev), sock_no, 243 HAVE_CARD(val) ? "inserted" : "removed")); 244 245 sapcic_intr(arg); 246 247 return 1; 248 } 249 #endif /* DONT_USE_CARD_DETECT_INTR */ 250 251 static int 252 opcic_read(struct sapcic_socket *__so, int which) 253 { 254 struct opcic_socket *so = (struct opcic_socket *)__so; 255 uint8_t reg; 256 257 reg = opcic_read_card_status(so); 258 259 switch (which) { 260 case SAPCIC_STATUS_CARD: 261 return HAVE_CARD(reg) ? 262 SAPCIC_CARD_VALID : SAPCIC_CARD_INVALID; 263 264 case SAPCIC_STATUS_VS1: 265 return (reg & CARDDET_NVS1) == 0; 266 267 case SAPCIC_STATUS_VS2: 268 return (reg & CARDDET_NVS2) == 0; 269 270 case SAPCIC_STATUS_READY: 271 return 1; 272 273 default: 274 panic("%s: bogus register", __func__); 275 } 276 } 277 278 static void 279 opcic_write(struct sapcic_socket *__so, int which, int arg) 280 { 281 struct opcic_socket *so = (struct opcic_socket *)__so; 282 struct opcic_softc *sc = (struct opcic_softc *)so->ss.sc; 283 struct opio_softc *psc = 284 device_private(device_parent(sc->sc_pc.sc_dev)); 285 struct obio_softc *bsc = 286 device_private(device_parent(psc->sc_dev)); 287 288 switch (which) { 289 case SAPCIC_CONTROL_RESET: 290 obio_peripheral_reset(bsc, so->ss.socket, arg); 291 delay(500*1000); 292 break; 293 294 case SAPCIC_CONTROL_LINEENABLE: 295 break; 296 297 case SAPCIC_CONTROL_WAITENABLE: 298 break; 299 300 case SAPCIC_CONTROL_POWERSELECT: 301 #if 0 302 so->voltage = arg; 303 #endif 304 break; 305 306 default: 307 panic("%s: bogus register", __func__); 308 } 309 } 310 311 static void 312 opcic_set_power(struct sapcic_socket *__so, int arg) 313 { 314 struct opcic_socket *so = (struct opcic_socket *)__so; 315 struct opcic_softc *sc = (struct opcic_softc *)so->ss.sc; 316 struct opio_softc *psc = 317 device_private(device_parent(sc->sc_pc.sc_dev)); 318 int shift, save; 319 volatile uint8_t *p; 320 321 if( arg < 0 || SAPCIC_POWER_5V < arg ) 322 panic("sacpcic_set_power: bogus arg\n"); 323 324 DPRINTF(("card %d: DET=%x\n", 325 so->ss.socket, 326 bus_space_read_1(psc->sc_iot, psc->sc_ioh, 327 GB225_CFDET + 2*so->ss.socket))); 328 329 p = (volatile uint8_t *)bus_space_vaddr(psc->sc_iot, psc->sc_ioh) 330 + GB225_CARDPOW; 331 332 shift = 4 * !so->ss.socket; 333 334 save = disable_interrupts(I32_bit); 335 *p = (*p & ~(0x0f << shift)) | ((CARDPOW_VPPVCC | (arg<<2)) << shift); 336 restore_interrupts(save); 337 338 DPRINTF(("card %d power: %x\n", so->ss.socket, *p)); 339 } 340 341 static void 342 opcic_clear_intr(int arg) 343 { 344 } 345 346 static void * 347 opcic_intr_establish(struct sapcic_socket *so, int level, 348 int (* ih_fun)(void *), void *ih_arg) 349 { 350 struct opcic_softc *sc = (struct opcic_softc *)so->sc; 351 struct opio_softc *psc = 352 device_private(device_parent(sc->sc_pc.sc_dev)); 353 struct obio_softc *bsc = 354 device_private(device_parent(psc->sc_dev)); 355 int irq; 356 357 DPRINTF(("opcic_intr_establish %d\n", so->socket)); 358 359 irq = so->socket ? PCMCIA_INT : CF_INT; 360 return obio_intr_establish(bsc, irq, level, IST_EDGE_FALLING, 361 ih_fun, ih_arg); 362 } 363 364 static void 365 opcic_intr_disestablish(struct sapcic_socket *so, void *ih) 366 { 367 struct opcic_softc *sc = (struct opcic_softc *)so->sc; 368 struct opio_softc *psc = 369 device_private(device_parent(sc->sc_pc.sc_dev)); 370 struct obio_softc *bsc = 371 device_private(device_parent(psc->sc_dev)); 372 int (* func)(void *) = ((struct obio_handler *)ih)->func; 373 374 int irq = so->socket ? PCMCIA_INT : CF_INT; 375 376 obio_intr_disestablish(bsc, irq, func); 377 } 378