pata_hpt37x: Updates from drivers/ide work
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Thu, 8 Mar 2007 23:28:52 +0000 (23:28 +0000)
committerJeff Garzik <jeff@garzik.org>
Sat, 28 Apr 2007 18:15:58 +0000 (14:15 -0400)
Drag pata_hpt37x kicking and screaming in the direction of
drivers/ide/pci/hpt366.c and all the work that Sergei has been doing
there. Plenty left to be done but this is a good snapshot for folks to
work on and to review

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/ata/pata_hpt37x.c

index f331eeeafa0f39d75302023953c676910d446e64..12f387f377712f944de70aaea47b55a383d314be 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001         Sun Microsystems, Inc.
  * Portions Copyright (C) 2003         Red Hat Inc
+ * Portions Copyright (C) 2005-2006    MontaVista Software, Inc.
  *
  * TODO
  *     PLL mode
@@ -25,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt37x"
-#define DRV_VERSION    "0.6.0"
+#define DRV_VERSION    "0.6.4"
 
 struct hpt_clock {
        u8      xfer_speed;
@@ -61,201 +62,75 @@ struct hpt_chip {
  * 31     FIFO enable.
  */
 
-/* from highpoint documentation. these are old values */
-static const struct hpt_clock hpt370_timings_33[] = {
-/*     {       XFER_UDMA_5,    0x1A85F442,     0x16454e31      }, */
-       {       XFER_UDMA_5,    0x16454e31      },
-       {       XFER_UDMA_4,    0x16454e31      },
-       {       XFER_UDMA_3,    0x166d4e31      },
-       {       XFER_UDMA_2,    0x16494e31      },
-       {       XFER_UDMA_1,    0x164d4e31      },
-       {       XFER_UDMA_0,    0x16514e31      },
-
-       {       XFER_MW_DMA_2,  0x26514e21      },
-       {       XFER_MW_DMA_1,  0x26514e33      },
-       {       XFER_MW_DMA_0,  0x26514e97      },
-
-       {       XFER_PIO_4,     0x06514e21      },
-       {       XFER_PIO_3,     0x06514e22      },
-       {       XFER_PIO_2,     0x06514e33      },
-       {       XFER_PIO_1,     0x06914e43      },
-       {       XFER_PIO_0,     0x06914e57      },
-       {       0,              0x06514e57      }
+static struct hpt_clock hpt37x_timings_33[] = {
+       { XFER_UDMA_6,          0x12446231 },   /* 0x12646231 ?? */
+       { XFER_UDMA_5,          0x12446231 },
+       { XFER_UDMA_4,          0x12446231 },
+       { XFER_UDMA_3,          0x126c6231 },
+       { XFER_UDMA_2,          0x12486231 },
+       { XFER_UDMA_1,          0x124c6233 },
+       { XFER_UDMA_0,          0x12506297 },
+
+       { XFER_MW_DMA_2,        0x22406c31 },
+       { XFER_MW_DMA_1,        0x22406c33 },
+       { XFER_MW_DMA_0,        0x22406c97 },
+
+       { XFER_PIO_4,           0x06414e31 },
+       { XFER_PIO_3,           0x06414e42 },
+       { XFER_PIO_2,           0x06414e53 },
+       { XFER_PIO_1,           0x06814e93 },
+       { XFER_PIO_0,           0x06814ea7 }
 };
 
-static const struct hpt_clock hpt370_timings_66[] = {
-       {       XFER_UDMA_5,    0x14846231      },
-       {       XFER_UDMA_4,    0x14886231      },
-       {       XFER_UDMA_3,    0x148c6231      },
-       {       XFER_UDMA_2,    0x148c6231      },
-       {       XFER_UDMA_1,    0x14906231      },
-       {       XFER_UDMA_0,    0x14986231      },
-
-       {       XFER_MW_DMA_2,  0x26514e21      },
-       {       XFER_MW_DMA_1,  0x26514e33      },
-       {       XFER_MW_DMA_0,  0x26514e97      },
-
-       {       XFER_PIO_4,     0x06514e21      },
-       {       XFER_PIO_3,     0x06514e22      },
-       {       XFER_PIO_2,     0x06514e33      },
-       {       XFER_PIO_1,     0x06914e43      },
-       {       XFER_PIO_0,     0x06914e57      },
-       {       0,              0x06514e57      }
+static struct hpt_clock hpt37x_timings_50[] = {
+       { XFER_UDMA_6,          0x12848242 },
+       { XFER_UDMA_5,          0x12848242 },
+       { XFER_UDMA_4,          0x12ac8242 },
+       { XFER_UDMA_3,          0x128c8242 },
+       { XFER_UDMA_2,          0x120c8242 },
+       { XFER_UDMA_1,          0x12148254 },
+       { XFER_UDMA_0,          0x121882ea },
+
+       { XFER_MW_DMA_2,        0x22808242 },
+       { XFER_MW_DMA_1,        0x22808254 },
+       { XFER_MW_DMA_0,        0x228082ea },
+
+       { XFER_PIO_4,           0x0a81f442 },
+       { XFER_PIO_3,           0x0a81f443 },
+       { XFER_PIO_2,           0x0a81f454 },
+       { XFER_PIO_1,           0x0ac1f465 },
+       { XFER_PIO_0,           0x0ac1f48a }
 };
 
-/* these are the current (4 sep 2001) timings from highpoint */
-static const struct hpt_clock hpt370a_timings_33[] = {
-       {       XFER_UDMA_5,    0x12446231      },
-       {       XFER_UDMA_4,    0x12446231      },
-       {       XFER_UDMA_3,    0x126c6231      },
-       {       XFER_UDMA_2,    0x12486231      },
-       {       XFER_UDMA_1,    0x124c6233      },
-       {       XFER_UDMA_0,    0x12506297      },
-
-       {       XFER_MW_DMA_2,  0x22406c31      },
-       {       XFER_MW_DMA_1,  0x22406c33      },
-       {       XFER_MW_DMA_0,  0x22406c97      },
-
-       {       XFER_PIO_4,     0x06414e31      },
-       {       XFER_PIO_3,     0x06414e42      },
-       {       XFER_PIO_2,     0x06414e53      },
-       {       XFER_PIO_1,     0x06814e93      },
-       {       XFER_PIO_0,     0x06814ea7      },
-       {       0,              0x06814ea7      }
+static struct hpt_clock hpt37x_timings_66[] = {
+       { XFER_UDMA_6,          0x1c869c62 },
+       { XFER_UDMA_5,          0x1cae9c62 },   /* 0x1c8a9c62 */
+       { XFER_UDMA_4,          0x1c8a9c62 },
+       { XFER_UDMA_3,          0x1c8e9c62 },
+       { XFER_UDMA_2,          0x1c929c62 },
+       { XFER_UDMA_1,          0x1c9a9c62 },
+       { XFER_UDMA_0,          0x1c829c62 },
+
+       { XFER_MW_DMA_2,        0x2c829c62 },
+       { XFER_MW_DMA_1,        0x2c829c66 },
+       { XFER_MW_DMA_0,        0x2c829d2e },
+
+       { XFER_PIO_4,           0x0c829c62 },
+       { XFER_PIO_3,           0x0c829c84 },
+       { XFER_PIO_2,           0x0c829ca6 },
+       { XFER_PIO_1,           0x0d029d26 },
+       { XFER_PIO_0,           0x0d029d5e }
 };
 
-/* 2x 33MHz timings */
-static const struct hpt_clock hpt370a_timings_66[] = {
-       {       XFER_UDMA_5,    0x1488e673      },
-       {       XFER_UDMA_4,    0x1488e673      },
-       {       XFER_UDMA_3,    0x1498e673      },
-       {       XFER_UDMA_2,    0x1490e673      },
-       {       XFER_UDMA_1,    0x1498e677      },
-       {       XFER_UDMA_0,    0x14a0e73f      },
-
-       {       XFER_MW_DMA_2,  0x2480fa73      },
-       {       XFER_MW_DMA_1,  0x2480fa77      },
-       {       XFER_MW_DMA_0,  0x2480fb3f      },
-
-       {       XFER_PIO_4,     0x0c82be73      },
-       {       XFER_PIO_3,     0x0c82be95      },
-       {       XFER_PIO_2,     0x0c82beb7      },
-       {       XFER_PIO_1,     0x0d02bf37      },
-       {       XFER_PIO_0,     0x0d02bf5f      },
-       {       0,              0x0d02bf5f      }
-};
-
-static const struct hpt_clock hpt370a_timings_50[] = {
-       {       XFER_UDMA_5,    0x12848242      },
-       {       XFER_UDMA_4,    0x12ac8242      },
-       {       XFER_UDMA_3,    0x128c8242      },
-       {       XFER_UDMA_2,    0x120c8242      },
-       {       XFER_UDMA_1,    0x12148254      },
-       {       XFER_UDMA_0,    0x121882ea      },
-
-       {       XFER_MW_DMA_2,  0x22808242      },
-       {       XFER_MW_DMA_1,  0x22808254      },
-       {       XFER_MW_DMA_0,  0x228082ea      },
-
-       {       XFER_PIO_4,     0x0a81f442      },
-       {       XFER_PIO_3,     0x0a81f443      },
-       {       XFER_PIO_2,     0x0a81f454      },
-       {       XFER_PIO_1,     0x0ac1f465      },
-       {       XFER_PIO_0,     0x0ac1f48a      },
-       {       0,              0x0ac1f48a      }
-};
-
-static const struct hpt_clock hpt372_timings_33[] = {
-       {       XFER_UDMA_6,    0x1c81dc62      },
-       {       XFER_UDMA_5,    0x1c6ddc62      },
-       {       XFER_UDMA_4,    0x1c8ddc62      },
-       {       XFER_UDMA_3,    0x1c8edc62      },      /* checkme */
-       {       XFER_UDMA_2,    0x1c91dc62      },
-       {       XFER_UDMA_1,    0x1c9adc62      },      /* checkme */
-       {       XFER_UDMA_0,    0x1c82dc62      },      /* checkme */
-
-       {       XFER_MW_DMA_2,  0x2c829262      },
-       {       XFER_MW_DMA_1,  0x2c829266      },      /* checkme */
-       {       XFER_MW_DMA_0,  0x2c82922e      },      /* checkme */
-
-       {       XFER_PIO_4,     0x0c829c62      },
-       {       XFER_PIO_3,     0x0c829c84      },
-       {       XFER_PIO_2,     0x0c829ca6      },
-       {       XFER_PIO_1,     0x0d029d26      },
-       {       XFER_PIO_0,     0x0d029d5e      },
-       {       0,              0x0d029d5e      }
-};
-
-static const struct hpt_clock hpt372_timings_50[] = {
-       {       XFER_UDMA_5,    0x12848242      },
-       {       XFER_UDMA_4,    0x12ac8242      },
-       {       XFER_UDMA_3,    0x128c8242      },
-       {       XFER_UDMA_2,    0x120c8242      },
-       {       XFER_UDMA_1,    0x12148254      },
-       {       XFER_UDMA_0,    0x121882ea      },
-
-       {       XFER_MW_DMA_2,  0x22808242      },
-       {       XFER_MW_DMA_1,  0x22808254      },
-       {       XFER_MW_DMA_0,  0x228082ea      },
-
-       {       XFER_PIO_4,     0x0a81f442      },
-       {       XFER_PIO_3,     0x0a81f443      },
-       {       XFER_PIO_2,     0x0a81f454      },
-       {       XFER_PIO_1,     0x0ac1f465      },
-       {       XFER_PIO_0,     0x0ac1f48a      },
-       {       0,              0x0a81f443      }
-};
-
-static const struct hpt_clock hpt372_timings_66[] = {
-       {       XFER_UDMA_6,    0x1c869c62      },
-       {       XFER_UDMA_5,    0x1cae9c62      },
-       {       XFER_UDMA_4,    0x1c8a9c62      },
-       {       XFER_UDMA_3,    0x1c8e9c62      },
-       {       XFER_UDMA_2,    0x1c929c62      },
-       {       XFER_UDMA_1,    0x1c9a9c62      },
-       {       XFER_UDMA_0,    0x1c829c62      },
-
-       {       XFER_MW_DMA_2,  0x2c829c62      },
-       {       XFER_MW_DMA_1,  0x2c829c66      },
-       {       XFER_MW_DMA_0,  0x2c829d2e      },
-
-       {       XFER_PIO_4,     0x0c829c62      },
-       {       XFER_PIO_3,     0x0c829c84      },
-       {       XFER_PIO_2,     0x0c829ca6      },
-       {       XFER_PIO_1,     0x0d029d26      },
-       {       XFER_PIO_0,     0x0d029d5e      },
-       {       0,              0x0d029d26      }
-};
-
-static const struct hpt_clock hpt374_timings_33[] = {
-       {       XFER_UDMA_6,    0x12808242      },
-       {       XFER_UDMA_5,    0x12848242      },
-       {       XFER_UDMA_4,    0x12ac8242      },
-       {       XFER_UDMA_3,    0x128c8242      },
-       {       XFER_UDMA_2,    0x120c8242      },
-       {       XFER_UDMA_1,    0x12148254      },
-       {       XFER_UDMA_0,    0x121882ea      },
-
-       {       XFER_MW_DMA_2,  0x22808242      },
-       {       XFER_MW_DMA_1,  0x22808254      },
-       {       XFER_MW_DMA_0,  0x228082ea      },
-
-       {       XFER_PIO_4,     0x0a81f442      },
-       {       XFER_PIO_3,     0x0a81f443      },
-       {       XFER_PIO_2,     0x0a81f454      },
-       {       XFER_PIO_1,     0x0ac1f465      },
-       {       XFER_PIO_0,     0x0ac1f48a      },
-       {       0,              0x06814e93      }
-};
 
 static const struct hpt_chip hpt370 = {
        "HPT370",
        48,
        {
-               hpt370_timings_33,
+               hpt37x_timings_33,
                NULL,
                NULL,
-               hpt370_timings_66
+               hpt37x_timings_66
        }
 };
 
@@ -263,10 +138,10 @@ static const struct hpt_chip hpt370a = {
        "HPT370A",
        48,
        {
-               hpt370a_timings_33,
+               hpt37x_timings_33,
                NULL,
-               hpt370a_timings_50,
-               hpt370a_timings_66
+               hpt37x_timings_50,
+               hpt37x_timings_66
        }
 };
 
@@ -274,10 +149,10 @@ static const struct hpt_chip hpt372 = {
        "HPT372",
        55,
        {
-               hpt372_timings_33,
+               hpt37x_timings_33,
                NULL,
-               hpt372_timings_50,
-               hpt372_timings_66
+               hpt37x_timings_50,
+               hpt37x_timings_66
        }
 };
 
@@ -285,10 +160,10 @@ static const struct hpt_chip hpt302 = {
        "HPT302",
        66,
        {
-               hpt372_timings_33,
+               hpt37x_timings_33,
                NULL,
-               hpt372_timings_50,
-               hpt372_timings_66
+               hpt37x_timings_50,
+               hpt37x_timings_66
        }
 };
 
@@ -296,10 +171,10 @@ static const struct hpt_chip hpt371 = {
        "HPT371",
        66,
        {
-               hpt372_timings_33,
+               hpt37x_timings_33,
                NULL,
-               hpt372_timings_50,
-               hpt372_timings_66
+               hpt37x_timings_50,
+               hpt37x_timings_66
        }
 };
 
@@ -307,10 +182,10 @@ static const struct hpt_chip hpt372a = {
        "HPT372A",
        66,
        {
-               hpt372_timings_33,
+               hpt37x_timings_33,
                NULL,
-               hpt372_timings_50,
-               hpt372_timings_66
+               hpt37x_timings_50,
+               hpt37x_timings_66
        }
 };
 
@@ -318,7 +193,7 @@ static const struct hpt_chip hpt374 = {
        "HPT374",
        48,
        {
-               hpt374_timings_33,
+               hpt37x_timings_33,
                NULL,
                NULL,
                NULL
@@ -462,8 +337,7 @@ static int hpt37x_pre_reset(struct ata_port *ap)
                ap->cbl = ATA_CBL_PATA80;
 
        /* Reset the state machine */
-       pci_write_config_byte(pdev, 0x50, 0x37);
-       pci_write_config_byte(pdev, 0x54, 0x37);
+       pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
        udelay(100);
 
        return ata_std_prereset(ap);
@@ -513,8 +387,7 @@ static int hpt374_pre_reset(struct ata_port *ap)
                ap->cbl = ATA_CBL_PATA80;
 
        /* Reset the state machine */
-       pci_write_config_byte(pdev, 0x50, 0x37);
-       pci_write_config_byte(pdev, 0x54, 0x37);
+       pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
        udelay(100);
 
        return ata_std_prereset(ap);
@@ -1032,6 +905,24 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                .udma_mask = 0x3f,
                .port_ops = &hpt370a_port_ops
        };
+       /* HPT370 - UDMA100 */
+       static struct ata_port_info info_hpt370_33 = {
+               .sht = &hpt37x_sht,
+               .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+               .pio_mask = 0x1f,
+               .mwdma_mask = 0x07,
+               .udma_mask = 0x0f,
+               .port_ops = &hpt370_port_ops
+       };
+       /* HPT370A - UDMA100 */
+       static struct ata_port_info info_hpt370a_33 = {
+               .sht = &hpt37x_sht,
+               .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+               .pio_mask = 0x1f,
+               .mwdma_mask = 0x07,
+               .udma_mask = 0x0f,
+               .port_ops = &hpt370a_port_ops
+       };
        /* HPT371, 372 and friends - UDMA133 */
        static struct ata_port_info info_hpt372 = {
                .sht = &hpt37x_sht,
@@ -1067,7 +958,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        u8 irqmask;
        u32 class_rev;
+       u8 mcr1;
        u32 freq;
+       int prefer_dpll = 1;
+       
+       unsigned long iobase = pci_resource_start(dev, 4);
 
        const struct hpt_chip *chip_table;
        int clock_slot;
@@ -1088,10 +983,12 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                        case 3:
                                port = &info_hpt370;
                                chip_table = &hpt370;
+                               prefer_dpll = 0;
                                break;
                        case 4:
                                port = &info_hpt370a;
                                chip_table = &hpt370a;
+                               prefer_dpll = 0;
                                break;
                        case 5:
                                port = &info_hpt372;
@@ -1119,8 +1016,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                                chip_table = &hpt302;
                                break;
                        case PCI_DEVICE_ID_TTI_HPT371:
+                               if (class_rev > 1)
+                                       return -ENODEV;
                                port = &info_hpt372;
                                chip_table = &hpt371;
+                               /* Single channel device, paster is not present
+                                  but the NIOS (or us for non x86) must mark it
+                                  absent */
+                               pci_read_config_byte(dev, 0x50, &mcr1);
+                               mcr1 &= ~0x04;
+                               pci_write_config_byte(dev, 0x50, mcr1);
                                break;
                        case PCI_DEVICE_ID_TTI_HPT374:
                                chip_table = &hpt374;
@@ -1150,8 +1055,18 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
         */
 
        pci_write_config_byte(dev, 0x5b, 0x23);
+       
+       /*
+        * HighPoint does this for HPT372A.
+        * NOTE: This register is only writeable via I/O space.
+        */
+       if (chip_table == &hpt372a)
+               outb(0x0e, iobase + 0x9c);
 
-       pci_read_config_dword(dev, 0x70, &freq);
+       /* Some devices do not let this value be accessed via PCI space
+          according to the old driver */
+
+       freq = inl(iobase + 0x90);
        if ((freq >> 12) != 0xABCDE) {
                int i;
                u8 sr;
@@ -1162,7 +1077,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                /* This is the process the HPT371 BIOS is reported to use */
                for(i = 0; i < 128; i++) {
                        pci_read_config_byte(dev, 0x78, &sr);
-                       total += sr;
+                       total += sr & 0x1FF;
                        udelay(15);
                }
                freq = total / 128;
@@ -1173,15 +1088,27 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
         *      Turn the frequency check into a band and then find a timing
         *      table to match it.
         */
-
+        
        clock_slot = hpt37x_clock_slot(freq, chip_table->base);
-       if (chip_table->clocks[clock_slot] == NULL) {
+       if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) {
                /*
                 *      We need to try PLL mode instead
+                *
+                *      For non UDMA133 capable devices we should
+                *      use a 50MHz DPLL by choice
                 */
-               unsigned int f_low = (MHz[clock_slot] * chip_table->base) / 192;
-               unsigned int f_high = f_low + 2;
+               unsigned int f_low, f_high;
                int adjust;
+               
+               clock_slot = 2;
+               if (port->udma_mask & 0xE0)
+                       clock_slot = 3;
+               
+               f_low = (MHz[clock_slot] * chip_table->base) / 192;
+               f_high = f_low + 2;
+
+               /* Select the DPLL clock. */
+               pci_write_config_byte(dev, 0x5b, 0x21);
 
                for(adjust = 0; adjust < 8; adjust++) {
                        if (hpt37x_calibrate_dpll(dev))
@@ -1197,15 +1124,17 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                        printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n");
                        return -ENODEV;
                }
-               /* Check if this works for all cases */
-               port->private_data = (void *)hpt370_timings_66;
+               if (clock_slot == 3)
+                       port->private_data = (void *)hpt37x_timings_66;
+               else
+                       port->private_data = (void *)hpt37x_timings_50;
 
                printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]);
        } else {
                port->private_data = (void *)chip_table->clocks[clock_slot];
                /*
                 *      Perform a final fixup. The 371 and 372 clock determines
-                *      if UDMA133 is available.
+                *      if UDMA133 is available. (FIXME: should we use DPLL then ?)
                 */
 
                if (clock_slot == 2 && chip_table == &hpt372) { /* 50Mhz */
@@ -1214,8 +1143,13 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                                port = &info_hpt372_50;
                        else BUG();
                }
+               if (clock_slot < 2 && port == &info_hpt370)
+                       port = &info_hpt370_33;
+               if (clock_slot < 2 && port == &info_hpt370a)
+                       port = &info_hpt370a_33;
                printk(KERN_INFO "hpt37x: %s: Bus clock %dMHz.\n", chip_table->name, MHz[clock_slot]);
        }
+
        port_info[0] = port_info[1] = port;
        /* Now kick off ATA set up */
        return ata_pci_init_one(dev, port_info, 2);