From 3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 16 May 2007 00:51:44 +0200 Subject: [PATCH] cs5530/sc1200: add ->speedproc support * add {cs5530,sc1200}_tunepio() for programming PIO timings * add {cs5530,sc1200}_tune_chipset() (->speedproc method) for setting transfer mode and convert {cs5530,sc1200}_config_dma() to use it * bump driver version Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/cs5530.c | 59 +++++++++++++++++++++------------ drivers/ide/pci/sc1200.c | 70 ++++++++++++++++++++++++---------------- 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index ec52dbec675f..aacb79b4a9cd 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/cs5530.c Version 0.72 Mar 10 2007 + * linux/drivers/ide/pci/cs5530.c Version 0.73 Mar 10 2007 * * Copyright (C) 2000 Andre Hedrick * Copyright (C) 2000 Mark Lord @@ -62,6 +62,14 @@ static unsigned int cs5530_pio_timings[2][5] = { #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) #define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) +static void cs5530_tunepio(ide_drive_t *drive, u8 pio) +{ + unsigned long basereg = CS5530_BASEREG(drive->hwif); + unsigned int format = (inl(basereg + 4) >> 31) & 1; + + outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3)); +} + /** * cs5530_tuneproc - select/set PIO modes * @@ -74,17 +82,10 @@ static unsigned int cs5530_pio_timings[2][5] = { static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ { - ide_hwif_t *hwif = HWIF(drive); - unsigned int format; - unsigned long basereg = CS5530_BASEREG(hwif); - static u8 modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - if (!cs5530_set_xfer_mode(drive, modes[pio])) { - format = (inl(basereg + 4) >> 31) & 1; - outl(cs5530_pio_timings[format][pio], - basereg+(drive->select.b.unit<<3)); - } + + if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0) + cs5530_tunepio(drive, pio); } /** @@ -136,18 +137,27 @@ static u8 cs5530_udma_filter(ide_drive_t *drive) static int cs5530_config_dma(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - unsigned int reg, timings = 0; - unsigned long basereg; - u8 unit = drive->dn & 1, mode = 0; + if (ide_use_dma(drive)) { + u8 mode = ide_max_dma_mode(drive); - if (ide_use_dma(drive)) - mode = ide_max_dma_mode(drive); + if (mode && drive->hwif->speedproc(drive, mode) == 0) + return 0; + } + + return 1; +} + +static int cs5530_tune_chipset(ide_drive_t *drive, u8 mode) +{ + unsigned long basereg; + unsigned int reg, timings = 0; + + mode = ide_rate_filter(drive, mode); /* * Tell the drive to switch to the new mode; abort on failure. */ - if (!mode || cs5530_set_xfer_mode(drive, mode)) + if (cs5530_set_xfer_mode(drive, mode)) return 1; /* failure */ /* @@ -160,14 +170,21 @@ static int cs5530_config_dma(ide_drive_t *drive) case XFER_MW_DMA_0: timings = 0x00077771; break; case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_2: timings = 0x00002020; break; + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + cs5530_tunepio(drive, mode - XFER_PIO_0); + return 0; default: BUG(); break; } - basereg = CS5530_BASEREG(hwif); + basereg = CS5530_BASEREG(drive->hwif); reg = inl(basereg + 4); /* get drive0 config register */ timings |= reg & 0x80000000; /* preserve PIO format bit */ - if (unit == 0) { /* are we configuring drive0? */ + if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */ outl(timings, basereg + 4); /* write drive0 config register */ } else { if (timings & 0x00100000) @@ -293,6 +310,8 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) hwif->serialized = hwif->mate->serialized = 1; hwif->tuneproc = &cs5530_tuneproc; + hwif->speedproc = &cs5530_tune_chipset; + basereg = CS5530_BASEREG(hwif); d0_timings = inl(basereg + 0); if (CS5530_BAD_PIO(d0_timings)) { diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 65dcabe48205..c989fd90f377 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/sc1200.c Version 0.93 Mar 10 2007 + * linux/drivers/ide/pci/sc1200.c Version 0.94 Mar 10 2007 * * Copyright (C) 2000-2002 Mark Lord * Copyright (C) 2007 Bartlomiej Zolnierkiewicz @@ -95,6 +95,20 @@ static const unsigned int sc1200_pio_timings[4][5] = */ //#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) +static void sc1200_tunepio(ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *pdev = hwif->pci_dev; + unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; + + pci_read_config_dword(pdev, basereg + 4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3), + sc1200_pio_timings[format][pio]); +} + /* * The SC1200 specifies that two drives sharing a cable cannot mix * UDMA/MDMA. It has to be one or the other, for the pair, though @@ -124,11 +138,7 @@ static u8 sc1200_udma_filter(ide_drive_t *drive) return mask; } -/* - * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes - * for both the chipset and drive. - */ -static int sc1200_config_dma2 (ide_drive_t *drive, int mode) +static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode) { ide_hwif_t *hwif = HWIF(drive); int unit = drive->select.b.unit; @@ -136,14 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) unsigned short pci_clock; unsigned int basereg = hwif->channel ? 0x50 : 0x40; + mode = ide_rate_filter(drive, mode); + /* * Tell the drive to switch to the new mode; abort on failure. */ - if (!mode || sc1200_set_xfer_mode(drive, mode)) { + if (sc1200_set_xfer_mode(drive, mode)) { printk("SC1200: set xfer mode failure\n"); return 1; /* failure */ } + switch (mode) { + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + sc1200_tunepio(drive, mode - XFER_PIO_0); + return 0; + } + pci_clock = sc1200_get_pci_clock(); /* @@ -196,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) case PCI_CLK_66: timings = 0x00015151; break; } break; - } - - if (timings == 0) { - printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock); - return 1; /* failure */ + default: + BUG(); + break; } if (unit == 0) { /* are we configuring drive0? */ @@ -220,12 +240,14 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) */ static int sc1200_config_dma (ide_drive_t *drive) { - u8 mode = 0; + if (ide_use_dma(drive)) { + u8 mode = ide_max_dma_mode(drive); - if (ide_use_dma(drive)) - mode = ide_max_dma_mode(drive); + if (mode && drive->hwif->speedproc(drive, mode) == 0) + return 0; + } - return sc1200_config_dma2(drive, mode); + return 1; } @@ -265,8 +287,6 @@ static int sc1200_ide_dma_end (ide_drive_t *drive) static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ { ide_hwif_t *hwif = HWIF(drive); - unsigned int format; - static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; int mode = -1; /* @@ -283,21 +303,16 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au if (mode != -1) { printk("SC1200: %s: changing (U)DMA mode\n", drive->name); hwif->dma_off_quietly(drive); - if (sc1200_config_dma2(drive, mode) == 0) + if (sc1200_tune_chipset(drive, mode) == 0) hwif->dma_host_on(drive); return; } pio = ide_get_best_pio_mode(drive, pio, 4, NULL); printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); - if (!sc1200_set_xfer_mode(drive, modes[pio])) { - unsigned int basereg = hwif->channel ? 0x50 : 0x40; - pci_read_config_dword (hwif->pci_dev, basereg+4, &format); - format = (format >> 31) & 1; - if (format) - format += sc1200_get_pci_clock(); - pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]); - } + + if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0) + sc1200_tunepio(drive, pio); } #ifdef CONFIG_PM @@ -447,6 +462,7 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->tuneproc = &sc1200_tuneproc; + hwif->speedproc = &sc1200_tune_chipset; } hwif->atapi_dma = 1; hwif->ultra_mask = 0x07;