Change to use pxapcic from sa11xx_pcic.

Support multiple socket.  But not tested.
This commit is contained in:
kiyohara 2007-04-20 13:00:08 +00:00
parent e0c180145d
commit 3af5743d0a
5 changed files with 234 additions and 228 deletions

View File

@ -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 # 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} sm0 at gxio? addr 0x04000300 gpirq 36 # etherstix, net{MMC,CF,DUO}
sm1 at gxio? addr 0x08000300 gpirq 27 # netDUO(2nd NIC) sm1 at gxio? addr 0x08000300 gpirq 27 # netDUO(2nd NIC)
# PCMCIA/CF card # integrated PCMCIA/CF controller
gxpcic* at gxio? addr 0x20000000 gpirq 11 # cfstix, netCF pxapcic0 at pxaip? # cfstix, netCF
pcmcia* at gxpcic?
# PCMCIA bus support
pcmcia* at pxapcic?
# PCMCIA serial interfaces # PCMCIA serial interfaces
com* at pcmcia? function ? # Modems and serial cards com* at pcmcia? function ? # Modems and serial cards

View File

@ -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 # 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 attach sm at gxio with sm_gxio
file arch/evbarm/gumstix/if_sm_gxio.c sm_gxio file arch/evbarm/gumstix/if_sm_gxio.c sm_gxio
device gxpcic: pcmciabus # PCMCIA/CF socket and GPIO controllers
attach gxpcic at gxio attach pxapcic at pxaip with pxapcic_gxpcic
file arch/arm/sa11x0/sa11xx_pcic.c gxpcic file arch/evbarm/gumstix/gxpcic.c pxapcic_gxpcic
file arch/evbarm/gumstix/gxpcic.c gxpcic

View File

