forked from Minki/linux
[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>
This commit is contained in:
parent
193fdd1a99
commit
af8184718a
@ -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 = {
|
|||||||
|
|
||||||
.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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
|
|
||||||
#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 = {
|
|||||||
|
|
||||||
.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)
|
|||||||
{
|
{
|
||||||
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 {
|
|||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
unsigned long mul;
|
int recover;
|
||||||
unsigned long offset;
|
int cycle;
|
||||||
u32 setup, pulse, cycle, mode;
|
|
||||||
|
|
||||||
if (!hsmc)
|
unsigned long mul;
|
||||||
return -ENODEV;
|
|
||||||
if (cs >= NR_CHIP_SELECTS)
|
/* Reset all SMC timings */
|
||||||
return -EINVAL;
|
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
|
* 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)
|
#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 @@
|
|||||||
/*
|
/*
|
||||||
* All timing parameters are in nanoseconds.
|
* All timing parameters are in nanoseconds.
|
||||||
*/
|
*/
|
||||||
struct smc_config {
|
struct smc_timing {
|
||||||
/* Delay from address valid to assertion of given strobe */
|
/* Delay from address valid to assertion of given strobe */
|
||||||
u16 ncs_read_setup;
|
int ncs_read_setup;
|
||||||
u16 nrd_setup;
|
int nrd_setup;
|
||||||
u16 ncs_write_setup;
|
int ncs_write_setup;
|
||||||
u16 nwe_setup;
|
int nwe_setup;
|
||||||
|
|
||||||
/* Pulse length of given strobe */
|
/* Pulse length of given strobe */
|
||||||
u16 ncs_read_pulse;
|
int ncs_read_pulse;
|
||||||
u16 nrd_pulse;
|
int nrd_pulse;
|
||||||
u16 ncs_write_pulse;
|
int ncs_write_pulse;
|
||||||
u16 nwe_pulse;
|
int nwe_pulse;
|
||||||
|
|
||||||
/* Total cycle length of given operation */
|
/* Total cycle length of given operation */
|
||||||
u16 read_cycle;
|
int read_cycle;
|
||||||
u16 write_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 */
|
||||||
|
u8 ncs_read_setup;
|
||||||
|
u8 nrd_setup;
|
||||||
|
u8 ncs_write_setup;
|
||||||
|
u8 nwe_setup;
|
||||||
|
|
||||||
|
/* Pulse length of given strobe */
|
||||||
|
u8 ncs_read_pulse;
|
||||||
|
u8 nrd_pulse;
|
||||||
|
u8 ncs_write_pulse;
|
||||||
|
u8 nwe_pulse;
|
||||||
|
|
||||||
|
/* Total cycle length of given operation */
|
||||||
|
u8 read_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 {
|
|||||||
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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user