[AVR32] SMC configuration in clock cycles
authorKristoffer Nyborg Gregertsen <kngregertsen@norway.atmel.com>
Fri, 17 Aug 2007 14:59:57 +0000 (16:59 +0200)
committerHaavard Skinnemoen <hskinnemoen@atmel.com>
Thu, 11 Oct 2007 11:32:49 +0000 (13:32 +0200)
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>
arch/avr32/boards/atngw100/flash.c
arch/avr32/boards/atstk1000/flash.c
arch/avr32/mach-at32ap/hsmc.c
include/asm-avr32/arch-at32ap/smc.h

index f9b32a8eab9b217bfca2db0e7f21c90b2cff5bf7..b07ae63aa54802eaa47b700c009da90c83f31a9a 100644 (file)
@@ -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");
index aac4300cca125afe112d97ce46a6fafec5acca72..3d0a102ad45ec1e8fd77ad4bd794b4d726a65888 100644 (file)
@@ -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");
index 5e22a750632b78755c24d84d05718c24822b587c..704607fbcc696d2223241ff26103176daa254b46 100644 (file)
@@ -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:
index 07152b7fd9c94da03f2c3d2fa1af3c9d00464b8c..c98eea44a70a08eba09b2d24b7f522dd6ea5b255 100644 (file)
 /*
  * All timing parameters are in nanoseconds.
  */
+struct smc_timing {
+       /* Delay from address valid to assertion of given strobe */
+       int ncs_read_setup;
+       int nrd_setup;
+       int ncs_write_setup;
+       int nwe_setup;
+
+       /* Pulse length of given strobe */
+       int ncs_read_pulse;
+       int nrd_pulse;
+       int ncs_write_pulse;
+       int nwe_pulse;
+
+       /* Total cycle length of given operation */
+       int read_cycle;
+       int write_cycle;
+
+       /* Minimal recovery times, will extend cycle if needed */
+       int ncs_read_recover;
+       int nrd_recover;
+       int ncs_write_recover;
+       int nwe_recover;
+};
+
+/*
+ * All timing parameters are in clock cycles.
+ */
 struct smc_config {
+
        /* Delay from address valid to assertion of given strobe */
-       u16             ncs_read_setup;
-       u16             nrd_setup;
-       u16             ncs_write_setup;
-       u16             nwe_setup;
+       u             ncs_read_setup;
+       u             nrd_setup;
+       u             ncs_write_setup;
+       u             nwe_setup;
 
        /* Pulse length of given strobe */
-       u16             ncs_read_pulse;
-       u16             nrd_pulse;
-       u16             ncs_write_pulse;
-       u16             nwe_pulse;
+       u             ncs_read_pulse;
+       u             nrd_pulse;
+       u             ncs_write_pulse;
+       u             nwe_pulse;
 
        /* Total cycle length of given operation */
-       u16             read_cycle;
-       u16             write_cycle;
+       u             read_cycle;
+       u             write_cycle;
 
        /* Bus width in bytes */
        u8              bus_width;
@@ -76,6 +104,9 @@ struct smc_config {
        unsigned int    tdf_mode:1;
 };
 
+extern void smc_set_timing(struct smc_config *config,
+                          const struct smc_timing *timing);
+
 extern int smc_set_configuration(int cs, const struct smc_config *config);
 extern struct smc_config *smc_get_configuration(int cs);