1 /* $NetBSD: gxpcic.c,v 1.8 2008/05/11 08:23:17 kiyohara Exp $ */ 2 /* 3 * Copyright (C) 2005, 2006 WIDE Project and SOUM Corporation. 4 * All rights reserved. 5 * 6 * Written by Takashi Kiyohara and Susumu Miki for WIDE Project and SOUM 7 * Corporation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the name of SOUM Corporation 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT and SOUM CORPORATION ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT AND SOUM CORPORATION 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* 34 * Copyright (c) 2002, 2003, 2005 Genetec corp. All rights reserved. 35 * 36 * PCMCIA/CF support for TWINTAIL (G4255EB) 37 * Written by Hiroyuki Bessho for Genetec corp. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. The name of Genetec corp. may not be used to endorse 48 * or promote products derived from this software without specific prior 49 * written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP. 55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61 * POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #include <sys/types.h> 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/device.h> 68 #include <sys/callout.h> 69 #include <sys/kernel.h> 70 #include <sys/kthread.h> 71 #include <sys/malloc.h> 72 #include <uvm/uvm.h> 73 74 #include <machine/bus.h> 75 #include <machine/intr.h> 76 77 #include <dev/pcmcia/pcmciareg.h> 78 #include <dev/pcmcia/pcmciavar.h> 79 #include <dev/pcmcia/pcmciachip.h> 80 81 #include <arch/arm/xscale/pxa2x0cpu.h> 82 #include <arch/arm/xscale/pxa2x0var.h> 83 #include <arch/arm/xscale/pxa2x0reg.h> 84 #include <arch/arm/xscale/pxa2x0_gpio.h> 85 #include <arch/arm/xscale/pxa2x0_pcic.h> 86 #include <arch/evbarm/gumstix/gumstixvar.h> 87 88 89 #ifdef DEBUG 90 #define DPRINTF(arg) printf arg 91 #else 92 #define DPRINTF(arg) 93 #endif 94 95 #define HAVE_CARD(r) (!((r) & GPIO_SET)) 96 97 #define GXIO_GPIRQ11_CD1 11 98 #define GXIO_GPIRQ26_PRDY1 26 99 #define GXIO_GPIRQ27_PRDY2 27 100 #define GXIO_GPIRQ36_CD2 36 101 102 103 static int gxpcic_match(device_t, struct cfdata *, void *); 104 static void gxpcic_attach(device_t, device_t, void *); 105 static void gxpcic_pcic_socket_setup(struct pxapcic_socket *); 106 107 static u_int gxpcic_read(struct pxapcic_socket *, int); 108 static void gxpcic_write(struct pxapcic_socket *, int, u_int); 109 static void gxpcic_set_power(struct pxapcic_socket *, int); 110 static void gxpcic_clear_intr(struct pxapcic_socket *); 111 static void *gxpcic_intr_establish(struct pxapcic_socket *, int, 112 int (*)(void *), void *); 113 static void gxpcic_intr_disestablish(struct pxapcic_socket *, void *); 114 __inline void gxpcic_cpld_clk(void); 115 __inline u_char gxpcic_cpld_read_bits(int bits); 116 static int gxpcic_count_slot(struct pxapcic_softc *); 117 118 CFATTACH_DECL(pxapcic_gxpcic, sizeof(struct pxapcic_softc), 119 gxpcic_match, gxpcic_attach, NULL, NULL); 120 121 static struct pxapcic_tag gxpcic_pcic_functions = { 122 gxpcic_read, 123 gxpcic_write, 124 gxpcic_set_power, 125 gxpcic_clear_intr, 126 gxpcic_intr_establish, 127 gxpcic_intr_disestablish, 128 }; 129 130 static struct { 131 int cd; 132 int prdy; 133 } gxpcic_slot_irqs[] = { 134 { GXIO_GPIRQ11_CD1, GXIO_GPIRQ26_PRDY1 }, 135 { GXIO_GPIRQ36_CD2, GXIO_GPIRQ27_PRDY2 } 136 }; 137 138 139 static int 140 gxpcic_match(device_t parent, struct cfdata *cf, void *aux) 141 { 142 struct pxa2x0_gpioconf *gpioconf; 143 u_int reg; 144 int i; 145 146 /* 147 * Check GPIO configuration. If you use these, it is sure already 148 * to have been set by gxio. 149 */ 150 gpioconf = CPU_IS_PXA250 ? pxa25x_pcic_gpioconf : 151 pxa27x_pcic_gpioconf; 152 for (i = 0; gpioconf[i].pin != -1; i++) { 153 reg = pxa2x0_gpio_get_function(gpioconf[i].pin); 154 if (GPIO_FN(reg) != GPIO_FN(gpioconf[i].value) || 155 GPIO_FN_IS_OUT(reg) != GPIO_FN_IS_OUT(gpioconf[i].value)) 156 return (0); 157 } 158 159 return 1; /* match */ 160 } 161 162 static void 163 gxpcic_attach(device_t parent, device_t self, void *aux) 164 { 165 struct pxapcic_softc *sc = device_private(self); 166 struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux; 167 int nslot, i; 168 169 sc->sc_iot = pxa->pxa_iot; 170 171 nslot = gxpcic_count_slot(sc); 172 173 for (i = 0; i < nslot; i++) { 174 sc->sc_irqpin[i] = gxpcic_slot_irqs[i].prdy; 175 sc->sc_irqcfpin[i] = gxpcic_slot_irqs[i].cd; 176 } 177 sc->sc_nslots = nslot; 178 179 pxapcic_attach_common(sc, &gxpcic_pcic_socket_setup); 180 } 181 182 static void 183 gxpcic_pcic_socket_setup(struct pxapcic_socket *so) 184 { 185 struct pxapcic_softc *sc = so->sc; 186 187 /* 3.3V only? */ 188 so->power_capability = PXAPCIC_POWER_3V; 189 so->pcictag_cookie = NULL; 190 so->pcictag = &gxpcic_pcic_functions; 191 192 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, 193 MEMCTL_MCMEM(so->socket), MC_TIMING_VAL(9 ,9, 29)); 194 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, 195 MEMCTL_MCATT(so->socket), MC_TIMING_VAL(9 ,9, 29)); 196 bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, 197 MEMCTL_MCIO(so->socket), MC_TIMING_VAL(5 ,5, 16)); 198 } 199 200 static u_int 201 gxpcic_read(struct pxapcic_socket *so, int which) 202 { 203 int reg; 204 205 switch (which) { 206 case PXAPCIC_CARD_STATUS: 207 reg = pxa2x0_gpio_get_function(gxpcic_slot_irqs[so->socket].cd); 208 return (HAVE_CARD(reg) ? 209 PXAPCIC_CARD_VALID : PXAPCIC_CARD_INVALID); 210 211 case PXAPCIC_CARD_READY: 212 reg = pxa2x0_gpio_get_function( 213 gxpcic_slot_irqs[so->socket].prdy); 214 return (reg & GPIO_SET ? 1 : 0); 215 216 default: 217 panic("%s: bogus register", __func__); 218 } 219 /* NOTREACHED */ 220 } 221 222 /* ARGSUSED */ 223 static void 224 gxpcic_write(struct pxapcic_socket *so, int which, u_int arg) 225 { 226 227 switch (which) { 228 case PXAPCIC_CARD_POWER: 229 case PXAPCIC_CARD_RESET: 230 /* We can't */ 231 break; 232 233 default: 234 panic("%s: bogus register", __func__); 235 } 236 /* NOTREACHED */ 237 } 238 239 static void 240 gxpcic_set_power(struct pxapcic_socket *__so, int arg) 241 { 242 243 if(arg != PXAPCIC_POWER_OFF && arg != PXAPCIC_POWER_3V) 244 panic("%s: bogus arg\n", __func__); 245 246 /* 3.3V only? */ 247 } 248 249 /* ARGSUSED */ 250 static void 251 gxpcic_clear_intr(struct pxapcic_socket *so) 252 { 253 254 /* nothing to do */ 255 } 256 257 static void * 258 gxpcic_intr_establish(struct pxapcic_socket *so, int level, 259 int (* ih_fun)(void *), void *ih_arg) 260 { 261 262 return pxa2x0_gpio_intr_establish(so->irqpin, IST_EDGE_FALLING, 263 level, ih_fun, ih_arg); 264 } 265 266 /* ARGSUSED */ 267 static void 268 gxpcic_intr_disestablish(struct pxapcic_socket *so, void *ih) 269 { 270 271 pxa2x0_gpio_intr_disestablish(ih); 272 } 273 274 275 /* 276 * XXXXX: slot count functions from Linux 277 */ 278 __inline void 279 gxpcic_cpld_clk() 280 { 281 282 pxa2x0_gpio_set_function(48, GPIO_OUT | GPIO_CLR); 283 pxa2x0_gpio_set_function(48, GPIO_OUT | GPIO_SET); 284 } 285 286 __inline u_char 287 gxpcic_cpld_read_bits(int bits) 288 { 289 u_int shift = 0, gpio; 290 u_char result = 0; 291 292 while (bits--) { 293 gpio = pxa2x0_gpio_get_function(11); 294 result |= ((gpio & GPIO_SET) == GPIO_SET) << shift; 295 shift++; 296 gxpcic_cpld_clk(); 297 } 298 return result; 299 } 300 301 /* 302 * We use the CPLD on the CF-CF card to read a value from a shift register. 303 * If we can read that magic sequence, then we have 2 CF cards; otherwise 304 * we assume just one. The CPLD will send the value of the shift register 305 * on GPIO11 (the CD line for slot 0) when RESET is held in reset. We use 306 * GPIO48 (nPWE) as a clock signal, GPIO52/53 (card enable for both cards) 307 * to control read/write to the shift register. 308 */ 309 static int 310 gxpcic_count_slot(struct pxapcic_softc *sc) 311 { 312 u_int poe, pce1, pce2; 313 int nslot; 314 315 poe = pxa2x0_gpio_get_function(48); 316 pce1 = pxa2x0_gpio_get_function(52); 317 pce2 = pxa2x0_gpio_get_function(53); 318 319 /* Reset */ 320 pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_SET); 321 322 /* Setup the shift register */ 323 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); 324 pxa2x0_gpio_set_function(53, GPIO_OUT | GPIO_CLR); 325 326 /* Tick the clock to program the shift register */ 327 gxpcic_cpld_clk(); 328 329 /* Now set shift register into read mode */ 330 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_CLR); 331 pxa2x0_gpio_set_function(53, GPIO_OUT | GPIO_SET); 332 333 /* We can read the bits now -- 0xc2 means "Dual compact flash" */ 334 if (gxpcic_cpld_read_bits(8) != 0xc2) 335 /* We do not have 2 CF slots */ 336 nslot = 1; 337 else 338 /* We have 2 CF slots */ 339 nslot = 2; 340 341 delay(50); 342 pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_CLR); /* clr RESET */ 343 344 pxa2x0_gpio_set_function(48, poe); 345 pxa2x0_gpio_set_function(52, pce1); 346 pxa2x0_gpio_set_function(53, pce2); 347 348 return nslot; 349 } 350