mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 00:21:32 +00:00
[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>
|
||||
|
||||
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");
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
{
|
||||
unsigned long mul;
|
||||
unsigned long offset;
|
||||
u32 setup, pulse, cycle, mode;
|
||||
int recover;
|
||||
int cycle;
|
||||
|
||||
if (!hsmc)
|
||||
return -ENODEV;
|
||||
if (cs >= NR_CHIP_SELECTS)
|
||||
return -EINVAL;
|
||||
unsigned long mul;
|
||||
|
||||
/* 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:
|
||||
|
@ -15,22 +15,50 @@
|
||||
/*
|
||||
* All timing parameters are in nanoseconds.
|
||||
*/
|
||||
struct smc_config {
|
||||
struct smc_timing {
|
||||
/* Delay from address valid to assertion of given strobe */
|
||||
u16 ncs_read_setup;
|
||||
u16 nrd_setup;
|
||||
u16 ncs_write_setup;
|
||||
u16 nwe_setup;
|
||||
int ncs_read_setup;
|
||||
int nrd_setup;
|
||||
int ncs_write_setup;
|
||||
int nwe_setup;
|
||||
|
||||
/* Pulse length of given strobe */
|
||||
u16 ncs_read_pulse;
|
||||
u16 nrd_pulse;
|
||||
u16 ncs_write_pulse;
|
||||
u16 nwe_pulse;
|
||||
int ncs_read_pulse;
|
||||
int nrd_pulse;
|
||||
int ncs_write_pulse;
|
||||
int nwe_pulse;
|
||||
|
||||
/* Total cycle length of given operation */
|
||||
u16 read_cycle;
|
||||
u16 write_cycle;
|
||||
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 */
|
||||
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 */
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user