@ -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. * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation.
* All rights reserved. * All rights reserved.
@ -292,6 +292,7 @@ int comcnspeed = CONSPEED;
int comcnmode = CONMODE; int comcnmode = CONMODE;
extern void gxio_config_pin(void); extern void gxio_config_pin(void);
extern void gxio_config_busheader(char *);
/* /*
* void cpu_reboot(int howto, char *bootstr) * void cpu_reboot(int howto, char *bootstr)
@ -936,7 +937,6 @@ read_system_serial()
static void static void
process_kernel_args(int argc, char *argv[]) process_kernel_args(int argc, char *argv[])
{ {
extern char busheader[MAX_BOOT_STRING];
static const char busheader_name[] = "busheader="; static const char busheader_name[] = "busheader=";
int i, j; int i, j;
@ -951,8 +951,8 @@ process_kernel_args(int argc, char *argv[])
for (i = 1, j = 0; i < argc; i++) { for (i = 1, j = 0; i < argc; i++) {
if (!strncmp(argv[i], busheader_name, strlen(busheader_name))) { if (!strncmp(argv[i], busheader_name, strlen(busheader_name))) {
strncpy(busheader, /* configure for GPIOs of busheader side */
argv[i] + strlen(busheader_name), MAX_BOOT_STRING); gxio_config_busheader(argv[i] + strlen(busheader_name));
continue; continue;
} }
if (j == MAX_BOOT_STRING) { if (j == MAX_BOOT_STRING) {

View File

@ -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. * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation.
* All rights reserved. * All rights reserved.
@ -31,7 +31,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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" #include "opt_gxio.h"
@ -58,7 +58,7 @@ struct gpioconf {
}; };
struct gxioconf { struct gxioconf {
const char *name; const char *name;
void (*config)(struct gxio_softc *); void (*config)(void);
}; };
static int gxiomatch(struct device *, struct cfdata *, 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 *); static int gxioprint(void *, const char *);
void gxio_config_pin(void); void gxio_config_pin(void);
static void void gxio_config_busheader(char *);
gxio_config_gpio(struct gxio_softc *, const struct gxioconf *, char *); static void gxio_config_gpio(const struct gxioconf *, char *);
static void cfstix_config(struct gxio_softc *); static void cfstix_config(void);
static void etherstix_config(struct gxio_softc *); static void etherstix_config(void);
static void netcf_config(struct gxio_softc *); static void netcf_config(void);
static void netduommc_config(struct gxio_softc *); static void netduommc_config(void);
static void netduo_config(struct gxio_softc *); static void netduo_config(void);
static void netmmc_config(struct gxio_softc *); static void netmmc_config(void);
static void wifistix_cf_config(void);
CFATTACH_DECL( CFATTACH_DECL(
gxio, sizeof(struct gxio_softc), gxiomatch, gxioattach, NULL, NULL); gxio, sizeof(struct gxio_softc), gxiomatch, gxioattach, NULL, NULL);
@ -137,6 +138,7 @@ static const struct gxioconf busheader_conf[] = {
{ "netduo-mmc", netduommc_config }, { "netduo-mmc", netduommc_config },
{ "netduo", netduo_config }, { "netduo", netduo_config },
{ "netmmc", netmmc_config }, { "netmmc", netmmc_config },
{ "wifistix-cf", wifistix_cf_config },
{ "wifistix", cfstix_config }, { "wifistix", cfstix_config },
{ NULL } { NULL }
}; };
@ -173,11 +175,8 @@ gxioattach(struct device *parent, struct device *self, void *aux)
PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh)) PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh))
return; 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); config_search_ia(gxiosearch, self, "gxio", NULL);
} }
@ -231,9 +230,15 @@ gxio_config_pin()
pxa2x0_gpio_set_function(gpioconf[i].pin, gpioconf[i].value); pxa2x0_gpio_set_function(gpioconf[i].pin, gpioconf[i].value);
} }
void
gxio_config_busheader(char *expansion)
{
gxio_config_gpio(busheader_conf, expansion);
}
static void static void
gxio_config_gpio(struct gxio_softc *sc, gxio_config_gpio(const struct gxioconf *gxioconflist, char *expansion)
const struct gxioconf *gxioconflist, char *expansion)
{ {
int i, rv; int i, rv;
@ -243,7 +248,7 @@ gxio_config_gpio(struct gxio_softc *sc,
rv = strncmp(expansion, gxioconflist[i].name, rv = strncmp(expansion, gxioconflist[i].name,
strlen(gxioconflist[i].name) + 1); strlen(gxioconflist[i].name) + 1);
if (rv == 0) { if (rv == 0) {
gxioconflist[i].config(sc); gxioconflist[i].config();
break; break;
} }
} }
@ -251,21 +256,17 @@ gxio_config_gpio(struct gxio_softc *sc,
static void static void
cfstix_config(struct gxio_softc *sc) cfstix_config()
{ {
u_int gpio, npoe_fn; u_int gpio, npoe_fn;
bus_space_write_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR, #if 1
bus_space_read_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR) & ~MECR_NOS); /* this configuration set by pxapcic_attach_common()::pxa2x0_pcic.c */
#else
pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_SET); /* RESET */ pxa2x0_gpio_set_function(11, GPIO_IN); /* PCD1 */
delay(50); pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY1/~IRQ1 */
pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_CLR); #endif
pxa2x0_gpio_set_function(4, GPIO_IN); /* BVD1/~STSCHG1 */
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 */
for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++) for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++)
npoe_fn |= pxa2x0_gpio_get_function(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(50, GPIO_ALT_FN_2_OUT); /* nPIOR */
pxa2x0_gpio_set_function(51, GPIO_ALT_FN_2_OUT); /* nPIOW */ 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(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(54, GPIO_ALT_FN_2_OUT); /* pSKTSEL */
pxa2x0_gpio_set_function(55, GPIO_ALT_FN_2_OUT); /* nPREG */ 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(56, GPIO_ALT_FN_1_IN); /* nPWAIT */
pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */ pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */
} }
/* ARGSUSED */
static void static void
etherstix_config(struct gxio_softc *sc) etherstix_config()
{ {
pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */
@ -296,27 +297,27 @@ etherstix_config(struct gxio_softc *sc)
} }
static void static void
netcf_config(struct gxio_softc *sc) netcf_config()
{ {
etherstix_config(sc); etherstix_config();
cfstix_config(sc); cfstix_config();
} }
static void static void
netduommc_config(struct gxio_softc *sc) netduommc_config()
{ {
netduo_config(sc); netduo_config();
/* mmc not yet... */ /* mmc not yet... */
} }
static void 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(78, GPIO_ALT_FN_2_OUT); /* nCS 2 */
pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */ pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */
@ -326,10 +327,25 @@ netduo_config(struct gxio_softc *sc)
} }
static void static void
netmmc_config(struct gxio_softc *sc) netmmc_config()
{ {
etherstix_config(sc); etherstix_config();
/* mmc not yet... */ /* 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();
}

View File

@ -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. * Copyright (C) 2005, 2006 WIDE Project and SOUM Corporation.
* All rights reserved. * All rights reserved.
@ -80,7 +80,7 @@
#include <arch/arm/xscale/pxa2x0var.h> #include <arch/arm/xscale/pxa2x0var.h>
#include <arch/arm/xscale/pxa2x0reg.h> #include <arch/arm/xscale/pxa2x0reg.h>
#include <arch/arm/sa11x0/sa11xx_pcicvar.h> #include <arch/arm/xscale/pxa2x0_pcic.h>
#include <arch/evbarm/gumstix/gumstixvar.h> #include <arch/evbarm/gumstix/gumstixvar.h>
@ -92,43 +92,31 @@
#define HAVE_CARD(r) (!((r) & GPIO_SET)) #define HAVE_CARD(r) (!((r) & GPIO_SET))
#define GXIO_GPIO8_RESET 8 #define GXIO_GPIRQ11_CD1 11
#define GXIO_GPIRQ11_nCD 11 #define GXIO_GPIRQ26_PRDY1 26
#define GXIO_GPIO26_READY 26 #define GXIO_GPIRQ27_PRDY2 27
#define GXIO_GPIRQ36_CD2 36
struct gxpcic_softc;
struct gxpcic_socket { static int gxpcic_match(struct device *, struct cfdata *, void *);
struct sapcic_socket ss; /* inherit socket for sa11x0 pcic */ static void gxpcic_attach(struct device *, struct device *, void *);
}; static void gxpcic_pcic_socket_setup(struct pxapcic_socket *);
struct gxpcic_softc { static u_int gxpcic_read(struct pxapcic_socket *, int);
struct sapcic_softc sc_pc; /* inherit SA11xx pcic */ static void gxpcic_write(struct pxapcic_socket *, int, u_int);
static void gxpcic_set_power(struct pxapcic_socket *, int);
bus_space_tag_t sc_iot; static void gxpcic_clear_intr(struct pxapcic_socket *);
bus_space_handle_t sc_ioh; static void *gxpcic_intr_establish(struct pxapcic_socket *, int,
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,
int (*)(void *), void *); 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); gxpcic_match, gxpcic_attach, NULL, NULL);
static struct sapcic_tag gxpcic_tag = { static struct pxapcic_tag gxpcic_pcic_functions = {
gxpcic_read, gxpcic_read,
gxpcic_write, gxpcic_write,
gxpcic_set_power, gxpcic_set_power,
@ -137,6 +125,14 @@ static struct sapcic_tag gxpcic_tag = {
gxpcic_intr_disestablish, 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 static int
gxpcic_match(struct device *parent, struct cfdata *cf, void *aux) 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 { struct {
int gpio; int gpio;
u_int fn; u_int fn;
} gpiomodes[] = { } pcic_gpiomodes[] = {
{ 48, GPIO_ALT_FN_2_OUT }, /* nPOE */ { 48, GPIO_ALT_FN_2_OUT }, /* nPOE */
{ 49, GPIO_ALT_FN_2_OUT }, /* nPWE */ { 49, GPIO_ALT_FN_2_OUT }, /* nPWE */
{ 50, GPIO_ALT_FN_2_OUT }, /* nPIOR */ { 50, GPIO_ALT_FN_2_OUT }, /* nPIOR */
{ 51, GPIO_ALT_FN_2_OUT }, /* nPIOW */ { 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 */ { 54, GPIO_ALT_FN_2_OUT }, /* pSKTSEL */
{ 55, GPIO_ALT_FN_2_OUT }, /* nPREG */ { 55, GPIO_ALT_FN_2_OUT }, /* nPREG */
{ 56, GPIO_ALT_FN_1_IN }, /* nPWAIT */ { 56, GPIO_ALT_FN_1_IN }, /* nPWAIT */
@ -158,13 +156,17 @@ gxpcic_match(struct device *parent, struct cfdata *cf, void *aux)
u_int reg; u_int reg;
int i; int i;
for (i = 0; gpiomodes[i].gpio != -1; i++) { /*
reg = pxa2x0_gpio_get_function(gpiomodes[i].gpio); * Check GPIO configuration. If you use these, it is sure already
if (GPIO_FN(reg) != GPIO_FN(gpiomodes[i].fn) || * to have been set by gxio.
GPIO_FN_IS_OUT(reg) != GPIO_FN_IS_OUT(gpiomodes[i].fn)) */
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; break;
} }
if (gpiomodes[i].gpio != -1) if (pcic_gpiomodes[i].gpio != -1)
return 0; return 0;
return 1; /* match */ return 1; /* match */
@ -173,166 +175,85 @@ gxpcic_match(struct device *parent, struct cfdata *cf, void *aux)
static void static void
gxpcic_attach(struct device *parent, struct device *self, void *aux) gxpcic_attach(struct device *parent, struct device *self, void *aux)
{ {
struct gxio_softc *gxsc = device_private(parent); struct pxapcic_softc *sc = (struct pxapcic_softc *)self;
struct gxpcic_softc *sc = device_private(self); struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux;
struct gxio_attach_args *gxa = aux; int nslot, i;
struct pcmciabus_attach_args paa;
int mecr, val, i, n;
aprint_normal("\n"); sc->sc_iot = pxa->pxa_iot;
aprint_naive("\n");
sc->sc_iot = sc->sc_pc.sc_iot = gxa->gxa_iot; nslot = gxpcic_count_slot(sc);
sc->sc_ioh = gxsc->sc_ioh;
sc->sc_gpirq = gxa->gxa_gpirq;
sc->sc_cards = 0;
n = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR) & MECR_NOS ? for (i = 0; i < nslot; i++) {
2 : 1; sc->sc_irqpin[i] = gxpcic_slot_irqs[i].prdy;
for (i = 0; i < n; i++) { sc->sc_irqcfpin[i] = gxpcic_slot_irqs[i].cd;
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);
} }
sc->sc_nslots = nslot;
pxapcic_attach_common(sc, &gxpcic_pcic_socket_setup);
} }
static int static void
gxpcic_card_detect(void *arg) gxpcic_pcic_socket_setup(struct pxapcic_socket *so)
{ {
struct gxpcic_socket *socket = arg; struct pxapcic_softc *sc = so->sc;
struct gxpcic_softc *sc = (struct gxpcic_softc *)socket->ss.sc;
int sock_no = socket->ss.socket;
int mecr, last, val, s;
s = splbio(); /* 3.3V only? */
last = sc->sc_cards; so->power_capability = PXAPCIC_POWER_3V;
val = pxa2x0_gpio_get_function(GXIO_GPIRQ11_nCD); so->pcictag_cookie = NULL;
if (HAVE_CARD(val)) { so->pcictag = &gxpcic_pcic_functions;
sc->sc_cards |= 1<<sock_no;
/* if it is the first card, turn on expansion memory control. */
if (last == 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);
}
} else {
sc->sc_cards &= ~(1<<sock_no);
/* if we loast all cards, turn off expansion memory control. */
if (sc->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);
DPRINTF(("%s: card %d %s\n", sc->sc_pc.sc_dev.dv_xname, sock_no, bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh,
HAVE_CARD(val) ? "inserted" : "removed")); MEMCTL_MCMEM(so->socket), MC_TIMING_VAL(9 ,9, 29));
bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh,
sapcic_intr(arg); MEMCTL_MCATT(so->socket), MC_TIMING_VAL(9 ,9, 29));
bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh,
return 1; MEMCTL_MCIO(so->socket), MC_TIMING_VAL(5 ,5, 16));
} }
/* ARGSUSED */ static u_int
static int gxpcic_read(struct pxapcic_socket *so, int which)
gxpcic_read(struct sapcic_socket *so, int which)
{ {
int reg; int reg;
switch (which) { switch (which) {
case SAPCIC_STATUS_CARD: case PXAPCIC_CARD_STATUS:
reg = pxa2x0_gpio_get_function(GXIO_GPIRQ11_nCD); reg = pxa2x0_gpio_get_function(gxpcic_slot_irqs[so->socket].cd);
return (HAVE_CARD(reg) ? return (HAVE_CARD(reg) ?
SAPCIC_CARD_VALID : SAPCIC_CARD_INVALID); PXAPCIC_CARD_VALID : PXAPCIC_CARD_INVALID);
case SAPCIC_STATUS_READY: case PXAPCIC_CARD_READY:
reg = pxa2x0_gpio_get_function(GXIO_GPIO26_READY); reg = pxa2x0_gpio_get_function(
gxpcic_slot_irqs[so->socket].prdy);
return (reg & GPIO_SET ? 1 : 0); return (reg & GPIO_SET ? 1 : 0);
default: default:
panic("%s: bogus register", __FUNCTION__); panic("%s: bogus register", __FUNCTION__);
} }
/* NOTREACHED */
} }
/* ARGSUSED */ /* ARGSUSED */
static void 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) { switch (which) {
case SAPCIC_CONTROL_RESET: case PXAPCIC_CARD_POWER:
#if 0 /* XXXX: Our PXA2x0 no necessary ??? */ case PXAPCIC_CARD_RESET:
if (arg) /* We can't */
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:
break; break;
default: default:
panic("%s: bogus register", __FUNCTION__); panic("%s: bogus register", __FUNCTION__);
} }
/* NOTREACHED */
} }
static void 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__); panic("%s: bogus arg\n", __FUNCTION__);
/* 3.3V only? */ /* 3.3V only? */
@ -340,34 +261,102 @@ gxpcic_set_power(struct sapcic_socket *__so, int arg)
/* ARGSUSED */ /* ARGSUSED */
static void static void
gxpcic_clear_intr(int arg) gxpcic_clear_intr(struct pxapcic_socket *so)
{ {
/* nothing to do */ /* nothing to do */
} }
static void * 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) int (* ih_fun)(void *), void *ih_arg)
{ {
__attribute__((unused))struct gxpcic_softc *sc =
(struct gxpcic_softc *)so->sc;
int gpirq;
gpirq = GXIO_GPIO26_READY; return pxa2x0_gpio_intr_establish(so->irqpin, IST_EDGE_FALLING,
level, ih_fun, ih_arg);
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);
} }
/* ARGSUSED */
static void 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;
} }