Commit af818471 authored by Kristoffer Nyborg Gregertsen's avatar Kristoffer Nyborg Gregertsen Committed by Haavard Skinnemoen

[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: default avatarKristoffer Nyborg Gregertsen <gregerts@stud.ntnu.no>
Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 193fdd1a
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <asm/arch/smc.h> #include <asm/arch/smc.h>
static struct smc_config flash_config __initdata = { static struct smc_timing flash_timing __initdata = {
.ncs_read_setup = 0, .ncs_read_setup = 0,
.nrd_setup = 40, .nrd_setup = 40,
.ncs_write_setup = 0, .ncs_write_setup = 0,
...@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = { ...@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {
.read_cycle = 120, .read_cycle = 120,
.write_cycle = 120, .write_cycle = 120,
};
static struct smc_config flash_config __initdata = {
.bus_width = 2, .bus_width = 2,
.nrd_controlled = 1, .nrd_controlled = 1,
.nwe_controlled = 1, .nwe_controlled = 1,
...@@ -82,6 +84,7 @@ static int __init atngw100_flash_init(void) ...@@ -82,6 +84,7 @@ static int __init atngw100_flash_init(void)
{ {
int ret; int ret;
smc_set_timing(&flash_config, &flash_timing);
ret = smc_set_configuration(0, &flash_config); ret = smc_set_configuration(0, &flash_config);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "atngw100: failed to set NOR flash timing\n"); printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <asm/arch/smc.h> #include <asm/arch/smc.h>
static struct smc_config flash_config __initdata = { static struct smc_timing flash_timing __initdata = {
.ncs_read_setup = 0, .ncs_read_setup = 0,
.nrd_setup = 40, .nrd_setup = 40,
.ncs_write_setup = 0, .ncs_write_setup = 0,
...@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = { ...@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {
.read_cycle = 120, .read_cycle = 120,
.write_cycle = 120, .write_cycle = 120,
};
static struct smc_config flash_config __initdata = {
.bus_width = 2, .bus_width = 2,
.nrd_controlled = 1, .nrd_controlled = 1,
.nwe_controlled = 1, .nwe_controlled = 1,
...@@ -82,6 +84,7 @@ static int __init atstk1000_flash_init(void) ...@@ -82,6 +84,7 @@ static int __init atstk1000_flash_init(void)
{ {
int ret; int ret;
smc_set_timing(&flash_config, &flash_timing);
ret = smc_set_configuration(0, &flash_config); ret = smc_set_configuration(0, &flash_config);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n"); printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
......
...@@ -29,16 +29,25 @@ struct hsmc { ...@@ -29,16 +29,25 @@ struct hsmc {
static struct hsmc *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 mul;
unsigned long offset;
u32 setup, pulse, cycle, mode;
if (!hsmc) /* Reset all SMC timings */
return -ENODEV; config->ncs_read_setup = 0;
if (cs >= NR_CHIP_SELECTS) config->nrd_setup = 0;
return -EINVAL; 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 * cycles = x / T = x * f
...@@ -50,16 +59,102 @@ int smc_set_configuration(int cs, const struct smc_config *config) ...@@ -50,16 +59,102 @@ int smc_set_configuration(int cs, const struct smc_config *config)
#define ns2cyc(x) ((((x) * mul) + 65535) >> 16) #define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup)) if (timing->ncs_read_setup > 0)
| HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup)) config->ncs_read_setup = ns2cyc(timing->ncs_read_setup);
| HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))
| HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup))); if (timing->nrd_setup > 0)
pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse)) config->nrd_setup = ns2cyc(timing->nrd_setup);
| HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))
| HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse)) if (timing->ncs_write_setup > 0)
| HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse))); config->ncs_write_setup = ns2cyc(timing->ncs_write_setup);
cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))
| HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle))); 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) { switch (config->bus_width) {
case 1: case 1:
......
...@@ -15,22 +15,50 @@ ...@@ -15,22 +15,50 @@
/* /*
* All timing parameters are in nanoseconds. * 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 { struct smc_config {
/* Delay from address valid to assertion of given strobe */ /* Delay from address valid to assertion of given strobe */
u16 ncs_read_setup; u8 ncs_read_setup;
u16 nrd_setup; u8 nrd_setup;
u16 ncs_write_setup; u8 ncs_write_setup;
u16 nwe_setup; u8 nwe_setup;
/* Pulse length of given strobe */ /* Pulse length of given strobe */
u16 ncs_read_pulse; u8 ncs_read_pulse;
u16 nrd_pulse; u8 nrd_pulse;
u16 ncs_write_pulse; u8 ncs_write_pulse;
u16 nwe_pulse; u8 nwe_pulse;
/* Total cycle length of given operation */ /* Total cycle length of given operation */
u16 read_cycle; u8 read_cycle;
u16 write_cycle; u8 write_cycle;
/* Bus width in bytes */ /* Bus width in bytes */
u8 bus_width; u8 bus_width;
...@@ -76,6 +104,9 @@ struct smc_config { ...@@ -76,6 +104,9 @@ struct smc_config {
unsigned int tdf_mode:1; 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 int smc_set_configuration(int cs, const struct smc_config *config);
extern struct smc_config *smc_get_configuration(int cs); extern struct smc_config *smc_get_configuration(int cs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment