summary refs log tree commit diff
path: root/arch/avr32
diff options
context:
space:
mode:
authorKristoffer Nyborg Gregertsen <kngregertsen@norway.atmel.com>2007-08-17 16:59:57 +0200
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-10-11 13:32:49 +0200
commitaf8184718a322ae589efa583aa69ffdae61bf266 (patch)
tree7324ba9e6a14e78b89b703bea7d0594a0ae9ef6e /arch/avr32
parent193fdd1a99db8623697cb18a13dbcaa4eadbb1f2 (diff)
downloadlinux-af8184718a322ae589efa583aa69ffdae61bf266.tar.gz
[AVR32] SMC configuration in clock cycles
This patch makes the SMC configuration take timings in clock cycles
instead of nanoseconds. A function to calculate timings in clock
cycles is added.

This patch removes the rounding troubles of the previous SMC
configuration method.

[hskinnemoen@atmel.com: fix atstk1002/atngw100 flash config]
Signed-off-by: Kristoffer Nyborg Gregertsen <gregerts@stud.ntnu.no>
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32')
-rw-r--r--arch/avr32/boards/atngw100/flash.c5
-rw-r--r--arch/avr32/boards/atstk1000/flash.c5
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c129
3 files changed, 120 insertions, 19 deletions
diff --git a/arch/avr32/boards/atngw100/flash.c b/arch/avr32/boards/atngw100/flash.c
index f9b32a8eab9b..b07ae63aa548 100644
--- a/arch/avr32/boards/atngw100/flash.c
+++ b/arch/avr32/boards/atngw100/flash.c
@@ -15,7 +15,7 @@
 
 #include <asm/arch/smc.h>
 
