[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