summaryrefslogtreecommitdiff
path: root/target/linux/ixp4xx/patches-2.6.38/312-ixp4xx_pata_optimization.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ixp4xx/patches-2.6.38/312-ixp4xx_pata_optimization.patch')
-rw-r--r--target/linux/ixp4xx/patches-2.6.38/312-ixp4xx_pata_optimization.patch137
1 files changed, 137 insertions, 0 deletions
diff --git a/target/linux/ixp4xx/patches-2.6.38/312-ixp4xx_pata_optimization.patch b/target/linux/ixp4xx/patches-2.6.38/312-ixp4xx_pata_optimization.patch
new file mode 100644
index 0000000..3bf1b74
--- /dev/null
+++ b/target/linux/ixp4xx/patches-2.6.38/312-ixp4xx_pata_optimization.patch
@@ -0,0 +1,137 @@
+--- 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 ata_device *dev;
++ struct ixp4xx_pata_data *data = link->ap->host->dev->platform_data;
++ unsigned int pio_mask;
+
+ ata_for_each_dev(dev, link, ENABLED) {
+- ata_dev_printk(dev, KERN_INFO, "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 = ap->host->dev->platform_data;
+@@ -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;
+ }