Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg...
[pandora-kernel.git] / drivers / ata / pata_hpt3x2n.c
index 32f3463..d2239bb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Libata driver for the highpoint 372N and 302N UDMA66 ATA controllers.
+ * Libata driver for the HighPoint 371N, 372N, and 302N UDMA66 ATA controllers.
  *
  * This driver is heavily based upon:
  *
@@ -8,7 +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-2009    MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2010    MontaVista Software, Inc.
  *
  *
  * TODO
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt3x2n"
-#define DRV_VERSION    "0.3.10"
+#define DRV_VERSION    "0.3.13"
 
 enum {
        HPT_PCI_FAST    =       (1 << 31),
@@ -103,7 +103,7 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)
 {
        struct hpt_clock *clocks = hpt3x2n_clocks;
 
-       while(clocks->xfer_speed) {
+       while (clocks->xfer_speed) {
                if (clocks->xfer_speed == speed)
                        return clocks->timing;
                clocks++;
@@ -112,6 +112,22 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)
        return 0xffffffffU;     /* silence compiler warning */
 }
 
+/**
+ *     hpt372n_filter  -       mode selection filter
+ *     @adev: ATA device
+ *     @mask: mode mask
+ *
+ *     The Marvell bridge chips used on the HighPoint SATA cards do not seem
+ *     to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
+ */
+static unsigned long hpt372n_filter(struct ata_device *adev, unsigned long mask)
+{
+       if (ata_id_is_sata(adev->id))
+               mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
+
+       return mask;
+}
+
 /**
  *     hpt3x2n_cable_detect    -       Detect the cable type
  *     @ap: ATA port to detect on
@@ -153,6 +169,7 @@ static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
 {
        struct ata_port *ap = link->ap;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
        /* Reset the state machine */
        pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
        udelay(100);
@@ -328,10 +345,10 @@ static struct scsi_host_template hpt3x2n_sht = {
 };
 
 /*
- *     Configuration for HPT3x2n.
+ *     Configuration for HPT302N/371N.
  */
 
-static struct ata_port_operations hpt3x2n_port_ops = {
+static struct ata_port_operations hpt3xxn_port_ops = {
        .inherits       = &ata_bmdma_port_ops,
 
        .bmdma_stop     = hpt3x2n_bmdma_stop,
@@ -345,6 +362,15 @@ static struct ata_port_operations hpt3x2n_port_ops = {
        .prereset       = hpt3x2n_pre_reset,
 };
 
+/*
+ *     Configuration for HPT372N. Same as 302N/371N but we have a mode filter.
+ */
+
+static struct ata_port_operations hpt372n_port_ops = {
+       .inherits       = &hpt3xxn_port_ops,
+       .mode_filter    = &hpt372n_filter,
+};
+
 /**
  *     hpt3xn_calibrate_dpll           -       Calibrate the DPLL loop
  *     @dev: PCI device
@@ -359,12 +385,12 @@ static int hpt3xn_calibrate_dpll(struct pci_dev *dev)
        u32 reg5c;
        int tries;
 
-       for(tries = 0; tries < 0x5000; tries++) {
+       for (tries = 0; tries < 0x5000; tries++) {
                udelay(50);
                pci_read_config_byte(dev, 0x5b, &reg5b);
                if (reg5b & 0x80) {
                        /* See if it stays set */
-                       for(tries = 0; tries < 0x1000; tries ++) {
+                       for (tries = 0; tries < 0x1000; tries++) {
                                pci_read_config_byte(dev, 0x5b, &reg5b);
                                /* Failed ? */
                                if ((reg5b & 0x80) == 0)
@@ -372,7 +398,7 @@ static int hpt3xn_calibrate_dpll(struct pci_dev *dev)
                        }
                        /* Turn off tuning, we have the DPLL set */
                        pci_read_config_dword(dev, 0x5c, &reg5c);
-                       pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);
+                       pci_write_config_dword(dev, 0x5c, reg5c & ~0x100);
                        return 1;
                }
        }
@@ -388,8 +414,19 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)
 
        fcnt = inl(iobase + 0x90);      /* Not PCI readable for some chips */
        if ((fcnt >> 12) != 0xABCDE) {
-               printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n");
-               return 33;      /* Not BIOS set */
+               int i;
+               u16 sr;
+               u32 total = 0;
+
+               printk(KERN_WARNING "pata_hpt3x2n: BIOS clock data not set.\n");
+
+               /* This is the process the HPT371 BIOS is reported to use */
+               for (i = 0; i < 128; i++) {
+                       pci_read_config_word(pdev, 0x78, &sr);
+                       total += sr & 0x1FF;
+                       udelay(15);
+               }
+               fcnt = total / 128;
        }
        fcnt &= 0x1FF;
 
@@ -431,21 +468,27 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)
  *     HPT372N                 9 (HPT372N)     *       UDMA133
  *
  *     (1) UDMA133 support depends on the bus clock
