diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/hsmc.c')
| -rw-r--r-- | arch/avr32/mach-at32ap/hsmc.c | 160 |
1 files changed, 139 insertions, 21 deletions
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c index 7691721928a..f66245e6e63 100644 --- a/arch/avr32/mach-at32ap/hsmc.c +++ b/arch/avr32/mach-at32ap/hsmc.c @@ -7,15 +7,15 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define DEBUG #include <linux/clk.h> #include <linux/err.h> #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <asm/io.h> -#include <asm/arch/smc.h> +#include <mach/smc.h> #include "hsmc.h" @@ -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: @@ -75,12 +170,35 @@ int smc_set_configuration(int cs, const struct smc_config *config) return -EINVAL; } + switch (config->nwait_mode) { + case 0: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED); + break; + case 1: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED); + break; + case 2: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN); + break; + case 3: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY); + break; + default: + return -EINVAL; + } + + if (config->tdf_cycles) { + mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles); + } + if (config->nrd_controlled) mode |= HSMC_BIT(READ_MODE); if (config->nwe_controlled) mode |= HSMC_BIT(WRITE_MODE); if (config->byte_write) mode |= HSMC_BIT(BAT); + if (config->tdf_mode) + mode |= HSMC_BIT(TDF_MODE); pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", cs, setup, pulse, cycle, mode); @@ -127,7 +245,7 @@ static int hsmc_probe(struct platform_device *pdev) hsmc->pclk = pclk; hsmc->mck = mck; - hsmc->regs = ioremap(regs->start, regs->end - regs->start + 1); + hsmc->regs = ioremap(regs->start, resource_size(regs)); if (!hsmc->regs) goto out_disable_clocks; @@ -161,4 +279,4 @@ static int __init hsmc_init(void) { return platform_driver_register(&hsmc_driver); } -arch_initcall(hsmc_init); +core_initcall(hsmc_init); |
