OpenWrt – Rev 1

Subversion Repositories:
Rev:
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -24,16 +24,58 @@
 #include <scsi/scsi_host.h>
 
 #define DRV_NAME       "pata_ixp4xx_cf"
-#define DRV_VERSION    "0.2"
+#define DRV_VERSION    "0.3"
 
 static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
 {
+       struct ixp4xx_pata_data *data = link->ap->host->dev->platform_data;
+       unsigned int pio_mask;
        struct ata_device *dev;
 
        ata_for_each_dev(dev, link, ENABLED) {
-               ata_dev_info(dev, "configured for PIO0\n");
-               dev->pio_mode = XFER_PIO_0;
-               dev->xfer_mode = XFER_PIO_0;
+               if (dev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+                       pio_mask = dev->id[ATA_ID_PIO_MODES] & 0x03;
+                       if (pio_mask & (1 << 1)) {
+                               pio_mask = 4;
+                       } else {
+                               pio_mask = 3;
+                       }
+               } else {
+                       pio_mask = (dev->id[ATA_ID_OLD_PIO_MODES] >> 8);
+               }
+
+               switch (pio_mask){
+                       case 0:
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
+                               dev->pio_mode = XFER_PIO_0;
+                               dev->xfer_mode = XFER_PIO_0;
+                               *data->cs0_cfg = 0x8a473c03;
+                               break;
+                       case 1:
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO1\n");
+                               dev->pio_mode = XFER_PIO_1;
+                               dev->xfer_mode = XFER_PIO_1;
+                               *data->cs0_cfg = 0x86433c03;
+                               break;
+                       case 2:
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO2\n");
+                               dev->pio_mode = XFER_PIO_2;
+                               dev->xfer_mode = XFER_PIO_2;
+                               *data->cs0_cfg = 0x82413c03;
+                               break;
+                       case 3:
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO3\n");
+                               dev->pio_mode = XFER_PIO_3;
+                               dev->xfer_mode = XFER_PIO_3;
+                               *data->cs0_cfg = 0x80823c03;
+                               break;
+                       case 4:
+                               ata_dev_printk(dev, KERN_INFO, "configured for PIO4\n");
+                               dev->pio_mode = XFER_PIO_4;
+                               dev->xfer_mode = XFER_PIO_4;
+                               *data->cs0_cfg = 0x80403c03;
+                               break;
+               }
                dev->xfer_shift = ATA_SHIFT_PIO;
                dev->flags |= ATA_DFLAG_PIO;
        }
@@ -46,6 +88,7 @@ static unsigned int ixp4xx_mmio_data_xfe
        unsigned int i;
        unsigned int words = buflen >> 1;
        u16 *buf16 = (u16 *) buf;
+       unsigned int pio_mask;
        struct ata_port *ap = dev->link->ap;
        void __iomem *mmio = ap->ioaddr.data_addr;
        struct ixp4xx_pata_data *data = dev_get_platdata(ap->host->dev);
@@ -53,8 +96,34 @@ static unsigned int ixp4xx_mmio_data_xfe
        /* set the expansion bus in 16bit mode and restore
         * 8 bit mode after the transaction.
         */
-       *data->cs0_cfg &= ~(0x01);
-       udelay(100);
+       if (dev->id[ATA_ID_FIELD_VALID] & (1 << 1)){
+               pio_mask = dev->id[ATA_ID_PIO_MODES] & 0x03;
+               if (pio_mask & (1 << 1)){
+                       pio_mask = 4;
+               }else{
+                       pio_mask = 3;
+               }
+       }else{
+               pio_mask = (dev->id[ATA_ID_OLD_PIO_MODES] >> 8);
+       }
+       switch (pio_mask){
+               case 0:
+                       *data->cs0_cfg = 0xa9643c42;
+               break;
+               case 1:
+                       *data->cs0_cfg = 0x85033c42;
+               break;
+               case 2:
+                       *data->cs0_cfg = 0x80b23c42;
+               break;
+               case 3:
+                       *data->cs0_cfg = 0x80823c42;
+               break;
+               case 4:
+                       *data->cs0_cfg = 0x80403c42;
+               break;
+       }
+       udelay(5);
 
        /* Transfer multiple of 2 bytes */
        if (rw == READ)
@@ -79,8 +148,24 @@ static unsigned int ixp4xx_mmio_data_xfe
                words++;
        }
 
-       udelay(100);
-       *data->cs0_cfg |= 0x01;
+       udelay(5);
+       switch (pio_mask){
+               case 0:
+                       *data->cs0_cfg = 0x8a473c03;
+               break;
+               case 1:
+                       *data->cs0_cfg = 0x86433c03;
+               break;
+               case 2:
+                       *data->cs0_cfg = 0x82413c03;
+               break;
+               case 3:
+                       *data->cs0_cfg = 0x80823c03;
+               break;
+               case 4:
+                       *data->cs0_cfg = 0x80403c03;
+               break;
+       }
 
        return words << 1;
 }