aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/sc1200.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-16 00:51:44 +0200
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-16 00:51:44 +0200
commit3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f (patch)
treea30b4d97b72f14bd2781d73f88c0c3f7abd87616 /drivers/ide/pci/sc1200.c
parentcs5530/sc1200: DMA support cleanup (diff)
downloadlinux-dev-3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f.tar.xz
linux-dev-3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f.zip
cs5530/sc1200: add ->speedproc support
* add {cs5530,sc1200}_tunepio() for programming PIO timings * add {cs5530,sc1200}_tune_chipset() (->speedproc method) for setting transfer mode and convert {cs5530,sc1200}_config_dma() to use it * bump driver version Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to '')
-rw-r--r--drivers/ide/pci/sc1200.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 65dcabe48205..c989fd90f377 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/sc1200.c Version 0.93 Mar 10 2007
+ * linux/drivers/ide/pci/sc1200.c Version 0.94 Mar 10 2007
*
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
@@ -95,6 +95,20 @@ static const unsigned int sc1200_pio_timings[4][5] =
*/
//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
+static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *pdev = hwif->pci_dev;
+ unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
+
+ pci_read_config_dword(pdev, basereg + 4, &format);
+ format = (format >> 31) & 1;
+ if (format)
+ format += sc1200_get_pci_clock();
+ pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3),
+ sc1200_pio_timings[format][pio]);
+}
+
/*
* The SC1200 specifies that two drives sharing a cable cannot mix
* UDMA/MDMA. It has to be one or the other, for the pair, though
@@ -124,11 +138,7 @@ out:
return mask;
}
-/*
- * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes
- * for both the chipset and drive.
- */
-static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
+static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode)
{
ide_hwif_t *hwif = HWIF(drive);
int unit = drive->select.b.unit;
@@ -136,14 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
unsigned short pci_clock;
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
+ mode = ide_rate_filter(drive, mode);
+
/*
* Tell the drive to switch to the new mode; abort on failure.
*/
- if (!mode || sc1200_set_xfer_mode(drive, mode)) {
+ if (sc1200_set_xfer_mode(drive, mode)) {
printk("SC1200: set xfer mode failure\n");
return 1; /* failure */
}
+ switch (mode) {
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ sc1200_tunepio(drive, mode - XFER_PIO_0);
+ return 0;
+ }
+
pci_clock = sc1200_get_pci_clock();
/*
@@ -196,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
case PCI_CLK_66: timings = 0x00015151; break;
}
break;
- }
-
- if (timings == 0) {
- printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock);
- return 1; /* failure */
+ default:
+ BUG();
+ break;
}
if (unit == 0) { /* are we configuring drive0? */
@@ -220,12 +240,14 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
*/
static int sc1200_config_dma (ide_drive_t *drive)
{
- u8 mode = 0;
+ if (ide_use_dma(drive)) {
+ u8 mode = ide_max_dma_mode(drive);
- if (ide_use_dma(drive))
- mode = ide_max_dma_mode(drive);
+ if (mode && drive->hwif->speedproc(drive, mode) == 0)
+ return 0;
+ }
- return sc1200_config_dma2(drive, mode);
+ return 1;
}
@@ -265,8 +287,6 @@ static int sc1200_ide_dma_end (ide_drive_t *drive)
static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int format;
- static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
int mode = -1;
/*
@@ -283,21 +303,16 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au
if (mode != -1) {
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
hwif->dma_off_quietly(drive);
- if (sc1200_config_dma2(drive, mode) == 0)
+ if (sc1200_tune_chipset(drive, mode) == 0)
hwif->dma_host_on(drive);
return;
}
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio);
- if (!sc1200_set_xfer_mode(drive, modes[pio])) {
- unsigned int basereg = hwif->channel ? 0x50 : 0x40;
- pci_read_config_dword (hwif->pci_dev, basereg+4, &format);
- format = (format >> 31) & 1;
- if (format)
- format += sc1200_get_pci_clock();
- pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]);
- }
+
+ if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
+ sc1200_tunepio(drive, pio);
}
#ifdef CONFIG_PM
@@ -447,6 +462,7 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
if (!noautodma)
hwif->autodma = 1;
hwif->tuneproc = &sc1200_tuneproc;
+ hwif->speedproc = &sc1200_tune_chipset;
}
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x07;