diff options
author | Igor Plyatov <plyatov@gmail.com> | 2011-05-12 14:15:51 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2011-05-14 15:00:13 -0400 |
commit | 0144261fa677e9490eb112231de30c95af1679d2 (patch) | |
tree | a73a2ff3e3c6a2d00ff634b893de6b8448215010 /drivers/ata/pata_at91.c | |
parent | af649a1b56032a84b75825a94204a8f8f0120698 (diff) |
pata_at91: SMC settings calculation bugfixes, support for t6z and IORDY
* New code correctly calculates SMC registers values, adjusts calculated
to admissible ranges, enlarges cycles when required and converts values
into SMC's format.
* Support for TDF cycles (ATA t6z) and IORDY line added.
* Eliminate need in the initial_timing structure.
* Code cleanup.
Signed-off-by: Igor Plyatov <plyatov@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/ata/pata_at91.c')
-rw-r--r-- | drivers/ata/pata_at91.c | 297 |
1 files changed, 198 insertions, 99 deletions
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index a5fdbdcb0faf..960c72571395 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * with CompactFlash interface in True IDE mode | 3 | * with CompactFlash interface in True IDE mode |
4 | * | 4 | * |
5 | * Copyright (C) 2009 Matyukevich Sergey | 5 | * Copyright (C) 2009 Matyukevich Sergey |
6 | * 2011 Igor Plyatov | ||
6 | * | 7 | * |
7 | * Based on: | 8 | * Based on: |
8 | * * generic platform driver by Paul Mundt: drivers/ata/pata_platform.c | 9 | * * generic platform driver by Paul Mundt: drivers/ata/pata_platform.c |
@@ -31,38 +32,150 @@ | |||
31 | #include <mach/board.h> | 32 | #include <mach/board.h> |
32 | #include <mach/gpio.h> | 33 | #include <mach/gpio.h> |
33 | 34 | ||
35 | #define DRV_NAME "pata_at91" | ||
36 | #define DRV_VERSION "0.3" | ||
34 | 37 | ||
35 | #define DRV_NAME "pata_at91" | 38 | #define CF_IDE_OFFSET 0x00c00000 |
36 | #define DRV_VERSION "0.2" | 39 | #define CF_ALT_IDE_OFFSET 0x00e00000 |
37 | 40 | #define CF_IDE_RES_SIZE 0x08 | |
38 | #define CF_IDE_OFFSET 0x00c00000 | 41 | #define CS_PULSE_MAXIMUM 319 |
39 | #define CF_ALT_IDE_OFFSET 0x00e00000 | 42 | #define ER_SMC_CALC 1 |
40 | #define CF_IDE_RES_SIZE 0x08 | 43 | #define ER_SMC_RECALC 2 |
41 | #define NCS_RD_PULSE_LIMIT 0x3f /* maximal value for pulse bitfields */ | ||
42 | 44 | ||
43 | struct at91_ide_info { | 45 | struct at91_ide_info { |
44 | unsigned long mode; | 46 | unsigned long mode; |
45 | unsigned int cs; | 47 | unsigned int cs; |
46 | |||
47 | struct clk *mck; | 48 | struct clk *mck; |
48 | |||
49 | void __iomem *ide_addr; | 49 | void __iomem *ide_addr; |
50 | void __iomem *alt_addr; | 50 | void __iomem *alt_addr; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static const struct ata_timing initial_timing = { | 53 | /** |
54 | .mode = XFER_PIO_0, | 54 | * struct smc_range - range of valid values for SMC register. |
55 | .setup = 70, | 55 | */ |
56 | .act8b = 290, | 56 | struct smc_range { |
57 | .rec8b = 240, | 57 | int min; |
58 | .cyc8b = 600, | 58 | int max; |
59 | .active = 165, | ||
60 | .recover = 150, | ||
61 | .dmack_hold = 0, | ||
62 | .cycle = 600, | ||
63 | .udma = 0 | ||
64 | }; | 59 | }; |
65 | 60 | ||
61 | /** | ||
62 | * adjust_smc_value - adjust value for one of SMC registers. | ||
63 | * @value: adjusted value | ||
64 | * @range: array of SMC ranges with valid values | ||
65 | * @size: SMC ranges array size | ||
66 | * | ||
67 | * This returns the difference between input and output value or negative | ||
68 | * in case of invalid input value. | ||
69 | * If negative returned, then output value = maximal possible from ranges. | ||
70 | */ | ||
71 | static int adjust_smc_value(int *value, struct smc_range *range, int size) | ||
72 | { | ||
73 | int maximum = (range + size - 1)->max; | ||
74 | int remainder; | ||
75 | |||
76 | do { | ||
77 | if (*value < range->min) { | ||
78 | remainder = range->min - *value; | ||
79 | *value = range->min; /* nearest valid value */ | ||
80 | return remainder; | ||
81 | } else if ((range->min <= *value) && (*value <= range->max)) | ||
82 | return 0; | ||
83 | |||
84 | range++; | ||
85 | } while (--size); | ||
86 | *value = maximum; | ||
87 | |||
88 | return -1; /* invalid value */ | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * calc_smc_vals - calculate SMC register values | ||
93 | * @dev: ATA device | ||
94 | * @setup: SMC_SETUP register value | ||
95 | * @pulse: SMC_PULSE register value | ||
96 | * @cycle: SMC_CYCLE register value | ||
97 | * | ||
98 | * This returns negative in case of invalid values for SMC registers: | ||
99 | * -ER_SMC_RECALC - recalculation required for SMC values, | ||
100 | * -ER_SMC_CALC - calculation failed (invalid input values). | ||
101 | * | ||
102 | * SMC use special coding scheme, see "Coding and Range of Timing | ||
103 | * Parameters" table from AT91SAM9 datasheets. | ||
104 | * | ||
105 | * SMC_SETUP = 128*setup[5] + setup[4:0] | ||
106 | * SMC_PULSE = 256*pulse[6] + pulse[5:0] | ||
107 | * SMC_CYCLE = 256*cycle[8:7] + cycle[6:0] | ||
108 | */ | ||
109 | static int calc_smc_vals(struct device *dev, | ||
110 | int *setup, int *pulse, int *cycle, int *cs_pulse) | ||
111 | { | ||
112 | int ret_val; | ||
113 | int err = 0; | ||
114 | struct smc_range range_setup[] = { /* SMC_SETUP valid values */ | ||
115 | {.min = 0, .max = 31}, /* first range */ | ||
116 | {.min = 128, .max = 159} /* second range */ | ||
117 | }; | ||
118 | struct smc_range range_pulse[] = { /* SMC_PULSE valid values */ | ||
119 | {.min = 0, .max = 63}, /* first range */ | ||
120 | {.min = 256, .max = 319} /* second range */ | ||
121 | }; | ||
122 | struct smc_range range_cycle[] = { /* SMC_CYCLE valid values */ | ||
123 | {.min = 0, .max = 127}, /* first range */ | ||
124 | {.min = 256, .max = 383}, /* second range */ | ||
125 | {.min = 512, .max = 639}, /* third range */ | ||
126 | {.min = 768, .max = 895} /* fourth range */ | ||
127 | }; | ||
128 | |||
129 | ret_val = adjust_smc_value(setup, range_setup, ARRAY_SIZE(range_setup)); | ||
130 | if (ret_val < 0) | ||
131 | dev_warn(dev, "maximal SMC Setup value\n"); | ||
132 | else | ||
133 | *cycle += ret_val; | ||
134 | |||
135 | ret_val = adjust_smc_value(pulse, range_pulse, ARRAY_SIZE(range_pulse)); | ||
136 | if (ret_val < 0) | ||
137 | dev_warn(dev, "maximal SMC Pulse value\n"); | ||
138 | else | ||
139 | *cycle += ret_val; | ||
140 | |||
141 | ret_val = adjust_smc_value(cycle, range_cycle, ARRAY_SIZE(range_cycle)); | ||
142 | if (ret_val < 0) | ||
143 | dev_warn(dev, "maximal SMC Cycle value\n"); | ||
144 | |||
145 | *cs_pulse = *cycle; | ||
146 | if (*cs_pulse > CS_PULSE_MAXIMUM) { | ||
147 | dev_err(dev, "unable to calculate valid SMC settings\n"); | ||
148 | return -ER_SMC_CALC; | ||
149 | } | ||
150 | |||
151 | ret_val = adjust_smc_value(cs_pulse, range_pulse, | ||
152 | ARRAY_SIZE(range_pulse)); | ||
153 | if (ret_val < 0) { | ||
154 | dev_warn(dev, "maximal SMC CS Pulse value\n"); | ||
155 | } else if (ret_val != 0) { | ||
156 | *cycle = *cs_pulse; | ||
157 | dev_warn(dev, "SMC Cycle extended\n"); | ||
158 | err = -ER_SMC_RECALC; | ||
159 | } | ||
160 | |||
161 | return err; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * to_smc_format - convert values into SMC format | ||
166 | * @setup: SETUP value of SMC Setup Register | ||
167 | * @pulse: PULSE value of SMC Pulse Register | ||
168 | * @cycle: CYCLE value of SMC Cycle Register | ||
169 | * @cs_pulse: NCS_PULSE value of SMC Pulse Register | ||
170 | */ | ||
171 | static void to_smc_format(int *setup, int *pulse, int *cycle, int *cs_pulse) | ||
172 | { | ||
173 | *setup = (*setup & 0x1f) | ((*setup & 0x80) >> 2); | ||
174 | *pulse = (*pulse & 0x3f) | ((*pulse & 0x100) >> 2); | ||
175 | *cycle = (*cycle & 0x7f) | ((*cycle & 0x300) >> 1); | ||
176 | *cs_pulse = (*cs_pulse & 0x3f) | ((*cs_pulse & 0x100) >> 2); | ||
177 | } | ||
178 | |||
66 | static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz) | 179 | static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz) |
67 | { | 180 | { |
68 | unsigned long mul; | 181 | unsigned long mul; |
@@ -80,85 +193,77 @@ static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz) | |||
80 | return (ns * mul + 65536) >> 16; /* rounding */ | 193 | return (ns * mul + 65536) >> 16; /* rounding */ |
81 | } | 194 | } |
82 | 195 | ||
83 | static void set_smc_mode(struct at91_ide_info *info) | 196 | /** |
84 | { | 197 | * set_smc_timing - SMC timings setup. |
85 | at91_sys_write(AT91_SMC_MODE(info->cs), info->mode); | 198 | * @dev: device |
86 | return; | 199 | * @info: AT91 IDE info |
87 | } | 200 | * @ata: ATA timings |
88 | 201 | * | |
89 | static void set_smc_timing(struct device *dev, | 202 | * Its assumed that write timings are same as read timings, |
203 | * cs_setup = 0 and cs_pulse = cycle. | ||
204 | */ | ||
205 | static void set_smc_timing(struct device *dev, struct ata_device *adev, | ||
90 | struct at91_ide_info *info, const struct ata_timing *ata) | 206 | struct at91_ide_info *info, const struct ata_timing *ata) |
91 | { | 207 | { |
92 | unsigned long read_cycle, write_cycle, active, recover; | 208 | int ret = 0; |
93 | unsigned long nrd_setup, nrd_pulse, nrd_recover; | 209 | int use_iordy; |
94 | unsigned long nwe_setup, nwe_pulse; | 210 | unsigned int t6z; /* data tristate time in ns */ |
95 | 211 | unsigned int cycle; /* SMC Cycle width in MCK ticks */ | |
96 | unsigned long ncs_write_setup, ncs_write_pulse; | 212 | unsigned int setup; /* SMC Setup width in MCK ticks */ |
97 | unsigned long ncs_read_setup, ncs_read_pulse; | 213 | unsigned int pulse; /* CFIOR and CFIOW pulse width in MCK ticks */ |
98 | 214 | unsigned int cs_setup = 0;/* CS4 or CS5 setup width in MCK ticks */ | |
99 | unsigned long mck_hz; | 215 | unsigned int cs_pulse; /* CS4 or CS5 pulse width in MCK ticks*/ |
100 | 216 | unsigned int tdf_cycles; /* SMC TDF MCK ticks */ | |
101 | read_cycle = ata->cyc8b; | 217 | unsigned long mck_hz; /* MCK frequency in Hz */ |
102 | nrd_setup = ata->setup; | 218 | |
103 | nrd_pulse = ata->act8b; | 219 | t6z = (ata->mode < XFER_PIO_5) ? 30 : 20; |
104 | nrd_recover = ata->rec8b; | ||
105 | |||
106 | mck_hz = clk_get_rate(info->mck); | 220 | mck_hz = clk_get_rate(info->mck); |
107 | 221 | cycle = calc_mck_cycles(ata->cyc8b, mck_hz); | |
108 | read_cycle = calc_mck_cycles(read_cycle, mck_hz); | 222 | setup = calc_mck_cycles(ata->setup, mck_hz); |
109 | nrd_setup = calc_mck_cycles(nrd_setup, mck_hz); | 223 | pulse = calc_mck_cycles(ata->act8b, mck_hz); |
110 | nrd_pulse = calc_mck_cycles(nrd_pulse, mck_hz); | 224 | tdf_cycles = calc_mck_cycles(t6z, mck_hz); |
111 | nrd_recover = calc_mck_cycles(nrd_recover, mck_hz); | 225 | |
112 | 226 | do { | |
113 | active = nrd_setup + nrd_pulse; | 227 | ret = calc_smc_vals(dev, &setup, &pulse, &cycle, &cs_pulse); |
114 | recover = read_cycle - active; | 228 | } while (ret == -ER_SMC_RECALC); |
115 | 229 | ||
116 | /* Need at least two cycles recovery */ | 230 | if (ret == -ER_SMC_CALC) |
117 | if (recover < 2) | 231 | dev_err(dev, "Interface may not operate correctly\n"); |
118 | read_cycle = active + 2; | 232 | |
119 | 233 | dev_dbg(dev, "SMC Setup=%u, Pulse=%u, Cycle=%u, CS Pulse=%u\n", | |
120 | /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */ | 234 | setup, pulse, cycle, cs_pulse); |
121 | ncs_read_setup = 1; | 235 | to_smc_format(&setup, &pulse, &cycle, &cs_pulse); |
122 | ncs_read_pulse = read_cycle - 2; | 236 | /* disable or enable waiting for IORDY signal */ |
123 | if (ncs_read_pulse > NCS_RD_PULSE_LIMIT) { | 237 | use_iordy = ata_pio_need_iordy(adev); |
124 | ncs_read_pulse = NCS_RD_PULSE_LIMIT; | 238 | if (use_iordy) |
125 | dev_warn(dev, "ncs_read_pulse limited to maximal value %lu\n", | 239 | info->mode |= AT91_SMC_EXNWMODE_READY; |
126 | ncs_read_pulse); | 240 | |
241 | if (tdf_cycles > 15) { | ||
242 | tdf_cycles = 15; | ||
243 | dev_warn(dev, "maximal SMC TDF Cycles value\n"); | ||
127 | } | 244 | } |
128 | 245 | ||
129 | /* Write timings same as read timings */ | 246 | dev_dbg(dev, "Use IORDY=%u, TDF Cycles=%u\n", use_iordy, tdf_cycles); |
130 | write_cycle = read_cycle; | 247 | info->mode |= AT91_SMC_TDF_(tdf_cycles); |
131 | nwe_setup = nrd_setup; | ||
132 | nwe_pulse = nrd_pulse; | ||
133 | ncs_write_setup = ncs_read_setup; | ||
134 | ncs_write_pulse = ncs_read_pulse; | ||
135 | |||
136 | dev_dbg(dev, "ATA timings: nrd_setup = %lu nrd_pulse = %lu nrd_cycle = %lu\n", | ||
137 | nrd_setup, nrd_pulse, read_cycle); | ||
138 | dev_dbg(dev, "ATA timings: nwe_setup = %lu nwe_pulse = %lu nwe_cycle = %lu\n", | ||
139 | nwe_setup, nwe_pulse, write_cycle); | ||
140 | dev_dbg(dev, "ATA timings: ncs_read_setup = %lu ncs_read_pulse = %lu\n", | ||
141 | ncs_read_setup, ncs_read_pulse); | ||
142 | dev_dbg(dev, "ATA timings: ncs_write_setup = %lu ncs_write_pulse = %lu\n", | ||
143 | ncs_write_setup, ncs_write_pulse); | ||
144 | 248 | ||
249 | /* write SMC Setup Register */ | ||
145 | at91_sys_write(AT91_SMC_SETUP(info->cs), | 250 | at91_sys_write(AT91_SMC_SETUP(info->cs), |
146 | AT91_SMC_NWESETUP_(nwe_setup) | | 251 | AT91_SMC_NWESETUP_(setup) | |
147 | AT91_SMC_NRDSETUP_(nrd_setup) | | 252 | AT91_SMC_NRDSETUP_(setup) | |
148 | AT91_SMC_NCS_WRSETUP_(ncs_write_setup) | | 253 | AT91_SMC_NCS_WRSETUP_(cs_setup) | |
149 | AT91_SMC_NCS_RDSETUP_(ncs_read_setup)); | 254 | AT91_SMC_NCS_RDSETUP_(cs_setup)); |
150 | 255 | /* write SMC Pulse Register */ | |
151 | at91_sys_write(AT91_SMC_PULSE(info->cs), | 256 | at91_sys_write(AT91_SMC_PULSE(info->cs), |
152 | AT91_SMC_NWEPULSE_(nwe_pulse) | | 257 | AT91_SMC_NWEPULSE_(pulse) | |
153 | AT91_SMC_NRDPULSE_(nrd_pulse) | | 258 | AT91_SMC_NRDPULSE_(pulse) | |
154 | AT91_SMC_NCS_WRPULSE_(ncs_write_pulse) | | 259 | AT91_SMC_NCS_WRPULSE_(cs_pulse) | |
155 | AT91_SMC_NCS_RDPULSE_(ncs_read_pulse)); | 260 | AT91_SMC_NCS_RDPULSE_(cs_pulse)); |
156 | 261 | /* write SMC Cycle Register */ | |
157 | at91_sys_write(AT91_SMC_CYCLE(info->cs), | 262 | at91_sys_write(AT91_SMC_CYCLE(info->cs), |
158 | AT91_SMC_NWECYCLE_(write_cycle) | | 263 | AT91_SMC_NWECYCLE_(cycle) | |
159 | AT91_SMC_NRDCYCLE_(read_cycle)); | 264 | AT91_SMC_NRDCYCLE_(cycle)); |
160 | 265 | /* write SMC Mode Register*/ | |
161 | return; | 266 | at91_sys_write(AT91_SMC_MODE(info->cs), info->mode); |
162 | } | 267 | } |
163 | 268 | ||
164 | static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev) | 269 | static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev) |
@@ -172,15 +277,9 @@ static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
172 | if (ret) { | 277 | if (ret) { |
173 | dev_warn(ap->dev, "Failed to compute ATA timing %d, " | 278 | dev_warn(ap->dev, "Failed to compute ATA timing %d, " |
174 | "set PIO_0 timing\n", ret); | 279 | "set PIO_0 timing\n", ret); |
175 | set_smc_timing(ap->dev, info, &initial_timing); | 280 | timing = *ata_timing_find_mode(XFER_PIO_0); |
176 | } else { | ||
177 | set_smc_timing(ap->dev, info, &timing); | ||
178 | } | 281 | } |
179 | 282 | set_smc_timing(ap->dev, adev, info, &timing); | |
180 | /* Setup SMC mode */ | ||
181 | set_smc_mode(info); | ||
182 | |||
183 | return; | ||
184 | } | 283 | } |
185 | 284 | ||
186 | static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev, | 285 | static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev, |
@@ -346,7 +445,7 @@ static int __devexit pata_at91_remove(struct platform_device *pdev) | |||
346 | static struct platform_driver pata_at91_driver = { | 445 | static struct platform_driver pata_at91_driver = { |
347 | .probe = pata_at91_probe, | 446 | .probe = pata_at91_probe, |
348 | .remove = __devexit_p(pata_at91_remove), | 447 | .remove = __devexit_p(pata_at91_remove), |
349 | .driver = { | 448 | .driver = { |
350 | .name = DRV_NAME, | 449 | .name = DRV_NAME, |
351 | .owner = THIS_MODULE, | 450 | .owner = THIS_MODULE, |
352 | }, | 451 | }, |