diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 7774d17..a75906f 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -195,6 +195,103 @@ void __init at91_add_device_eth(struct at91_eth_data *data) void __init at91_add_device_eth(struct at91_eth_data *data) {} #endif +/* -------------------------------------------------------------------- + * Compact Flash / PCMCIA + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) +static struct at91_cf_data cf_data; + +#define CF_BASE AT91_CHIPSELECT_4 + +static struct resource cf_resources[] = { + [0] = { + .start = CF_BASE, + /* ties up CS4 and CS5 */ + .end = CF_BASE + SZ_512M - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + }, +}; + +static struct platform_device at91sam9260_cf_device = { + .name = "at91_cf", + .id = -1, + .dev = { + .platform_data = &cf_data, + }, + .resource = cf_resources, + .num_resources = ARRAY_SIZE(cf_resources), +}; + +void __init at91_add_device_cf(struct at91_cf_data *data) +{ + unsigned int csa; + int cs; + + if (!data) + return; + + cs = data->chipselect; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + if (cs == 4) + csa |= AT91_MATRIX_CS4A_SMC_CF1; + else if (cs == 5) + csa |= AT91_MATRIX_CS5A_SMC_CF2; + else + BUG(); + + at91_sys_write(AT91_MATRIX_EBICSA, csa); + + /* Timing for sam9260 */ + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(cs), + AT91_SMC_NWESETUP_(3) | AT91_SMC_NCS_WRSETUP_(3) + | AT91_SMC_NRDSETUP_(3) | AT91_SMC_NCS_RDSETUP_(3)); + + at91_sys_write(AT91_SMC_PULSE(cs), + AT91_SMC_NWEPULSE_(15) | AT91_SMC_NCS_WRPULSE_(17) + | AT91_SMC_NRDPULSE_(13) | AT91_SMC_NCS_RDPULSE_(15)); + + at91_sys_write(AT91_SMC_CYCLE(cs), + AT91_SMC_NWECYCLE_(21) | AT91_SMC_NRDCYCLE_(18)); + + at91_sys_write(AT91_SMC_MODE(cs), + AT91_SMC_READMODE | AT91_SMC_WRITEMODE + | AT91_SMC_EXNWMODE_READY + | AT91_SMC_BAT_SELECT | AT91_SMC_DBW_16 + | AT91_SMC_TDF_(10) | AT91_SMC_TDFMODE); + + /* input/irq */ + if (data->irq_pin) { + at91_set_gpio_input(data->irq_pin, 1); + at91_set_deglitch(data->irq_pin, 1); + } + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + + /* outputs, initially off */ + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + at91_set_gpio_output(data->rst_pin, 0); + + /* force poweron defaults for this pin ... */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* A25/CFRNW */ + + if (cs == 4) + at91_set_A_periph(AT91_PIN_PC8, 0); /* NCS4/CFCS0 */ + else + at91_set_A_periph(AT91_PIN_PC9, 0); /* NCS5/CFCS1 */ + at91_set_A_periph(AT91_PIN_PC15, 1); /* nWAIT */ + at91_set_B_periph(AT91_PIN_PC6, 0); /* CFCE1 */ + at91_set_B_periph(AT91_PIN_PC7, 0); /* CFCE2 */ + + cf_data = *data; + platform_device_register(&at91sam9260_cf_device); +} +#else +void __init at91_add_device_cf(struct at91_cf_data *data) {} +#endif /* -------------------------------------------------------------------- * MMC / SD diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index cb20e70..d18f80d 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -84,6 +84,16 @@ static struct at91_udc_data __initdata ek_udc_data = { .pullup_pin = 0, /* pull-up driven by UDC */ }; +/* + * Compact Flash + */ +static struct at91_cf_data __initdata ek_cf_data = { + .irq_pin = AT91_PIN_PC14, + .det_pin = AT91_PIN_PC9, + // .vcc_pin = ... always powered + .rst_pin = AT91_PIN_PC11, + .chipselect = 4, +}; /* * Audio @@ -240,6 +250,8 @@ static void __init ek_board_init(void) at91_add_device_mmc(0, &ek_mmc_data); /* I2C */ at91_add_device_i2c(NULL, 0); + /* Compact Flash */ + at91_add_device_cf(&ek_cf_data); /* SSC (to AT73C213) */ at73c213_set_clk(&at73c213_data); at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX); diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index e0f8840..48bfb3e 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -273,7 +273,7 @@ config BFIN_CFPCMCIA config AT91_CF tristate "AT91 CompactFlash Controller" - depends on PCMCIA && ARCH_AT91RM9200 + depends on PCMCIA && (ARCH_AT91RM9200 || ARCH_AT91SAM9260) help Say Y here to support the CompactFlash controller on AT91 chips. Or choose M to compile the driver as a module named "at91_cf". diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index a0ffb8e..fa40174 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -24,8 +24,14 @@ #include #include -#include +#if defined(CONFIG_ARCH_AT91RM9200) +#include +#elif defined(CONFIG_ARCH_AT91SAM9260) +#include +#else +#error "Unsupported AT91 processor" +#endif /* * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW; @@ -157,7 +163,11 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) /* * Use 16 bit accesses unless/until we need 8-bit i/o space. */ +#if defined(CONFIG_ARCH_AT91RM9200) csr = at91_sys_read(AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW; +#else + csr = at91_sys_read(AT91_SMC_MODE(cf->board->chipselect)) & ~AT91_SMC_DBW; +#endif /* * NOTE: this CF controller ignores IOIS16, so we can't really do @@ -176,7 +186,11 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) csr |= AT91_SMC_DBW_16; pr_debug("%s: 16bit i/o bus\n", driver_name); } +#if defined(CONFIG_ARCH_AT91RM9200) at91_sys_write(AT91_SMC_CSR(cf->board->chipselect), csr); +#else + at91_sys_write(AT91_SMC_MODE(cf->board->chipselect), csr); +#endif io->start = cf->socket.io_offset; io->stop = io->start + SZ_2K - 1;