From 3af5743d0a47410dadb835388900c06338c8b5ed Mon Sep 17 00:00:00 2001 From: kiyohara Date: Fri, 20 Apr 2007 13:00:08 +0000 Subject: [PATCH] Change to use pxapcic from sa11xx_pcic. Support multiple socket. But not tested. --- sys/arch/evbarm/conf/GUMSTIX | 10 +- sys/arch/evbarm/conf/files.gumstix | 9 +- sys/arch/evbarm/gumstix/gumstix_machdep.c | 8 +- sys/arch/evbarm/gumstix/gxio.c | 98 ++++--- sys/arch/evbarm/gumstix/gxpcic.c | 337 +++++++++++----------- 5 files changed, 234 insertions(+), 228 deletions(-) diff --git a/sys/arch/evbarm/conf/GUMSTIX b/sys/arch/evbarm/conf/GUMSTIX index 1b80c21a85c5..e706424cb089 100644 --- a/sys/arch/evbarm/conf/GUMSTIX +++ b/sys/arch/evbarm/conf/GUMSTIX @@ -1,4 +1,4 @@ -# $NetBSD: GUMSTIX,v 1.11 2007/03/14 12:27:21 drochner Exp $ +# $NetBSD: GUMSTIX,v 1.12 2007/04/20 13:00:08 kiyohara Exp $ # # GUMSTIX -- Gumstix, Inc. gumstix platforms kernel # @@ -209,9 +209,11 @@ options GXIO_BLUETOOTH_ON_HWUART # Bluetooth module on HWUART sm0 at gxio? addr 0x04000300 gpirq 36 # etherstix, net{MMC,CF,DUO} sm1 at gxio? addr 0x08000300 gpirq 27 # netDUO(2nd NIC) -# PCMCIA/CF card -gxpcic* at gxio? addr 0x20000000 gpirq 11 # cfstix, netCF -pcmcia* at gxpcic? +# integrated PCMCIA/CF controller +pxapcic0 at pxaip? # cfstix, netCF + +# PCMCIA bus support +pcmcia* at pxapcic? # PCMCIA serial interfaces com* at pcmcia? function ? # Modems and serial cards diff --git a/sys/arch/evbarm/conf/files.gumstix b/sys/arch/evbarm/conf/files.gumstix index 6067c75f7c22..5153d430d056 100644 --- a/sys/arch/evbarm/conf/files.gumstix +++ b/sys/arch/evbarm/conf/files.gumstix @@ -1,4 +1,4 @@ -# $NetBSD: files.gumstix,v 1.3 2007/02/20 17:23:09 kiyohara Exp $ +# $NetBSD: files.gumstix,v 1.4 2007/04/20 13:00:08 kiyohara Exp $ # # Genetec corp. G4255EB evaluation board configuration info # @@ -22,7 +22,6 @@ file arch/evbarm/gumstix/gxio.c gxio attach sm at gxio with sm_gxio file arch/evbarm/gumstix/if_sm_gxio.c sm_gxio -device gxpcic: pcmciabus -attach gxpcic at gxio -file arch/arm/sa11x0/sa11xx_pcic.c gxpcic -file arch/evbarm/gumstix/gxpcic.c gxpcic +# PCMCIA/CF socket and GPIO controllers +attach pxapcic at pxaip with pxapcic_gxpcic +file arch/evbarm/gumstix/gxpcic.c pxapcic_gxpcic diff --git a/sys/arch/evbarm/gumstix/gumstix_machdep.c b/sys/arch/evbarm/gumstix/gumstix_machdep.c index e7ff7475e15d..a5ee07f81022 100644 --- a/sys/arch/evbarm/gumstix/gumstix_machdep.c +++ b/sys/arch/evbarm/gumstix/gumstix_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: gumstix_machdep.c,v 1.3 2007/01/18 10:06:47 kiyohara Exp $ */ +/* $NetBSD: gumstix_machdep.c,v 1.4 2007/04/20 13:00:08 kiyohara Exp $ */ /* * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation. * All rights reserved. @@ -292,6 +292,7 @@ int comcnspeed = CONSPEED; int comcnmode = CONMODE; extern void gxio_config_pin(void); +extern void gxio_config_busheader(char *); /* * void cpu_reboot(int howto, char *bootstr) @@ -936,7 +937,6 @@ read_system_serial() static void process_kernel_args(int argc, char *argv[]) { - extern char busheader[MAX_BOOT_STRING]; static const char busheader_name[] = "busheader="; int i, j; @@ -951,8 +951,8 @@ process_kernel_args(int argc, char *argv[]) for (i = 1, j = 0; i < argc; i++) { if (!strncmp(argv[i], busheader_name, strlen(busheader_name))) { - strncpy(busheader, - argv[i] + strlen(busheader_name), MAX_BOOT_STRING); + /* configure for GPIOs of busheader side */ + gxio_config_busheader(argv[i] + strlen(busheader_name)); continue; } if (j == MAX_BOOT_STRING) { diff --git a/sys/arch/evbarm/gumstix/gxio.c b/sys/arch/evbarm/gumstix/gxio.c index 8e5743d5afd9..57544647175d 100644 --- a/sys/arch/evbarm/gumstix/gxio.c +++ b/sys/arch/evbarm/gumstix/gxio.c @@ -1,4 +1,4 @@ -/* $NetBSD: gxio.c,v 1.3 2007/01/18 10:06:47 kiyohara Exp $ */ +/* $NetBSD: gxio.c,v 1.4 2007/04/20 13:00:08 kiyohara Exp $ */ /* * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation. * All rights reserved. @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.3 2007/01/18 10:06:47 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.4 2007/04/20 13:00:08 kiyohara Exp $"); #include "opt_gxio.h" @@ -58,7 +58,7 @@ struct gpioconf { }; struct gxioconf { const char *name; - void (*config)(struct gxio_softc *); + void (*config)(void); }; static int gxiomatch(struct device *, struct cfdata *, void *); @@ -67,14 +67,15 @@ static int gxiosearch(struct device *, struct cfdata *, const int *, void *); static int gxioprint(void *, const char *); void gxio_config_pin(void); -static void - gxio_config_gpio(struct gxio_softc *, const struct gxioconf *, char *); -static void cfstix_config(struct gxio_softc *); -static void etherstix_config(struct gxio_softc *); -static void netcf_config(struct gxio_softc *); -static void netduommc_config(struct gxio_softc *); -static void netduo_config(struct gxio_softc *); -static void netmmc_config(struct gxio_softc *); +void gxio_config_busheader(char *); +static void gxio_config_gpio(const struct gxioconf *, char *); +static void cfstix_config(void); +static void etherstix_config(void); +static void netcf_config(void); +static void netduommc_config(void); +static void netduo_config(void); +static void netmmc_config(void); +static void wifistix_cf_config(void); CFATTACH_DECL( gxio, sizeof(struct gxio_softc), gxiomatch, gxioattach, NULL, NULL); @@ -137,6 +138,7 @@ static const struct gxioconf busheader_conf[] = { { "netduo-mmc", netduommc_config }, { "netduo", netduo_config }, { "netmmc", netmmc_config }, + { "wifistix-cf", wifistix_cf_config }, { "wifistix", cfstix_config }, { NULL } }; @@ -173,11 +175,8 @@ gxioattach(struct device *parent, struct device *self, void *aux) PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh)) return; - /* configuration for GPIOs of busheader side */ - gxio_config_gpio(sc, busheader_conf, busheader); - /* - * Attach each gumstix expantion of busheader side devices + * Attach each gumstix expansion of busheader side devices */ config_search_ia(gxiosearch, self, "gxio", NULL); } @@ -231,9 +230,15 @@ gxio_config_pin() pxa2x0_gpio_set_function(gpioconf[i].pin, gpioconf[i].value); } +void +gxio_config_busheader(char *expansion) +{ + + gxio_config_gpio(busheader_conf, expansion); +} + static void -gxio_config_gpio(struct gxio_softc *sc, - const struct gxioconf *gxioconflist, char *expansion) +gxio_config_gpio(const struct gxioconf *gxioconflist, char *expansion) { int i, rv; @@ -243,7 +248,7 @@ gxio_config_gpio(struct gxio_softc *sc, rv = strncmp(expansion, gxioconflist[i].name, strlen(gxioconflist[i].name) + 1); if (rv == 0) { - gxioconflist[i].config(sc); + gxioconflist[i].config(); break; } } @@ -251,21 +256,17 @@ gxio_config_gpio(struct gxio_softc *sc, static void -cfstix_config(struct gxio_softc *sc) +cfstix_config() { u_int gpio, npoe_fn; - bus_space_write_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR, - bus_space_read_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR) & ~MECR_NOS); - - pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_SET); /* RESET */ - delay(50); - pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_CLR); - - pxa2x0_gpio_set_function(4, GPIO_IN); /* nBVD1/~nSTSCHG */ - pxa2x0_gpio_set_function(27, GPIO_IN); /* ~INPACK */ - pxa2x0_gpio_set_function(11, GPIO_IN); /* nPCD1 */ - pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY/~IRQ */ +#if 1 + /* this configuration set by pxapcic_attach_common()::pxa2x0_pcic.c */ +#else + pxa2x0_gpio_set_function(11, GPIO_IN); /* PCD1 */ + pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY1/~IRQ1 */ +#endif + pxa2x0_gpio_set_function(4, GPIO_IN); /* BVD1/~STSCHG1 */ for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++) npoe_fn |= pxa2x0_gpio_get_function(gpio); @@ -276,15 +277,15 @@ cfstix_config(struct gxio_softc *sc) pxa2x0_gpio_set_function(50, GPIO_ALT_FN_2_OUT); /* nPIOR */ pxa2x0_gpio_set_function(51, GPIO_ALT_FN_2_OUT); /* nPIOW */ pxa2x0_gpio_set_function(52, GPIO_ALT_FN_2_OUT); /* nPCE1 */ + pxa2x0_gpio_set_function(53, GPIO_ALT_FN_2_OUT); /* nPCE2 */ pxa2x0_gpio_set_function(54, GPIO_ALT_FN_2_OUT); /* pSKTSEL */ pxa2x0_gpio_set_function(55, GPIO_ALT_FN_2_OUT); /* nPREG */ pxa2x0_gpio_set_function(56, GPIO_ALT_FN_1_IN); /* nPWAIT */ pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */ } -/* ARGSUSED */ static void -etherstix_config(struct gxio_softc *sc) +etherstix_config() { pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ @@ -296,27 +297,27 @@ etherstix_config(struct gxio_softc *sc) } static void -netcf_config(struct gxio_softc *sc) +netcf_config() { - etherstix_config(sc); - cfstix_config(sc); + etherstix_config(); + cfstix_config(); } static void -netduommc_config(struct gxio_softc *sc) +netduommc_config() { - netduo_config(sc); + netduo_config(); /* mmc not yet... */ } static void -netduo_config(struct gxio_softc *sc) +netduo_config() { - etherstix_config(sc); + etherstix_config(); pxa2x0_gpio_set_function(78, GPIO_ALT_FN_2_OUT); /* nCS 2 */ pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */ @@ -326,10 +327,25 @@ netduo_config(struct gxio_softc *sc) } static void -netmmc_config(struct gxio_softc *sc) +netmmc_config() { - etherstix_config(sc); + etherstix_config(); /* mmc not yet... */ } + +static void +wifistix_cf_config() +{ + +#if 1 + /* this configuration set by pxapcic_attach_common()::pxa2x0_pcic.c */ +#else + pxa2x0_gpio_set_function(36, GPIO_IN); /* PCD2 */ + pxa2x0_gpio_set_function(27, GPIO_IN); /* PRDY2/~IRQ2 */ +#endif + pxa2x0_gpio_set_function(18, GPIO_IN); /* BVD2/~STSCHG2 */ + + cfstix_config(); +} diff --git a/sys/arch/evbarm/gumstix/gxpcic.c b/sys/arch/evbarm/gumstix/gxpcic.c index a72895bbfc21..5a47ad20c5a4 100644 --- a/sys/arch/evbarm/gumstix/gxpcic.c +++ b/sys/arch/evbarm/gumstix/gxpcic.c @@ -1,4 +1,4 @@ -/* $NetBSD: gxpcic.c,v 1.3 2007/01/18 10:02:55 kiyohara Exp $ */ +/* $NetBSD: gxpcic.c,v 1.4 2007/04/20 13:00:08 kiyohara Exp $ */ /* * Copyright (C) 2005, 2006 WIDE Project and SOUM Corporation. * All rights reserved. @@ -80,7 +80,7 @@ #include #include -#include +#include #include @@ -92,43 +92,31 @@ #define HAVE_CARD(r) (!((r) & GPIO_SET)) -#define GXIO_GPIO8_RESET 8 -#define GXIO_GPIRQ11_nCD 11 -#define GXIO_GPIO26_READY 26 +#define GXIO_GPIRQ11_CD1 11 +#define GXIO_GPIRQ26_PRDY1 26 +#define GXIO_GPIRQ27_PRDY2 27 +#define GXIO_GPIRQ36_CD2 36 -struct gxpcic_softc; -struct gxpcic_socket { - struct sapcic_socket ss; /* inherit socket for sa11x0 pcic */ -}; +static int gxpcic_match(struct device *, struct cfdata *, void *); +static void gxpcic_attach(struct device *, struct device *, void *); +static void gxpcic_pcic_socket_setup(struct pxapcic_socket *); -struct gxpcic_softc { - struct sapcic_softc sc_pc; /* inherit SA11xx pcic */ - - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; - int sc_gpirq; - - struct gxpcic_socket sc_socket[2]; - int sc_cards; -}; - -static int gxpcic_match(struct device *, struct cfdata *, void *); -static void gxpcic_attach(struct device *, struct device *, void *); - -static int gxpcic_card_detect(void *); -static int gxpcic_read(struct sapcic_socket *, int); -static void gxpcic_write(struct sapcic_socket *, int, int); -static void gxpcic_set_power(struct sapcic_socket *, int); -static void gxpcic_clear_intr(int); -static void *gxpcic_intr_establish(struct sapcic_socket *, int, +static u_int gxpcic_read(struct pxapcic_socket *, int); +static void gxpcic_write(struct pxapcic_socket *, int, u_int); +static void gxpcic_set_power(struct pxapcic_socket *, int); +static void gxpcic_clear_intr(struct pxapcic_socket *); +static void *gxpcic_intr_establish(struct pxapcic_socket *, int, int (*)(void *), void *); -static void gxpcic_intr_disestablish(struct sapcic_socket *, void *); +static void gxpcic_intr_disestablish(struct pxapcic_socket *, void *); +__inline void gxpcic_cpld_clk(void); +__inline u_char gxpcic_cpld_read_bits(int bits); +static int gxpcic_count_slot(struct pxapcic_softc *); -CFATTACH_DECL(gxpcic, sizeof(struct gxpcic_softc), +CFATTACH_DECL(pxapcic_gxpcic, sizeof(struct pxapcic_softc), gxpcic_match, gxpcic_attach, NULL, NULL); -static struct sapcic_tag gxpcic_tag = { +static struct pxapcic_tag gxpcic_pcic_functions = { gxpcic_read, gxpcic_write, gxpcic_set_power, @@ -137,6 +125,14 @@ static struct sapcic_tag gxpcic_tag = { gxpcic_intr_disestablish, }; +static struct { + int cd; + int prdy; +} gxpcic_slot_irqs[] = { + { GXIO_GPIRQ11_CD1, GXIO_GPIRQ26_PRDY1 }, + { GXIO_GPIRQ36_CD2, GXIO_GPIRQ27_PRDY2 } +}; + static int gxpcic_match(struct device *parent, struct cfdata *cf, void *aux) @@ -144,11 +140,13 @@ gxpcic_match(struct device *parent, struct cfdata *cf, void *aux) struct { int gpio; u_int fn; - } gpiomodes[] = { + } pcic_gpiomodes[] = { { 48, GPIO_ALT_FN_2_OUT }, /* nPOE */ { 49, GPIO_ALT_FN_2_OUT }, /* nPWE */ { 50, GPIO_ALT_FN_2_OUT }, /* nPIOR */ { 51, GPIO_ALT_FN_2_OUT }, /* nPIOW */ + { 52, GPIO_ALT_FN_2_OUT }, /* nPCE1 */ + { 53, GPIO_ALT_FN_2_OUT }, /* nPCE2 */ { 54, GPIO_ALT_FN_2_OUT }, /* pSKTSEL */ { 55, GPIO_ALT_FN_2_OUT }, /* nPREG */ { 56, GPIO_ALT_FN_1_IN }, /* nPWAIT */ @@ -158,13 +156,17 @@ gxpcic_match(struct device *parent, struct cfdata *cf, void *aux) u_int reg; int i; - for (i = 0; gpiomodes[i].gpio != -1; i++) { - reg = pxa2x0_gpio_get_function(gpiomodes[i].gpio); - if (GPIO_FN(reg) != GPIO_FN(gpiomodes[i].fn) || - GPIO_FN_IS_OUT(reg) != GPIO_FN_IS_OUT(gpiomodes[i].fn)) + /* + * Check GPIO configuration. If you use these, it is sure already + * to have been set by gxio. + */ + for (i = 0; pcic_gpiomodes[i].gpio != -1; i++) { + reg = pxa2x0_gpio_get_function(pcic_gpiomodes[i].gpio); + if (GPIO_FN(reg) != GPIO_FN(pcic_gpiomodes[i].fn) || + GPIO_FN_IS_OUT(reg) != GPIO_FN_IS_OUT(pcic_gpiomodes[i].fn)) break; } - if (gpiomodes[i].gpio != -1) + if (pcic_gpiomodes[i].gpio != -1) return 0; return 1; /* match */ @@ -173,166 +175,85 @@ gxpcic_match(struct device *parent, struct cfdata *cf, void *aux) static void gxpcic_attach(struct device *parent, struct device *self, void *aux) { - struct gxio_softc *gxsc = device_private(parent); - struct gxpcic_softc *sc = device_private(self); - struct gxio_attach_args *gxa = aux; - struct pcmciabus_attach_args paa; - int mecr, val, i, n; + struct pxapcic_softc *sc = (struct pxapcic_softc *)self; + struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux; + int nslot, i; - aprint_normal("\n"); - aprint_naive("\n"); + sc->sc_iot = pxa->pxa_iot; - sc->sc_iot = sc->sc_pc.sc_iot = gxa->gxa_iot; - sc->sc_ioh = gxsc->sc_ioh; - sc->sc_gpirq = gxa->gxa_gpirq; - sc->sc_cards = 0; + nslot = gxpcic_count_slot(sc); - n = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR) & MECR_NOS ? - 2 : 1; - for (i = 0; i < n; i++) { - sc->sc_socket[i].ss.sc = &sc->sc_pc; - sc->sc_socket[i].ss.socket = 0; - sc->sc_socket[i].ss.pcictag_cookie = NULL; - sc->sc_socket[i].ss.pcictag = &gxpcic_tag; - sc->sc_socket[i].ss.event_thread = NULL; - sc->sc_socket[i].ss.event = 0; - sc->sc_socket[i].ss.laststatus = SAPCIC_CARD_INVALID; - sc->sc_socket[i].ss.shutdown = 0; - - /* 3.3V only? */ - sc->sc_socket[i].ss.power_capability = SAPCIC_POWER_3V; - - bus_space_write_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MCMEM(i), - MC_TIMING_VAL(10,10,30)); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MCATT(i), - MC_TIMING_VAL(10,10,30)); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MCIO(i), - MC_TIMING_VAL(6,6,17)); - - paa.paa_busname = "pcmcia"; - paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions; - paa.pch = (pcmcia_chipset_handle_t)&sc->sc_socket[i].ss; - paa.iobase = 0; - paa.iosize = 0x4000000; - - sc->sc_socket[i].ss.pcmcia = - (struct device *)config_found_ia(&sc->sc_pc.sc_dev, - "pcmciabus", &paa, NULL); - - /* interrupt for card insertion/removal */ - gxio_intr_establish(sc, GXIO_GPIRQ11_nCD, IST_EDGE_BOTH, - IPL_BIO, gxpcic_card_detect, &sc->sc_socket[i]); - - /* if card was insert then set CIT */ - val = pxa2x0_gpio_get_function(GXIO_GPIRQ11_nCD); - if (HAVE_CARD(val)) { - mecr = bus_space_read_4( - sc->sc_iot, sc->sc_ioh, MEMCTL_MECR); - bus_space_write_4(sc->sc_iot, - sc->sc_ioh, MEMCTL_MECR, mecr | MECR_CIT); - } - - /* schedule kthread creation */ - kthread_create(sapcic_kthread_create, &sc->sc_socket[i].ss); + for (i = 0; i < nslot; i++) { + sc->sc_irqpin[i] = gxpcic_slot_irqs[i].prdy; + sc->sc_irqcfpin[i] = gxpcic_slot_irqs[i].cd; } + sc->sc_nslots = nslot; + pxapcic_attach_common(sc, &gxpcic_pcic_socket_setup); } -static int -gxpcic_card_detect(void *arg) +static void +gxpcic_pcic_socket_setup(struct pxapcic_socket *so) { - struct gxpcic_socket *socket = arg; - struct gxpcic_softc *sc = (struct gxpcic_softc *)socket->ss.sc; - int sock_no = socket->ss.socket; - int mecr, last, val, s; + struct pxapcic_softc *sc = so->sc; - s = splbio(); - last = sc->sc_cards; - val = pxa2x0_gpio_get_function(GXIO_GPIRQ11_nCD); - if (HAVE_CARD(val)) { - sc->sc_cards |= 1<sc_iot, sc->sc_ioh, MEMCTL_MECR); - bus_space_write_4(sc->sc_iot, - sc->sc_ioh, MEMCTL_MECR, mecr | MECR_CIT); - } - } else { - sc->sc_cards &= ~(1<sc_cards == 0) { - mecr = bus_space_read_4( - sc->sc_iot, sc->sc_ioh, MEMCTL_MECR); - bus_space_write_4(sc->sc_iot, - sc->sc_ioh, MEMCTL_MECR, mecr & ~MECR_CIT); - } - } - splx(s); + /* 3.3V only? */ + so->power_capability = PXAPCIC_POWER_3V; + so->pcictag_cookie = NULL; + so->pcictag = &gxpcic_pcic_functions; - DPRINTF(("%s: card %d %s\n", sc->sc_pc.sc_dev.dv_xname, sock_no, - HAVE_CARD(val) ? "inserted" : "removed")); - - sapcic_intr(arg); - - return 1; + bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCMEM(so->socket), MC_TIMING_VAL(9 ,9, 29)); + bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCATT(so->socket), MC_TIMING_VAL(9 ,9, 29)); + bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCIO(so->socket), MC_TIMING_VAL(5 ,5, 16)); } -/* ARGSUSED */ -static int -gxpcic_read(struct sapcic_socket *so, int which) +static u_int +gxpcic_read(struct pxapcic_socket *so, int which) { int reg; switch (which) { - case SAPCIC_STATUS_CARD: - reg = pxa2x0_gpio_get_function(GXIO_GPIRQ11_nCD); + case PXAPCIC_CARD_STATUS: + reg = pxa2x0_gpio_get_function(gxpcic_slot_irqs[so->socket].cd); return (HAVE_CARD(reg) ? - SAPCIC_CARD_VALID : SAPCIC_CARD_INVALID); + PXAPCIC_CARD_VALID : PXAPCIC_CARD_INVALID); - case SAPCIC_STATUS_READY: - reg = pxa2x0_gpio_get_function(GXIO_GPIO26_READY); + case PXAPCIC_CARD_READY: + reg = pxa2x0_gpio_get_function( + gxpcic_slot_irqs[so->socket].prdy); return (reg & GPIO_SET ? 1 : 0); default: panic("%s: bogus register", __FUNCTION__); } + /* NOTREACHED */ } /* ARGSUSED */ static void -gxpcic_write(struct sapcic_socket *so, int which, int arg) +gxpcic_write(struct pxapcic_socket *so, int which, u_int arg) { switch (which) { - case SAPCIC_CONTROL_RESET: -#if 0 /* XXXX: Our PXA2x0 no necessary ??? */ - if (arg) - pxa2x0_gpio_set_function(GXIO_GPIO8_RESET, GPIO_SET); - else - pxa2x0_gpio_set_function(GXIO_GPIO8_RESET, GPIO_CLR); -#endif - break; - - case SAPCIC_CONTROL_LINEENABLE: - break; - - case SAPCIC_CONTROL_WAITENABLE: - break; - - case SAPCIC_CONTROL_POWERSELECT: + case PXAPCIC_CARD_POWER: + case PXAPCIC_CARD_RESET: + /* We can't */ break; default: panic("%s: bogus register", __FUNCTION__); } + /* NOTREACHED */ } static void -gxpcic_set_power(struct sapcic_socket *__so, int arg) +gxpcic_set_power(struct pxapcic_socket *__so, int arg) { - if(arg != SAPCIC_POWER_OFF && arg != SAPCIC_POWER_3V) + if(arg != PXAPCIC_POWER_OFF && arg != PXAPCIC_POWER_3V) panic("%s: bogus arg\n", __FUNCTION__); /* 3.3V only? */ @@ -340,34 +261,102 @@ gxpcic_set_power(struct sapcic_socket *__so, int arg) /* ARGSUSED */ static void -gxpcic_clear_intr(int arg) +gxpcic_clear_intr(struct pxapcic_socket *so) { /* nothing to do */ } static void * -gxpcic_intr_establish(struct sapcic_socket *so, int level, +gxpcic_intr_establish(struct pxapcic_socket *so, int level, int (* ih_fun)(void *), void *ih_arg) { - __attribute__((unused))struct gxpcic_softc *sc = - (struct gxpcic_softc *)so->sc; - int gpirq; - gpirq = GXIO_GPIO26_READY; - - DPRINTF(("%s: card %d gpio %d\n", - sc->sc_pc.sc_dev.dv_xname, so->socket, gpirq)); - - return gxio_intr_establish(sc, gpirq, IST_EDGE_FALLING, level, - ih_fun, ih_arg); + return pxa2x0_gpio_intr_establish(so->irqpin, IST_EDGE_FALLING, + level, ih_fun, ih_arg); } +/* ARGSUSED */ static void -gxpcic_intr_disestablish(struct sapcic_socket *so, void *ih) +gxpcic_intr_disestablish(struct pxapcic_socket *so, void *ih) { - __attribute__((unused))struct gxpcic_softc *sc = - (struct gxpcic_softc *)so->sc; - gxio_intr_disestablish(sc, ih); + pxa2x0_gpio_intr_disestablish(ih); +} + + +/* + * XXXXX: slot count functions from Linux + */ +__inline void +gxpcic_cpld_clk() +{ + + pxa2x0_gpio_set_function(48, GPIO_OUT | GPIO_CLR); + pxa2x0_gpio_set_function(48, GPIO_OUT | GPIO_SET); +} + +__inline u_char +gxpcic_cpld_read_bits(int bits) +{ + u_int shift = 0, gpio; + u_char result = 0; + + while (bits--) { + gpio = pxa2x0_gpio_get_function(11); + result |= ((gpio & GPIO_SET) == GPIO_SET) << shift; + shift++; + gxpcic_cpld_clk(); + } + return result; +} + +/* + * We use the CPLD on the CF-CF card to read a value from a shift register. + * If we can read that magic sequence, then we have 2 CF cards; otherwise + * we assume just one. The CPLD will send the value of the shift register + * on GPIO11 (the CD line for slot 0) when RESET is held in reset. We use + * GPIO48 (nPWE) as a clock signal, GPIO52/53 (card enable for both cards) + * to control read/write to the shift register. + */ +static int +gxpcic_count_slot(struct pxapcic_softc *sc) +{ + u_int poe, pce1, pce2; + int nslot; + + poe = pxa2x0_gpio_get_function(48); + pce1 = pxa2x0_gpio_get_function(52); + pce2 = pxa2x0_gpio_get_function(53); + + /* Reset */ + pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_SET); + + /* Setup the shift register */ + pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); + pxa2x0_gpio_set_function(53, GPIO_OUT | GPIO_CLR); + + /* Tick the clock to program the shift register */ + gxpcic_cpld_clk(); + + /* Now set shift register into read mode */ + pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_CLR); + pxa2x0_gpio_set_function(53, GPIO_OUT | GPIO_SET); + + /* We can read the bits now -- 0xc2 means "Dual compact flash" */ + if (gxpcic_cpld_read_bits(8) != 0xc2) + /* We do not have 2 CF slots */ + nslot = 1; + else + /* We have 2 CF slots */ + nslot = 2; + + delay(50); + pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_CLR); /* clr RESET */ + + pxa2x0_gpio_set_function(48, poe); + pxa2x0_gpio_set_function(52, pce1); + pxa2x0_gpio_set_function(53, pce2); + + return nslot; }