cs5530/sc1200: add ->speedproc support
[pandora-kernel.git] / drivers / ide / pci / sc1200.c
index 65dcabe..c989fd9 100644 (file)
@@ -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;