aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-07-19 19:11:54 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-07-19 19:11:54 -0400
commit328dcbb63657ebbb2dd26982fa9e1fa9e04b6fa2 (patch)
tree902daf365cd6e8ecf559dbc98419140a9d3b6b8f /drivers
parent485efc6cf507eae2b8e83b56e179c8fa3980641a (diff)
siimage: PIO mode setup fixes (take 2)
* Add sil_tuneproc() wrapper for siimage_tuneproc() which also sets PIO mode on the device. * Add missing ide_get_best_pio_mode() call to sil_tuneproc() so "pio" == 255 (autotune) is handled correctly (previously PIO0 was used) and "pio" values > 4 && < 255 are filtered to PIO4 (instead of PIO0). * Add code limiting maximum PIO mode according to the pair device capabilities to sil_tuneproc(). * Convert users of config_siimage_chipset_for_pio() to use sil_tune_pio() and sil_tuneproc(). This fixes PIO fallback in siimage_config_drive_for_dma() to use max PIO mode available instead of PIO4 (config_siimage_chipset_for_pio() used wrong arguments for ide_get_best_pio_mode() and as a results always tried to set PIO4). * Remove no longer needed siimage_taskfile_timing() and config_siimage_chipset_for_pio(). * Enable ->autotune unconditionally and remove PIO tuning for UDMA/MDMA modes from siimage_speedproc() * Bump driver version. v2: * Fix issues noticed by Sergei: - correct pair device check - trim only taskfile PIO to the slowest of the master/slave - enable ->autotune unconditionally and remove PIO tuning for UDMA/MDMA modes from siimage_speedproc() - add TODO item for IORDY bugs - minor cleanups Reviewed-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/pci/siimage.c137
1 files changed, 39 insertions, 98 deletions
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 1c3e35487893..5304fc5c616a 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,9 +1,10 @@
1/* 1/*
2 * linux/drivers/ide/pci/siimage.c Version 1.12 Mar 10 2007 2 * linux/drivers/ide/pci/siimage.c Version 1.15 Jun 29 2007
3 * 3 *
4 * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> 4 * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
5 * Copyright (C) 2003 Red Hat <alan@redhat.com> 5 * Copyright (C) 2003 Red Hat <alan@redhat.com>
6 * Copyright (C) 2007 MontaVista Software, Inc. 6 * Copyright (C) 2007 MontaVista Software, Inc.
7 * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
7 * 8 *
8 * May be copied or modified under the terms of the GNU General Public License 9 * May be copied or modified under the terms of the GNU General Public License
9 * 10 *
@@ -31,6 +32,10 @@
31 * unplugging/replugging the virtual CD interface when the DRAC is reset. 32 * unplugging/replugging the virtual CD interface when the DRAC is reset.
32 * This often causes drivers/ide/siimage to panic but is ok with the rather 33 * This often causes drivers/ide/siimage to panic but is ok with the rather
33 * smarter code in libata. 34 * smarter code in libata.
35 *
36 * TODO:
37 * - IORDY fixes
38 * - VDMA support
34 */ 39 */
35 40
36#include <linux/types.h> 41#include <linux/types.h>
@@ -160,82 +165,45 @@ out:
160} 165}
161 166
162/** 167/**
163 * siimage_taskfile_timing - turn timing data to a mode 168 * sil_tune_pio - tune a drive
164 * @hwif: interface to query
165 *
166 * Read the timing data for the interface and return the
167 * mode that is being used.
168 */
169
170static byte siimage_taskfile_timing (ide_hwif_t *hwif)
171{
172 u16 timing = 0x328a;
173 unsigned long addr = siimage_selreg(hwif, 2);
174
175 if (hwif->mmio)
176 timing = hwif->INW(addr);
177 else
178 pci_read_config_word(hwif->pci_dev, addr, &timing);
179
180 switch (timing) {
181 case 0x10c1: return 4;
182 case 0x10c3: return 3;
183 case 0x1104:
184 case 0x1281: return 2;
185 case 0x2283: return 1;
186 case 0x328a:
187 default: return 0;
188 }
189}
190
191/**
192 * simmage_tuneproc - tune a drive
193 * @drive: drive to tune 169 * @drive: drive to tune
194 * @mode_wanted: the target operating mode 170 * @pio: the desired PIO mode
195 * 171 *
196 * Load the timing settings for this device mode into the 172 * Load the timing settings for this device mode into the
197 * controller. If we are in PIO mode 3 or 4 turn on IORDY 173 * controller. If we are in PIO mode 3 or 4 turn on IORDY
198 * monitoring (bit 9). The TF timing is bits 31:16 174 * monitoring (bit 9). The TF timing is bits 31:16
199 */ 175 */
200 176
201static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) 177static void sil_tune_pio(ide_drive_t *drive, u8 pio)
202{ 178{
179 const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
180 const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
181
203 ide_hwif_t *hwif = HWIF(drive); 182 ide_hwif_t *hwif = HWIF(drive);
183 ide_drive_t *pair = &hwif->drives[drive->dn ^ 1];
204 u32 speedt = 0; 184 u32 speedt = 0;
205 u16 speedp = 0; 185 u16 speedp = 0;
206 unsigned long addr = siimage_seldev(drive, 0x04); 186 unsigned long addr = siimage_seldev(drive, 0x04);
207 unsigned long tfaddr = siimage_selreg(hwif, 0x02); 187 unsigned long tfaddr = siimage_selreg(hwif, 0x02);
208 188 u8 tf_pio = pio;
209 /* cheat for now and use the docs */ 189
210 switch (mode_wanted) { 190 /* trim *taskfile* PIO to the slowest of the master/slave */
211 case 4: 191 if (pair->present) {
212 speedp = 0x10c1; 192 u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL);
213 speedt = 0x10c1; 193
214 break; 194 if (pair_pio < tf_pio)
215 case 3: 195 tf_pio = pair_pio;
216 speedp = 0x10c3;
217 speedt = 0x10c3;
218 break;
219 case 2:
220 speedp = 0x1104;
221 speedt = 0x1281;
222 break;
223 case 1:
224 speedp = 0x2283;
225 speedt = 0x2283;
226 break;
227 case 0:
228 default:
229 speedp = 0x328a;
230 speedt = 0x328a;
231 break;
232 } 196 }
233 197
198 /* cheat for now and use the docs */
199 speedp = data_speed[pio];
200 speedt = tf_speed[tf_pio];
201
234 if (hwif->mmio) { 202 if (hwif->mmio) {
235 hwif->OUTW(speedp, addr); 203 hwif->OUTW(speedp, addr);
236 hwif->OUTW(speedt, tfaddr); 204 hwif->OUTW(speedt, tfaddr);
237 /* Now set up IORDY */ 205 /* Now set up IORDY */
238 if(mode_wanted == 3 || mode_wanted == 4) 206 if (pio > 2)
239 hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); 207 hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
240 else 208 else
241 hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); 209 hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
@@ -245,42 +213,17 @@ static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted)
245 pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); 213 pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
246 speedp &= ~0x200; 214 speedp &= ~0x200;
247 /* Set IORDY for mode 3 or 4 */ 215 /* Set IORDY for mode 3 or 4 */
248 if(mode_wanted == 3 || mode_wanted == 4) 216 if (pio > 2)
249 speedp |= 0x200; 217 speedp |= 0x200;
250 pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); 218 pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp);
251 } 219 }
252} 220}
253 221
254/** 222static void sil_tuneproc(ide_drive_t *drive, u8 pio)
255 * config_siimage_chipset_for_pio - set drive timings
256 * @drive: drive to tune
257 * @speed we want
258 *
259 * Compute the best pio mode we can for a given device. Also honour
260 * the timings for the driver when dealing with mixed devices. Some
261 * of this is ugly but its all wrapped up here
262 *
263 * The SI680 can also do VDMA - we need to start using that
264 *
265 * FIXME: we use the BIOS channel timings to avoid driving the task
266 * files too fast at the disk. We need to compute the master/slave
267 * drive PIO mode properly so that we can up the speed on a hotplug
268 * system.
269 */
270
271static void config_siimage_chipset_for_pio (ide_drive_t *drive, byte set_speed)
272{ 223{
273 u8 channel_timings = siimage_taskfile_timing(HWIF(drive)); 224 pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
274 u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); 225 sil_tune_pio(drive, pio);
275 226 (void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
276 /* WARNING PIO timing mess is going to happen b/w devices, argh */
277 if ((channel_timings != set_pio) && (set_pio > channel_timings))
278 set_pio = channel_timings;
279
280 siimage_tuneproc(drive, set_pio);
281 speed = XFER_PIO_0 + set_pio;
282 if (set_speed)
283 (void) ide_config_drive_speed(drive, speed);
284} 227}
285 228
286/** 229/**
@@ -335,7 +278,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
335 case XFER_PIO_2: 278 case XFER_PIO_2:
336 case XFER_PIO_1: 279 case XFER_PIO_1:
337 case XFER_PIO_0: 280 case XFER_PIO_0:
338 siimage_tuneproc(drive, (speed - XFER_PIO_0)); 281 sil_tune_pio(drive, speed - XFER_PIO_0);
339 mode |= ((unit) ? 0x10 : 0x01); 282 mode |= ((unit) ? 0x10 : 0x01);
340 break; 283 break;
341 case XFER_MW_DMA_2: 284 case XFER_MW_DMA_2:
@@ -343,7 +286,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
343 case XFER_MW_DMA_0: 286 case XFER_MW_DMA_0:
344 multi = dma[speed - XFER_MW_DMA_0]; 287 multi = dma[speed - XFER_MW_DMA_0];
345 mode |= ((unit) ? 0x20 : 0x02); 288 mode |= ((unit) ? 0x20 : 0x02);
346 config_siimage_chipset_for_pio(drive, 0);
347 break; 289 break;
348 case XFER_UDMA_6: 290 case XFER_UDMA_6:
349 case XFER_UDMA_5: 291 case XFER_UDMA_5:
@@ -356,7 +298,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
356 ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : 298 ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
357 (ultra5[speed - XFER_UDMA_0])); 299 (ultra5[speed - XFER_UDMA_0]));
358 mode |= ((unit) ? 0x30 : 0x03); 300 mode |= ((unit) ? 0x30 : 0x03);
359 config_siimage_chipset_for_pio(drive, 0);
360 break; 301 break;
361 default: 302 default:
362 return 1; 303 return 1;
@@ -390,7 +331,7 @@ static int siimage_config_drive_for_dma (ide_drive_t *drive)
390 return 0; 331 return 0;
391 332
392 if (ide_use_fast_pio(drive)) 333 if (ide_use_fast_pio(drive))
393 config_siimage_chipset_for_pio(drive, 1); 334 sil_tuneproc(drive, 255);
394 335
395 return -1; 336 return -1;
396} 337}
@@ -961,7 +902,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
961 902
962 hwif->resetproc = &siimage_reset; 903 hwif->resetproc = &siimage_reset;
963 hwif->speedproc = &siimage_tune_chipset; 904 hwif->speedproc = &siimage_tune_chipset;
964 hwif->tuneproc = &siimage_tuneproc; 905 hwif->tuneproc = &sil_tuneproc;
965 hwif->reset_poll = &siimage_reset_poll; 906 hwif->reset_poll = &siimage_reset_poll;
966 hwif->pre_reset = &siimage_pre_reset; 907 hwif->pre_reset = &siimage_pre_reset;
967 hwif->udma_filter = &sil_udma_filter; 908 hwif->udma_filter = &sil_udma_filter;
@@ -976,11 +917,11 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
976 first = 0; 917 first = 0;
977 } 918 }
978 } 919 }
979 if (!hwif->dma_base) { 920
980 hwif->drives[0].autotune = 1; 921 hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
981 hwif->drives[1].autotune = 1; 922
923 if (hwif->dma_base == 0)
982 return; 924 return;
983 }
984 925
985 hwif->ultra_mask = 0x7f; 926 hwif->ultra_mask = 0x7f;
986 hwif->mwdma_mask = 0x07; 927 hwif->mwdma_mask = 0x07;