- *
- *     To pin down             HPT371N
  */
 
 static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       /* HPT372N and friends - UDMA133 */
-       static const struct ata_port_info info = {
+       /* HPT372N - UDMA133 */
+       static const struct ata_port_info info_hpt372n = {
+               .flags = ATA_FLAG_SLAVE_POSS,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA6,
+               .port_ops = &hpt372n_port_ops
+       };
+       /* HPT302N and HPT371N - UDMA133 */
+       static const struct ata_port_info info_hpt3xxn = {
                .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = ATA_PIO4,
                .mwdma_mask = ATA_MWDMA2,
                .udma_mask = ATA_UDMA6,
-               .port_ops = &hpt3x2n_port_ops
+               .port_ops = &hpt3xxn_port_ops
        };
-       const struct ata_port_info *ppi[] = { &info, NULL };
+       const struct ata_port_info *ppi[] = { &info_hpt3xxn, NULL };
        u8 rev = dev->revision;
        u8 irqmask;
        unsigned int pci_mhz;
@@ -459,30 +502,36 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        if (rc)
                return rc;
 
-       switch(dev->device) {
-               case PCI_DEVICE_ID_TTI_HPT366:
-                       if (rev < 6)
-                               return -ENODEV;
-                       break;
-               case PCI_DEVICE_ID_TTI_HPT371:
-                       if (rev < 2)
-                               return -ENODEV;
-                       /* 371N if rev > 1 */
-                       break;
-               case PCI_DEVICE_ID_TTI_HPT372:
-                       /* 372N if rev >= 2*/
-                       if (rev < 2)
-                               return -ENODEV;
-                       break;
-               case PCI_DEVICE_ID_TTI_HPT302:
-                       if (rev < 2)
-                               return -ENODEV;
-                       break;
-               case PCI_DEVICE_ID_TTI_HPT372N:
-                       break;
-               default:
-                       printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);
+       switch (dev->device) {
+       case PCI_DEVICE_ID_TTI_HPT366:
+               /* 372N if rev >= 6 */
+               if (rev < 6)
                        return -ENODEV;
+               goto hpt372n;
+       case PCI_DEVICE_ID_TTI_HPT371:
+               /* 371N if rev >= 2 */
+               if (rev < 2)
+                       return -ENODEV;
+               break;
+       case PCI_DEVICE_ID_TTI_HPT372:
+               /* 372N if rev >= 2 */
+               if (rev < 2)
+                       return -ENODEV;
+               goto hpt372n;
+       case PCI_DEVICE_ID_TTI_HPT302:
+               /* 302N if rev >= 2 */
+               if (rev < 2)
+                       return -ENODEV;
+               break;
+       case PCI_DEVICE_ID_TTI_HPT372N:
+hpt372n:
+               ppi[0] = &info_hpt372n;
+               break;
+       default:
+               printk(KERN_ERR
+                      "pata_hpt3x2n: PCI table is bogus please report (%d).\n",
+                      dev->device);
+               return -ENODEV;
        }
 
        /* Ok so this is a chip we support */
@@ -509,8 +558,10 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                pci_write_config_byte(dev, 0x50, mcr1);
        }
 
-       /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or
-          50 for UDMA100. Right now we always use 66 */
+       /*
+        * Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or
+        * 50 for UDMA100. Right now we always use 66
+        */
 
        pci_mhz = hpt3x2n_pci_clock(dev);
 
@@ -522,7 +573,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        pci_write_config_byte(dev, 0x5B, 0x21);
 
        /* Unlike the 37x we don't try jiggling the frequency */
-       for(adjust = 0; adjust < 8; adjust++) {
+       for (adjust = 0; adjust < 8; adjust++) {
                if (hpt3xn_calibrate_dpll(dev))
                        break;
                pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
@@ -534,8 +585,11 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n",
               pci_mhz);
-       /* Set our private data up. We only need a few flags so we use
-          it directly */
+
+       /*
+        * Set our private data up. We only need a few flags
+        * so we use it directly.
+        */
        if (pci_mhz > 60)
                hpriv = (void *)(PCI66 | USE_DPLL);
 
@@ -562,9 +616,9 @@ static const struct pci_device_id hpt3x2n[] = {
 };
 
 static struct pci_driver hpt3x2n_pci_driver = {
-       .name           = DRV_NAME,
+       .name           = DRV_NAME,
        .id_table       = hpt3x2n,
-       .probe          = hpt3x2n_init_one,
+       .probe          = hpt3x2n_init_one,
        .remove         = ata_pci_remove_one
 };
 
@@ -579,7 +633,7 @@ static void __exit hpt3x2n_exit(void)
 }
 
 MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x");
+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3xxN");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, hpt3x2n);
 MODULE_VERSION(DRV_VERSION);