aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-06-15 15:00:22 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-06-15 15:00:22 -0400
commit6c987183fcc3c6cb9eb77fd0b3e8ca1ac98a4813 (patch)
tree14176c7fdd1a0892f4bb593d64fd7cd9cac45aa4
parent21bd33a656a60daadc475ce330272f4410ae27b7 (diff)
opti621: program devices timings separately in ->set_pio_mode
* Set drive->drive_data to 'pio + XFER_PIO_0' instead of 'pio', then simplify selecting maximum adress setup timing. * Remove no longer needed compute_pios() and opti621_port_init_devs(). * Program devices timings separately in ->set_pio_mode. Based on a bugreport from Juergen Kosel & inspired by pata_opti.c code. Tested-by: Juergen Kosel <juergen.kosel@gmx.de> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/pci/opti621.c80
1 files changed, 15 insertions, 65 deletions
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 7547fa2d83ac..c746e6f06077 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -115,34 +115,6 @@ static int reg_base;
115 115
116static DEFINE_SPINLOCK(opti621_lock); 116static DEFINE_SPINLOCK(opti621_lock);
117 117
118/* there are stored pio numbers from other calls of opti621_set_pio_mode */
119static void compute_pios(ide_drive_t *drive, const u8 pio)
120/* Store values into drive->drive_data
121 * second_contr - 0 for primary controller, 1 for secondary
122 * slave_drive - 0 -> pio is for master, 1 -> pio is for slave
123 * pio - PIO mode for selected drive (for other we don't know)
124 */
125{
126 int d;
127 ide_hwif_t *hwif = HWIF(drive);
128
129 drive->drive_data = pio;
130
131 for (d = 0; d < 2; ++d) {
132 drive = &hwif->drives[d];
133 if (drive->present) {
134 if (drive->drive_data == PIO_DONT_KNOW)
135 drive->drive_data = ide_get_best_pio_mode(drive, 255, 3);
136#ifdef OPTI621_DEBUG
137 printk("%s: Selected PIO mode %d\n",
138 drive->name, drive->drive_data);
139#endif
140 } else {
141 drive->drive_data = PIO_NOT_EXIST;
142 }
143 }
144}
145
146static int cmpt_clk(int time, int bus_speed) 118static int cmpt_clk(int time, int bus_speed)
147/* Returns (rounded up) time in clocks for time in ns, 119/* Returns (rounded up) time in clocks for time in ns,
148 * with bus_speed in MHz. 120 * with bus_speed in MHz.
@@ -226,20 +198,19 @@ static void compute_clocks(int pio, pio_clocks_t *clks, int bus_speed)
226 198
227static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) 199static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
228{ 200{
229 /* primary and secondary drives share some registers, 201 ide_hwif_t *hwif = drive->hwif;
230 * so we have to program both drives 202 ide_drive_t *pair = ide_get_paired_drive(drive);
231 */
232 unsigned long flags; 203 unsigned long flags;
233 u8 pio1 = 0, pio2 = 0;
234 pio_clocks_t first, second; 204 pio_clocks_t first, second;
235 int ax, drdy; 205 int ax, drdy;
236 u8 cycle1, cycle2, misc, clk; 206 u8 cycle1, misc, clk, addr_pio = pio;
237 ide_hwif_t *hwif = HWIF(drive);
238 207
239 /* sets drive->drive_data for both drives */ 208 drive->drive_data = XFER_PIO_0 + pio;
240 compute_pios(drive, pio); 209
241 pio1 = hwif->drives[0].drive_data; 210 if (pair->present) {
242 pio2 = hwif->drives[1].drive_data; 211 if (pair->drive_data && pair->drive_data < drive->drive_data)
212 addr_pio = pair->drive_data - XFER_PIO_0;
213 }
243 214
244 spin_lock_irqsave(&opti621_lock, flags); 215 spin_lock_irqsave(&opti621_lock, flags);
245 216
@@ -259,8 +230,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
259 230
260 printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); 231 printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);
261 232
262 compute_clocks(pio1, &first, clk ? 25 : 33); 233 compute_clocks(pio, &first, clk ? 25 : 33);
263 compute_clocks(pio2, &second, clk ? 25 : 33); 234 compute_clocks(addr_pio, &second, clk ? 25 : 33);
264 235
265 /* ax = max(a1,a2) */ 236 /* ax = max(a1,a2) */
266 ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; 237 ax = (first.address_time < second.address_time) ? second.address_time : first.address_time;
@@ -268,37 +239,23 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
268 drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ 239 drdy = 2; /* DRDY is default 2 (by OPTi Databook) */
269 240
270 cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); 241 cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2);
271 cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2);
272 242
273 misc = ((ax - 1) << 4) | ((drdy - 2) << 1); 243 misc = ((ax - 1) << 4) | ((drdy - 2) << 1);
274 244
275#ifdef OPTI621_DEBUG 245#ifdef OPTI621_DEBUG
276 printk("%s: master: address: %d, data: %d, " 246 printk("%s: address: %d, data: %d, "
277 "recovery: %d, drdy: %d [clk]\n", 247 "recovery: %d, drdy: %d [clk]\n",
278 hwif->name, ax, first.data_time, 248 drive->name, ax, first.data_time,
279 first.recovery_time, drdy); 249 first.recovery_time, drdy);
280 printk("%s: slave: address: %d, data: %d, "
281 "recovery: %d, drdy: %d [clk]\n",
282 hwif->name, ax, second.data_time,
283 second.recovery_time, drdy);
284#endif 250#endif
285 251
286 /* program primary drive */ 252 /* select Index-0/1 for Register-A/B */
287 /* select Index-0 for Register-A */ 253 write_reg(drive->select.b.unit, MISC_REG);
288 write_reg(0, MISC_REG);
289 /* set read cycle timings */ 254 /* set read cycle timings */
290 write_reg(cycle1, READ_REG); 255 write_reg(cycle1, READ_REG);
291 /* set write cycle timings */ 256 /* set write cycle timings */
292 write_reg(cycle1, WRITE_REG); 257 write_reg(cycle1, WRITE_REG);
293 258
294 /* program secondary drive */
295 /* select Index-1 for Register-B */
296 write_reg(1, MISC_REG);
297 /* set read cycle timings */
298 write_reg(cycle2, READ_REG);
299 /* set write cycle timings */
300 write_reg(cycle2, WRITE_REG);
301
302 /* use Register-A for drive 0 */ 259 /* use Register-A for drive 0 */
303 /* use Register-B for drive 1 */ 260 /* use Register-B for drive 1 */
304 write_reg(0x85, CNTRL_REG); 261 write_reg(0x85, CNTRL_REG);
@@ -310,14 +267,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
310 spin_unlock_irqrestore(&opti621_lock, flags); 267 spin_unlock_irqrestore(&opti621_lock, flags);
311} 268}
312 269
313static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
314{
315 hwif->drives[0].drive_data = PIO_DONT_KNOW;
316 hwif->drives[1].drive_data = PIO_DONT_KNOW;
317}
318
319static const struct ide_port_ops opti621_port_ops = { 270static const struct ide_port_ops opti621_port_ops = {
320 .port_init_devs = opti621_port_init_devs,
321 .set_pio_mode = opti621_set_pio_mode, 271 .set_pio_mode = opti621_set_pio_mode,
322}; 272};
323 273