[PATCH 2/7] at91: introduce sama5d3's SMC support
Eric Bénard
eric at eukrea.com
Sat Dec 7 04:36:55 EST 2013
there is a new register (timings) vs SAM9 and thus a new mapping
Signed-off-by: Eric Bénard <eric at eukrea.com>
---
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
More information about the barebox
mailing list