diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-11-28 10:17:56 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-14 22:02:45 -0400 |
commit | 1f2ca141ec53a9c43ea0852f013907d19c435986 (patch) | |
tree | 40f88c5aa8382c1e0e121b84b875e7c79874173a | |
parent | b2b0f6ffd3f97953044e909ca311d2a580ae8575 (diff) |
memory/atmel-ebi: Fix ns <-> cycles conversions
commit ee194289502a6901cc77dc9a893bf2afd351ac5e upstream.
at91sam9_ebi_get_config() is incorrectly converting timings in clock
cycles into timings in nanoseconds by multiplying the cycle values by
the clk rate instead of the clk period.
at91sam9_ebi_xslate_config() has the same problem for the
tdf_ns -> tdf_cycles conversion.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Reported-by: Chris Leahy <leahycm@gmail.com>
Fixes: 6a4ec4cd0888 ("memory: add Atmel EBI (External Bus Interface) driver")
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/memory/atmel-ebi.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index b5ed3bd082b5..e9ebc4f31d16 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c | |||
@@ -93,7 +93,7 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid, | |||
93 | struct at91_ebi_dev_config *conf) | 93 | struct at91_ebi_dev_config *conf) |
94 | { | 94 | { |
95 | struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; | 95 | struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; |
96 | unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); | 96 | unsigned int clk_period = NSEC_PER_SEC / clk_get_rate(ebid->ebi->clk); |
97 | struct at91sam9_ebi_dev_config *config = &conf->sam9; | 97 | struct at91sam9_ebi_dev_config *config = &conf->sam9; |
98 | struct at91sam9_smc_timings *timings = &config->timings; | 98 | struct at91sam9_smc_timings *timings = &config->timings; |
99 | unsigned int val; | 99 | unsigned int val; |
@@ -102,43 +102,43 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid, | |||
102 | config->mode = val & ~AT91_SMC_TDF; | 102 | config->mode = val & ~AT91_SMC_TDF; |
103 | 103 | ||
104 | val = (val & AT91_SMC_TDF) >> 16; | 104 | val = (val & AT91_SMC_TDF) >> 16; |
105 | timings->tdf_ns = clk_rate * val; | 105 | timings->tdf_ns = clk_period * val; |
106 | 106 | ||
107 | regmap_fields_read(fields->setup, conf->cs, &val); | 107 | regmap_fields_read(fields->setup, conf->cs, &val); |
108 | timings->ncs_rd_setup_ns = (val >> 24) & 0x1f; | 108 | timings->ncs_rd_setup_ns = (val >> 24) & 0x1f; |
109 | timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128; | 109 | timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128; |
110 | timings->ncs_rd_setup_ns *= clk_rate; | 110 | timings->ncs_rd_setup_ns *= clk_period; |
111 | timings->nrd_setup_ns = (val >> 16) & 0x1f; | 111 | timings->nrd_setup_ns = (val >> 16) & 0x1f; |
112 | timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128; | 112 | timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128; |
113 | timings->nrd_setup_ns *= clk_rate; | 113 | timings->nrd_setup_ns *= clk_period; |
114 | timings->ncs_wr_setup_ns = (val >> 8) & 0x1f; | 114 | timings->ncs_wr_setup_ns = (val >> 8) & 0x1f; |
115 | timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128; | 115 | timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128; |
116 | timings->ncs_wr_setup_ns *= clk_rate; | 116 | timings->ncs_wr_setup_ns *= clk_period; |
117 | timings->nwe_setup_ns = val & 0x1f; | 117 | timings->nwe_setup_ns = val & 0x1f; |
118 | timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128; | 118 | timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128; |
119 | timings->nwe_setup_ns *= clk_rate; | 119 | timings->nwe_setup_ns *= clk_period; |
120 | 120 | ||
121 | regmap_fields_read(fields->pulse, conf->cs, &val); | 121 | regmap_fields_read(fields->pulse, conf->cs, &val); |
122 | timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f; | 122 | timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f; |
123 | timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256; | 123 | timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256; |
124 | timings->ncs_rd_pulse_ns *= clk_rate; | 124 | timings->ncs_rd_pulse_ns *= clk_period; |
125 | timings->nrd_pulse_ns = (val >> 16) & 0x3f; | 125 | timings->nrd_pulse_ns = (val >> 16) & 0x3f; |
126 | timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256; | 126 | timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256; |
127 | timings->nrd_pulse_ns *= clk_rate; | 127 | timings->nrd_pulse_ns *= clk_period; |
128 | timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f; | 128 | timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f; |
129 | timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256; | 129 | timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256; |
130 | timings->ncs_wr_pulse_ns *= clk_rate; | 130 | timings->ncs_wr_pulse_ns *= clk_period; |
131 | timings->nwe_pulse_ns = val & 0x3f; | 131 | timings->nwe_pulse_ns = val & 0x3f; |
132 | timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256; | 132 | timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256; |
133 | timings->nwe_pulse_ns *= clk_rate; | 133 | timings->nwe_pulse_ns *= clk_period; |
134 | 134 | ||
135 | regmap_fields_read(fields->cycle, conf->cs, &val); | 135 | regmap_fields_read(fields->cycle, conf->cs, &val); |
136 | timings->nrd_cycle_ns = (val >> 16) & 0x7f; | 136 | timings->nrd_cycle_ns = (val >> 16) & 0x7f; |
137 | timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256; | 137 | timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256; |
138 | timings->nrd_cycle_ns *= clk_rate; | 138 | timings->nrd_cycle_ns *= clk_period; |
139 | timings->nwe_cycle_ns = val & 0x7f; | 139 | timings->nwe_cycle_ns = val & 0x7f; |
140 | timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256; | 140 | timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256; |
141 | timings->nwe_cycle_ns *= clk_rate; | 141 | timings->nwe_cycle_ns *= clk_period; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int at91_xlate_timing(struct device_node *np, const char *prop, | 144 | static int at91_xlate_timing(struct device_node *np, const char *prop, |
@@ -334,6 +334,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid, | |||
334 | struct at91_ebi_dev_config *conf) | 334 | struct at91_ebi_dev_config *conf) |
335 | { | 335 | { |
336 | unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); | 336 | unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); |
337 | unsigned int clk_period = NSEC_PER_SEC / clk_rate; | ||
337 | struct at91sam9_ebi_dev_config *config = &conf->sam9; | 338 | struct at91sam9_ebi_dev_config *config = &conf->sam9; |
338 | struct at91sam9_smc_timings *timings = &config->timings; | 339 | struct at91sam9_smc_timings *timings = &config->timings; |
339 | struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; | 340 | struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; |
@@ -376,7 +377,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid, | |||
376 | val |= AT91SAM9_SMC_NWECYCLE(coded_val); | 377 | val |= AT91SAM9_SMC_NWECYCLE(coded_val); |
377 | regmap_fields_write(fields->cycle, conf->cs, val); | 378 | regmap_fields_write(fields->cycle, conf->cs, val); |
378 | 379 | ||
379 | val = DIV_ROUND_UP(timings->tdf_ns, clk_rate); | 380 | val = DIV_ROUND_UP(timings->tdf_ns, clk_period); |
380 | if (val > AT91_SMC_TDF_MAX) | 381 | if (val > AT91_SMC_TDF_MAX) |
381 | val = AT91_SMC_TDF_MAX; | 382 | val = AT91_SMC_TDF_MAX; |
382 | regmap_fields_write(fields->mode, conf->cs, | 383 | regmap_fields_write(fields->mode, conf->cs, |