Change to use pxapcic from sa11xx_pcic.
Support multiple socket. But not tested.
This commit is contained in:
parent
e0c180145d
commit
3af5743d0a
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue