mirror of https://gitee.com/openkylin/linux.git
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 <bzolnier@gmail.com>
This commit is contained in:
parent
a01ba4011a
commit
3c3f5d2c9f
|
@ -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 <andre@linux-ide.org>
|
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
|
||||||
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
|
* Copyright (C) 2000 Mark Lord <mlord@pobox.com>
|
||||||
|
@ -62,6 +62,14 @@ static unsigned int cs5530_pio_timings[2][5] = {
|
||||||
#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
|
#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
|
||||||
#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
|
#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
|
* 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" */
|
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);
|
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
|
||||||
if (!cs5530_set_xfer_mode(drive, modes[pio])) {
|
|
||||||
format = (inl(basereg + 4) >> 31) & 1;
|
if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
|
||||||
outl(cs5530_pio_timings[format][pio],
|
cs5530_tunepio(drive, pio);
|
||||||
basereg+(drive->select.b.unit<<3));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,18 +137,27 @@ static u8 cs5530_udma_filter(ide_drive_t *drive)
|
||||||
|
|
||||||
static int cs5530_config_dma(ide_drive_t *drive)
|
static int cs5530_config_dma(ide_drive_t *drive)
|
||||||
{
|
{
|
||||||
ide_hwif_t *hwif = drive->hwif;
|
if (ide_use_dma(drive)) {
|
||||||
unsigned int reg, timings = 0;
|
u8 mode = ide_max_dma_mode(drive);
|
||||||
unsigned long basereg;
|
|
||||||
u8 unit = drive->dn & 1, mode = 0;
|
|
||||||
|
|
||||||
if (ide_use_dma(drive))
|
if (mode && drive->hwif->speedproc(drive, mode) == 0)
|
||||||
mode = ide_max_dma_mode(drive);
|
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.
|
* 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 */
|
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_0: timings = 0x00077771; break;
|
||||||
case XFER_MW_DMA_1: timings = 0x00012121; break;
|
case XFER_MW_DMA_1: timings = 0x00012121; break;
|
||||||
case XFER_MW_DMA_2: timings = 0x00002020; 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:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
basereg = CS5530_BASEREG(hwif);
|
basereg = CS5530_BASEREG(drive->hwif);
|
||||||
reg = inl(basereg + 4); /* get drive0 config register */
|
reg = inl(basereg + 4); /* get drive0 config register */
|
||||||
timings |= reg & 0x80000000; /* preserve PIO format bit */
|
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 */
|
outl(timings, basereg + 4); /* write drive0 config register */
|
||||||
} else {
|
} else {
|
||||||
if (timings & 0x00100000)
|
if (timings & 0x00100000)
|
||||||
|
@ -293,6 +310,8 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
|
||||||
hwif->serialized = hwif->mate->serialized = 1;
|
hwif->serialized = hwif->mate->serialized = 1;
|
||||||
|
|
||||||
hwif->tuneproc = &cs5530_tuneproc;
|
hwif->tuneproc = &cs5530_tuneproc;
|
||||||
|
hwif->speedproc = &cs5530_tune_chipset;
|
||||||
|
|
||||||
basereg = CS5530_BASEREG(hwif);
|
basereg = CS5530_BASEREG(hwif);
|
||||||
d0_timings = inl(basereg + 0);
|
d0_timings = inl(basereg + 0);
|
||||||
if (CS5530_BAD_PIO(d0_timings)) {
|
if (CS5530_BAD_PIO(d0_timings)) {
|
||||||
|
|
|
@ -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 <mlord@pobox.com>
|
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
|
||||||
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
|
* 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)
|
//#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
|
* 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
|
* 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;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
ide_hwif_t *hwif = HWIF(drive);
|
ide_hwif_t *hwif = HWIF(drive);
|
||||||
int unit = drive->select.b.unit;
|
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 short pci_clock;
|
||||||
unsigned int basereg = hwif->channel ? 0x50 : 0x40;
|
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.
|
* 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");
|
printk("SC1200: set xfer mode failure\n");
|
||||||
return 1; /* failure */
|
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();
|
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;
|
case PCI_CLK_66: timings = 0x00015151; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
BUG();
|
||||||
if (timings == 0) {
|
break;
|
||||||
printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock);
|
|
||||||
return 1; /* failure */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unit == 0) { /* are we configuring drive0? */
|
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)
|
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))
|
if (mode && drive->hwif->speedproc(drive, mode) == 0)
|
||||||
mode = ide_max_dma_mode(drive);
|
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" */
|
static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */
|
||||||
{
|
{
|
||||||
ide_hwif_t *hwif = HWIF(drive);
|
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;
|
int mode = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -283,21 +303,16 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au
|
||||||
if (mode != -1) {
|
if (mode != -1) {
|
||||||
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
|
printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
|
||||||
hwif->dma_off_quietly(drive);
|
hwif->dma_off_quietly(drive);
|
||||||
if (sc1200_config_dma2(drive, mode) == 0)
|
if (sc1200_tune_chipset(drive, mode) == 0)
|
||||||
hwif->dma_host_on(drive);
|
hwif->dma_host_on(drive);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
|
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
|
||||||
printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio);
|
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;
|
if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
|
||||||
pci_read_config_dword (hwif->pci_dev, basereg+4, &format);
|
sc1200_tunepio(drive, pio);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
@ -447,6 +462,7 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
|
||||||
if (!noautodma)
|
if (!noautodma)
|
||||||
hwif->autodma = 1;
|
hwif->autodma = 1;
|
||||||
hwif->tuneproc = &sc1200_tuneproc;
|
hwif->tuneproc = &sc1200_tuneproc;
|
||||||
|
hwif->speedproc = &sc1200_tune_chipset;
|
||||||
}
|
}
|
||||||
hwif->atapi_dma = 1;
|
hwif->atapi_dma = 1;
|
||||||
hwif->ultra_mask = 0x07;
|
hwif->ultra_mask = 0x07;
|
||||||
|
|
Loading…
Reference in New Issue