there is a new register (timings) vs SAM9 and thus a new mapping Signed-off-by: Eric Bénard <eric@xxxxxxxxxx> --- arch/arm/mach-at91/generic.h | 7 ++ arch/arm/mach-at91/include/mach/sama5_smc.h | 124 +++++++++++++++++++++ arch/arm/mach-at91/sama5_smc.c | 161 ++++++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 arch/arm/mach-at91/include/mach/sama5_smc.h create mode 100644 arch/arm/mach-at91/sama5_smc.c diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index a47bcb2..3a510fb 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -36,4 +36,11 @@ static inline struct device_d *at91_add_sam9_smc(int id, resource_size_t start, IORESOURCE_MEM, NULL); } +static inline struct device_d *at91_add_sama5_smc(int id, resource_size_t start, + resource_size_t size) +{ + return add_generic_device("at91sama5-smc", id, NULL, start, size, + IORESOURCE_MEM, NULL); +} + void at91_rtt_irq_fixup(void *base); diff --git a/arch/arm/mach-at91/include/mach/sama5_smc.h b/arch/arm/mach-at91/include/mach/sama5_smc.h new file mode 100644 index 0000000..dde4cce --- /dev/null +++ b/arch/arm/mach-at91/include/mach/sama5_smc.h @@ -0,0 +1,124 @@ +/* + * [origin: Linux kernel include/asm-arm/arch-at91/at91sam9_smc.h] + * + * Copyright (C) 2007 Andrew Victor + * Copyright (C) 2007 Atmel Corporation. + * Copyright (C) 2013 Eric Bénard + * + * Static Memory Controllers (HSMC) - System peripherals registers. + * Based on SAMA5D3 series datasheet revision B. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef SAMA5_SMC_H +#define SAMA5_SMC_H + +#define at91_smc_read(id, field) \ + __raw_readl(AT91_BASE_SMC + ((id) * 0x14) + field) + +#define at91_smc_write(id, field, value) \ + __raw_writel(value, AT91_BASE_SMC + ((id) * 0x14) + field) + +#ifndef __ASSEMBLY__ +struct sama5_smc_config { + /* Setup register */ + u8 ncs_read_setup; + u8 nrd_setup; + u8 ncs_write_setup; + u8 nwe_setup; + + /* Pulse register */ + u8 ncs_read_pulse; + u8 nrd_pulse; + u8 ncs_write_pulse; + u8 nwe_pulse; + + /* Cycle register */ + u16 read_cycle; + u16 write_cycle; + + /* Timings register */ + u8 cle_to_ren_low_delay; + u8 ale_to_data_start; + u8 ale_to_ren_low_delay; + u8 off_chip_memory_scrambling_enable; + u8 ready_to_ren_low_delay; + u8 wen_high_to_ren_to_busy; + u8 ready_busy_line_selection; + u8 nand_flash_selection; + + /* Mode register */ + u32 mode; + u8 tdf_cycles:4; +}; + +extern void sama5_smc_configure(int id, int cs, struct sama5_smc_config *config); +extern void sama5_smc_read(int id, int cs, struct sama5_smc_config *config); +extern void sama5_smc_read_mode(int id, int cs, struct sama5_smc_config *config); +extern void sama5_smc_write_mode(int id, int cs, struct sama5_smc_config *config); +#endif + +#define AT91_SMC_SETUP 0x00 /* Setup Register for CS n */ +#define AT91_SMC_NWESETUP (0x3f << 0) /* NWE Setup Length */ +#define AT91_SMC_NWESETUP_(x) ((x) << 0) +#define AT91_SMC_NCS_WRSETUP (0x3f << 8) /* NCS Setup Length in Write Access */ +#define AT91_SMC_NCS_WRSETUP_(x) ((x) << 8) +#define AT91_SMC_NRDSETUP (0x3f << 16) /* NRD Setup Length */ +#define AT91_SMC_NRDSETUP_(x) ((x) << 16) +#define AT91_SMC_NCS_RDSETUP (0x3f << 24) /* NCS Setup Length in Read Access */ +#define AT91_SMC_NCS_RDSETUP_(x) ((x) << 24) + +#define AT91_SMC_PULSE 0x04 /* Pulse Register for CS n */ +#define AT91_SMC_NWEPULSE (0x7f << 0) /* NWE Pulse Length */ +#define AT91_SMC_NWEPULSE_(x) ((x) << 0) +#define AT91_SMC_NCS_WRPULSE (0x7f << 8) /* NCS Pulse Length in Write Access */ +#define AT91_SMC_NCS_WRPULSE_(x)((x) << 8) +#define AT91_SMC_NRDPULSE (0x7f << 16) /* NRD Pulse Length */ +#define AT91_SMC_NRDPULSE_(x) ((x) << 16) +#define AT91_SMC_NCS_RDPULSE (0x7f << 24) /* NCS Pulse Length in Read Access */ +#define AT91_SMC_NCS_RDPULSE_(x)((x) << 24) + +#define AT91_SMC_CYCLE 0x08 /* Cycle Register for CS n */ +#define AT91_SMC_NWECYCLE (0x1ff << 0 ) /* Total Write Cycle Length */ +#define AT91_SMC_NWECYCLE_(x) ((x) << 0) +#define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */ +#define AT91_SMC_NRDCYCLE_(x) ((x) << 16) + +#define AT91_SMC_TIMINGS 0x0c /* Cycle Register for CS n */ +#define AT91C_SMC_TIMINGS_TCLR (0xf << 0) +#define AT91C_SMC_TIMINGS_TCLR_(x) (x & 0xf) +#define AT91C_SMC_TIMINGS_TADL (0xf << 4) +#define AT91C_SMC_TIMINGS_TADL_(x) ((x & 0xf) << 4) +#define AT91C_SMC_TIMINGS_TAR (0xf << 8) +#define AT91C_SMC_TIMINGS_TAR_(x) ((x & 0xf) << 8) +#define AT91C_SMC_TIMINGS_OCMS (0x01 << 12) +#define AT91C_SMC_TIMINGS_TRR (0xf << 16) +#define AT91C_SMC_TIMINGS_TRR_(x) ((x & 0xf) << 16) +#define AT91C_SMC_TIMINGS_TWB (0xf << 24) +#define AT91C_SMC_TIMINGS_TWB_(x) ((x & 0xf) << 24) +#define AT91C_SMC_TIMINGS_RBNSEL (0x7 << 28) +#define AT91C_SMC_TIMINGS_RBNSEL_(x) ((x & 0x7) << 28) +#define AT91C_SMC_TIMINGS_NFSEL (0x01 << 31) + +#define AT91_SMC_MODE 0x10 /* Mode Register for CS n */ +#define AT91_SMC_READMODE (1 << 0) /* Read Mode */ +#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */ +#define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */ +#define AT91_SMC_EXNWMODE_DISABLE (0 << 4) +#define AT91_SMC_EXNWMODE_FROZEN (2 << 4) +#define AT91_SMC_EXNWMODE_READY (3 << 4) +#define AT91_SMC_BAT (1 << 8) /* Byte Access Type */ +#define AT91_SMC_BAT_SELECT (0 << 8) +#define AT91_SMC_BAT_WRITE (1 << 8) +#define AT91_SMC_DBW (1 << 12) /* Data Bus Width */ +#define AT91_SMC_DBW_8 (0 << 12) +#define AT91_SMC_DBW_16 (1 << 12) +#define AT91_SMC_TDF (0xf << 16) /* Data Float Time. */ +#define AT91_SMC_TDF_(x) ((x) << 16) +#define AT91_SMC_TDFMODE (1 << 20) /* TDF Optimization - Enabled */ + +#endif diff --git a/arch/arm/mach-at91/sama5_smc.c b/arch/arm/mach-at91/sama5_smc.c new file mode 100644 index 0000000..ea66c97 --- /dev/null +++ b/arch/arm/mach-at91/sama5_smc.c @@ -0,0 +1,161 @@ +/* + * linux/arch/arm/mach-at91/sama5smc.c + * + * Copyright (C) 2008 Andrew Victor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <mach/hardware.h> +#include <mach/io.h> + +#include <mach/sama5_smc.h> + +#define AT91_SMC_CS(id, n) (smc_base_addr[id] + ((n) * 0x14)) + +static void __iomem *smc_base_addr[2]; + +static void sama5smc_cs_write_mode(void __iomem *base, + struct sama5_smc_config *config) +{ + __raw_writel(config->mode + | AT91_SMC_TDF_(config->tdf_cycles), + base + AT91_SMC_MODE); +} + +void sama5smc_write_mode(int id, int cs, + struct sama5_smc_config *config) +{ + sama5smc_cs_write_mode(AT91_SMC_CS(id, cs), config); +} + +static void sama5smc_cs_configure(void __iomem *base, + struct sama5_smc_config *config) +{ + + /* Setup register */ + __raw_writel(AT91_SMC_NWESETUP_(config->nwe_setup) + | AT91_SMC_NCS_WRSETUP_(config->ncs_write_setup) + | AT91_SMC_NRDSETUP_(config->nrd_setup) + | AT91_SMC_NCS_RDSETUP_(config->ncs_read_setup), + base + AT91_SMC_SETUP); + + /* Pulse register */ + __raw_writel(AT91_SMC_NWEPULSE_(config->nwe_pulse) + | AT91_SMC_NCS_WRPULSE_(config->ncs_write_pulse) + | AT91_SMC_NRDPULSE_(config->nrd_pulse) + | AT91_SMC_NCS_RDPULSE_(config->ncs_read_pulse), + base + AT91_SMC_PULSE); + + /* Cycle register */ + __raw_writel(AT91_SMC_NWECYCLE_(config->write_cycle) + | AT91_SMC_NRDCYCLE_(config->read_cycle), + base + AT91_SMC_CYCLE); + + /* Timings register */ + __raw_writel(AT91C_SMC_TIMINGS_TCLR_(config->cle_to_ren_low_delay) + | AT91C_SMC_TIMINGS_TADL_(config->ale_to_data_start) + | AT91C_SMC_TIMINGS_TAR_(config->ale_to_ren_low_delay) + | (config->off_chip_memory_scrambling_enable ? AT91C_SMC_TIMINGS_OCMS : 0) + | AT91C_SMC_TIMINGS_TRR_(config->ready_to_ren_low_delay) + | AT91C_SMC_TIMINGS_TWB_(config->wen_high_to_ren_to_busy) + | AT91C_SMC_TIMINGS_RBNSEL_(config->ready_busy_line_selection) + | (config->nand_flash_selection ? AT91C_SMC_TIMINGS_NFSEL : 0), + base + AT91_SMC_TIMINGS); + + /* Mode register */ + sama5smc_cs_write_mode(base, config); +} + +void sama5_smc_configure(int id, int cs, + struct sama5_smc_config *config) +{ + sama5smc_cs_configure(AT91_SMC_CS(id, cs), config); +} + +static void sama5smc_cs_read_mode(void __iomem *base, + struct sama5_smc_config *config) +{ + u32 val = __raw_readl(base + AT91_SMC_MODE); + + config->mode = (val & ~AT91_SMC_NWECYCLE); + config->tdf_cycles = (val & AT91_SMC_NWECYCLE) >> 16 ; +} + +void sama5smc_read_mode(int id, int cs, + struct sama5_smc_config *config) +{ + sama5smc_cs_read_mode(AT91_SMC_CS(id, cs), config); +} + +static void sama5smc_cs_read(void __iomem *base, + struct sama5_smc_config *config) +{ + u32 val; + + /* Setup register */ + val = __raw_readl(base + AT91_SMC_SETUP); + + config->nwe_setup = val & AT91_SMC_NWESETUP; + config->ncs_write_setup = (val & AT91_SMC_NCS_WRSETUP) >> 8; + config->nrd_setup = (val & AT91_SMC_NRDSETUP) >> 16; + config->ncs_read_setup = (val & AT91_SMC_NCS_RDSETUP) >> 24; + + /* Pulse register */ + val = __raw_readl(base + AT91_SMC_PULSE); + + config->nwe_setup = val & AT91_SMC_NWEPULSE; + config->ncs_write_pulse = (val & AT91_SMC_NCS_WRPULSE) >> 8; + config->nrd_pulse = (val & AT91_SMC_NRDPULSE) >> 16; + config->ncs_read_pulse = (val & AT91_SMC_NCS_RDPULSE) >> 24; + + /* Cycle register */ + val = __raw_readl(base + AT91_SMC_CYCLE); + + config->write_cycle = val & AT91_SMC_NWECYCLE; + config->read_cycle = (val & AT91_SMC_NRDCYCLE) >> 16; + + /* Mode register */ + sama5smc_cs_read_mode(base, config); +} + +void sama5smc_read(int id, int cs, struct sama5_smc_config *config) +{ + sama5smc_cs_read(AT91_SMC_CS(id, cs), config); +} + +static int at91sama5smc_probe(struct device_d *dev) +{ + int id = dev->id; + + if (id < 0) { + id = 0; + } else if (id > 1) { + dev_warn(dev, "id > 1\n"); + return -EIO; + } + + smc_base_addr[id] = dev_request_mem_region(dev, 0); + if (!smc_base_addr[id]) { + dev_err(dev, "Impossible to request smc.%d\n", id); + return -ENOMEM; + } + + return 0; +} + +static struct driver_d at91sama5smc_driver = { + .name = "at91sama5-smc", + .probe = at91sama5smc_probe, +}; + +static int at91sama5smc_init(void) +{ + return platform_driver_register(&at91sama5smc_driver); +} +coredevice_initcall(at91sama5smc_init); -- 1.8.3.1 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox