IB/mlx4: Properly initialize GRH TClass and FlowLabel in AHs
[pandora-kernel.git] / drivers / ide / alim15x3.c
index 0abc43f..2c8016a 100644 (file)
@@ -8,7 +8,7 @@
  *  Copyright (C) 2002 Alan Cox
  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
  *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
- *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+ *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
  *
@@ -48,61 +48,84 @@ static u8 m5229_revision;
 static u8 chip_is_1543c_e;
 static struct pci_dev *isa_dev;
 
+static void ali_fifo_control(ide_hwif_t *hwif, ide_drive_t *drive, int on)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       int pio_fifo = 0x54 + hwif->channel;
+       u8 fifo;
+       int shift = 4 * (drive->dn & 1);
+
+       pci_read_config_byte(pdev, pio_fifo, &fifo);
+       fifo &= ~(0x0F << shift);
+       fifo |= (on << shift);
+       pci_write_config_byte(pdev, pio_fifo, fifo);
+}
+
+static void ali_program_timings(ide_hwif_t *hwif, ide_drive_t *drive,
+                               struct ide_timing *t, u8 ultra)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       int port = hwif->channel ? 0x5c : 0x58;
+       int udmat = 0x56 + hwif->channel;
+       u8 unit = drive->dn & 1, udma;
+       int shift = 4 * unit;
+
+       /* Set up the UDMA */
+       pci_read_config_byte(dev, udmat, &udma);
+       udma &= ~(0x0F << shift);
+       udma |= ultra << shift;
+       pci_write_config_byte(dev, udmat, udma);
+
+       if (t == NULL)
+               return;
+
+       t->setup = clamp_val(t->setup, 1, 8) & 7;
+       t->act8b = clamp_val(t->act8b, 1, 8) & 7;
+       t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
+       t->active = clamp_val(t->active, 1, 8) & 7;
+       t->recover = clamp_val(t->recover, 1, 16) & 15;
+
+       pci_write_config_byte(dev, port, t->setup);
+       pci_write_config_byte(dev, port + 1, (t->act8b << 4) | t->rec8b);
+       pci_write_config_byte(dev, port + unit + 2,
+                             (t->active << 4) | t->recover);
+}
+
 /**
  *     ali_set_pio_mode        -       set host controller for PIO mode
+ *     @hwif: port
  *     @drive: drive
- *     @pio: PIO mode number
  *
  *     Program the controller for the given PIO mode.
  */
 
-static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void ali_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-       int s_time = t->setup, a_time = t->active, c_time = t->cycle;
-       u8 s_clc, a_clc, r_clc;
-       unsigned long flags;
+       ide_drive_t *pair = ide_get_pair_dev(drive);
        int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-       int port = hwif->channel ? 0x5c : 0x58;
-       int portFIFO = hwif->channel ? 0x55 : 0x54;
-       u8 cd_dma_fifo = 0, unit = drive->dn & 1;
-
-       if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
-               s_clc = 0;
-       if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
-               a_clc = 0;
-
-       if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
-               r_clc = 1;
-       } else {
-               if (r_clc >= 16)
-                       r_clc = 0;
+       unsigned long T =  1000000 / bus_speed; /* PCI clock based */
+       struct ide_timing t;
+
+       ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
+       if (pair) {
+               struct ide_timing p;
+
+               ide_timing_compute(pair, pair->pio_mode, &p, T, 1);
+               ide_timing_merge(&p, &t, &t,
+                       IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+               if (pair->dma_mode) {
+                       ide_timing_compute(pair, pair->dma_mode, &p, T, 1);
+                       ide_timing_merge(&p, &t, &t,
+                               IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+               }
        }
-       local_irq_save(flags);
-       
+
        /* 
         * PIO mode => ATA FIFO on, ATAPI FIFO off
         */
-       pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);
-       if (drive->media==ide_disk) {
-               if (unit) {
-                       pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);
-               } else {
-                       pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);
-               }
-       } else {
-               if (unit) {
-                       pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);
-               } else {
-                       pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);
-               }
-       }
-       
-       pci_write_config_byte(dev, port, s_clc);
-       pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
-       local_irq_restore(flags);
+       ali_fifo_control(hwif, drive, (drive->media == ide_disk) ? 0x05 : 0x00);
+
+       ali_program_timings(hwif, drive, &t, 0);
 }
 
 /**
@@ -132,44 +155,42 @@ static u8 ali_udma_filter(ide_drive_t *drive)
 
 /**
  *     ali_set_dma_mode        -       set host controller for DMA mode
+ *     @hwif: port
  *     @drive: drive
- *     @speed: DMA mode
  *
  *     Configure the hardware for the desired IDE transfer mode.
  */
 
-static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void ali_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
+       static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 speed1               = speed;
-       u8 unit                 = drive->dn & 1;
+       ide_drive_t *pair       = ide_get_pair_dev(drive);
+       int bus_speed           = ide_pci_clk ? ide_pci_clk : 33;
+       unsigned long T         =  1000000 / bus_speed; /* PCI clock based */
+       const u8 speed          = drive->dma_mode;
        u8 tmpbyte              = 0x00;
-       int m5229_udma          = (hwif->channel) ? 0x57 : 0x56;
-
-       if (speed == XFER_UDMA_6)
-               speed1 = 0x47;
+       struct ide_timing t;
 
        if (speed < XFER_UDMA_0) {
-               u8 ultra_enable = (unit) ? 0x7f : 0xf7;
-               /*
-                * clear "ultra enable" bit
-                */
-               pci_read_config_byte(dev, m5229_udma, &tmpbyte);
-               tmpbyte &= ultra_enable;
-               pci_write_config_byte(dev, m5229_udma, tmpbyte);
-
-               /*
-                * FIXME: Oh, my... DMA timings are never set.
-                */
+               ide_timing_compute(drive, drive->dma_mode, &t, T, 1);
+               if (pair) {
+                       struct ide_timing p;
+
+                       ide_timing_compute(pair, pair->pio_mode, &p, T, 1);
+                       ide_timing_merge(&p, &t, &t,
+                               IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+                       if (pair->dma_mode) {
+                               ide_timing_compute(pair, pair->dma_mode,
+                                               &p, T, 1);
+                               ide_timing_merge(&p, &t, &t,
+                                       IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+                       }
+               }
+               ali_program_timings(hwif, drive, &t, 0);
        } else {
-               pci_read_config_byte(dev, m5229_udma, &tmpbyte);
-               tmpbyte &= (0x0f << ((1-unit) << 2));
-               /*
-                * enable ultra dma and set timing
-                */
-               tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2));
-               pci_write_config_byte(dev, m5229_udma, tmpbyte);
+               ali_program_timings(hwif, drive, NULL,
+                               udma_timing[speed - XFER_UDMA_0]);
                if (speed >= XFER_UDMA_3) {
                        pci_read_config_byte(dev, 0x4b, &tmpbyte);
                        tmpbyte |= 1;
@@ -355,19 +376,13 @@ static int ali_cable_override(struct pci_dev *pdev)
  *
  *     This checks if the controller and the cable are capable
  *     of UDMA66 transfers. It doesn't check the drives.
- *     But see note 2 below!
- *
- *     FIXME: frobs bits that are not defined on newer ALi devicea
  */
 
 static u8 ali_cable_detect(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned long flags;
        u8 cbl = ATA_CBL_PATA40, tmpbyte;
 
-       local_irq_save(flags);
-
        if (m5229_revision >= 0xC2) {
                /*
                 * m5229 80-pin cable detection (from Host View)
@@ -387,8 +402,6 @@ static u8 ali_cable_detect(ide_hwif_t *hwif)
                }
        }
 
-       local_irq_restore(flags);
-
        return cbl;
 }
 
@@ -584,6 +597,6 @@ static void __exit ali15x3_ide_exit(void)
 module_init(ali15x3_ide_init);
 module_exit(ali15x3_ide_exit);
 
-MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
+MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
 MODULE_LICENSE("GPL");