-static struct smc_config flash_config __initdata = {
+static struct smc_timing flash_timing __initdata = {
 	.ncs_read_setup		= 0,
 	.nrd_setup		= 40,
 	.ncs_write_setup	= 0,
@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {
 
 	.read_cycle		= 120,
 	.write_cycle		= 120,
+};
 
+static struct smc_config flash_config __initdata = {
 	.bus_width		= 2,
 	.nrd_controlled		= 1,
 	.nwe_controlled		= 1,
@@ -82,6 +84,7 @@ static int __init atngw100_flash_init(void)
 {
 	int ret;
 
+	smc_set_timing(&flash_config, &flash_timing);
 	ret = smc_set_configuration(0, &flash_config);
 	if (ret < 0) {
 		printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
diff --git a/arch/avr32/boards/atstk1000/flash.c b/arch/avr32/boards/atstk1000/flash.c
index aac4300cca12..3d0a102ad45e 100644
--- a/arch/avr32/boards/atstk1000/flash.c
+++ b/arch/avr32/boards/atstk1000/flash.c
@@ -15,7 +15,7 @@
 
 #include <asm/arch/smc.h>
 
-static struct smc_config flash_config __initdata = {
+static struct smc_timing flash_timing __initdata = {
 	.ncs_read_setup		= 0,
 	.nrd_setup		= 40,
 	.ncs_write_setup	= 0,
@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {
 
 	.read_cycle		= 120,
 	.write_cycle		= 120,
+};
 
+static struct smc_config flash_config __initdata = {
 	.bus_width		= 2,
 	.nrd_controlled		= 1,
 	.nwe_controlled		= 1,
@@ -82,6 +84,7 @@ static int __init atstk1000_flash_init(void)
 {
 	int ret;
 
+	smc_set_timing(&flash_config, &flash_timing);
 	ret = smc_set_configuration(0, &flash_config);
 	if (ret < 0) {
 		printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index 5e22a750632b..704607fbcc69 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -29,16 +29,25 @@ struct hsmc {
 
 static struct hsmc *hsmc;
 
-int smc_set_configuration(int cs, const struct smc_config *config)
+void smc_set_timing(struct smc_config *config,
+		    const struct smc_timing *timing)
 {
+	int recover;
+	int cycle;
+
 	unsigned long mul;
-	unsigned long offset;
-	u32 setup, pulse, cycle, mode;
 
-	if (!hsmc)
-		return -ENODEV;
-	if (cs >= NR_CHIP_SELECTS)
-		return -EINVAL;
+	/* Reset all SMC timings */
+	config->ncs_read_setup	= 0;
+	config->nrd_setup	= 0;
+	config->ncs_write_setup	= 0;
+	config->nwe_setup	= 0;
+	config->ncs_read_pulse	= 0;
+	config->nrd_pulse	= 0;
+	config->ncs_write_pulse	= 0;
+	config->nwe_pulse	= 0;
+	config->read_cycle	= 0;
+	config->write_cycle	= 0;
 
 	/*
 	 * cycles = x / T = x * f
@@ -50,16 +59,102 @@ int smc_set_configuration(int cs, const struct smc_config *config)
 
 #define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
 
-	setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup))
-		 | HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup))
-		 | HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))
-		 | HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup)));
-	pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse))
-		 | HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))
-		 | HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse))
-		 | HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse)));
-	cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))
-		 | HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle)));
+	if (timing->ncs_read_setup > 0)
+		config->ncs_read_setup = ns2cyc(timing->ncs_read_setup);
+
+	if (timing->nrd_setup > 0)
+		config->nrd_setup = ns2cyc(timing->nrd_setup);
+
+	if (timing->ncs_write_setup > 0)
+		config->ncs_write_setup = ns2cyc(timing->ncs_write_setup);
+
+	if (timing->nwe_setup > 0)
+		config->nwe_setup = ns2cyc(timing->nwe_setup);
+
+	if (timing->ncs_read_pulse > 0)
+		config->ncs_read_pulse = ns2cyc(timing->ncs_read_pulse);
+
+	if (timing->nrd_pulse > 0)
+		config->nrd_pulse = ns2cyc(timing->nrd_pulse);
+
+	if (timing->ncs_write_pulse > 0)
+		config->ncs_write_pulse = ns2cyc(timing->ncs_write_pulse);
+
+	if (timing->nwe_pulse > 0)
+		config->nwe_pulse = ns2cyc(timing->nwe_pulse);
+
+	if (timing->read_cycle > 0)
+		config->read_cycle = ns2cyc(timing->read_cycle);
+
+	if (timing->write_cycle > 0)
+		config->write_cycle = ns2cyc(timing->write_cycle);
+
+	/* Extend read cycle in needed */
+	if (timing->ncs_read_recover > 0)
+		recover = ns2cyc(timing->ncs_read_recover);
+	else
+		recover = 1;
+
+	cycle = config->ncs_read_setup + config->ncs_read_pulse + recover;
+
+	if (config->read_cycle < cycle)
+		config->read_cycle = cycle;
+
+	/* Extend read cycle in needed */
+	if (timing->nrd_recover > 0)
+		recover = ns2cyc(timing->nrd_recover);
+	else
+		recover = 1;
+
+	cycle = config->nrd_setup + config->nrd_pulse + recover;
+
+	if (config->read_cycle < cycle)
+		config->read_cycle = cycle;
+
+	/* Extend write cycle in needed */
+	if (timing->ncs_write_recover > 0)
+		recover = ns2cyc(timing->ncs_write_recover);
+	else
+		recover = 1;
+
+	cycle = config->ncs_write_setup + config->ncs_write_pulse + recover;
+
+	if (config->write_cycle < cycle)
+		config->write_cycle = cycle;
+
+	/* Extend write cycle in needed */
+	if (timing->nwe_recover > 0)
+		recover = ns2cyc(timing->nwe_recover);
+	else
+		recover = 1;
+
+	cycle = config->nwe_setup + config->nwe_pulse + recover;
+
+	if (config->write_cycle < cycle)
+		config->write_cycle = cycle;
+}
+EXPORT_SYMBOL(smc_set_timing);
+
+int smc_set_configuration(int cs, const struct smc_config *config)
+{
+	unsigned long offset;
+	u32 setup, pulse, cycle, mode;
+
+	if (!hsmc)
+		return -ENODEV;
+	if (cs >= NR_CHIP_SELECTS)
+		return -EINVAL;
+
+	setup = (HSMC_BF(NWE_SETUP, config->nwe_setup)
+		 | HSMC_BF(NCS_WR_SETUP, config->ncs_write_setup)
+		 | HSMC_BF(NRD_SETUP, config->nrd_setup)
+		 | HSMC_BF(NCS_RD_SETUP, config->ncs_read_setup));
+	pulse = (HSMC_BF(NWE_PULSE, config->nwe_pulse)
+		 | HSMC_BF(NCS_WR_PULSE, config->ncs_write_pulse)
+		 | HSMC_BF(NRD_PULSE, config->nrd_pulse)
+		 | HSMC_BF(NCS_RD_PULSE, config->ncs_read_pulse));
+	cycle = (HSMC_BF(NWE_CYCLE, config->write_cycle)
+		 | HSMC_BF(NRD_CYCLE, config->read_cycle));
 
 	switch (config->bus_width) {
 	case 1: