sis5513: DMA setup fixes

* Add sis_ata133_get_base() helper function for obtaining the address of
  the drive control registers on chipset_family == ATA_133 chipsets.

* Add three helper functions for programming PIO/MWDMA timings:
  - sis_ata16_program_timings()  (for ATA_16/33/66/100a chipset families)
  - sis_ata100_program_timings() (for ATA_100/133a chipset families)
  - sis_ata133_program_timings() (for ATA_133 chipset family)

  MWDMA timings are taken from datasheets and they match ATA spec.

* Add generic helper function sis_program_timings() and use it in
  ->set_pio_mode and ->set_dma_mode methods (previously the driver
  depended on BIOS to program the correct MWDMA timings).

* Remove redundant !chipset_family check from init_hwif_sis5513()
  (init_chipset_sis5513() guarantees that we will never get here if
   chipset_family cannot be determined).

* SWDMA seems to be unsupported by SiS chipsets (no info about SWDMA in
  datasheets and for SWDMA0 mode timing requirements are impossible to
  fulfill) so remove ->swdma_mask from init_hwif_sis5513() and handling
  of SWDMA modes from sis_set_dma_mode().

* Enable DMA support for chipset_family == ATA_16.

* Bump driver version.
Acked-by: NSergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: NBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
上级 a29ec3b2
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
/* /*
* linux/drivers/ide/pci/sis5513.c Version 0.27 Jul 14, 2007 * linux/drivers/ide/pci/sis5513.c Version 0.28 Aug 1, 2007
* *
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
...@@ -433,6 +433,95 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -433,6 +433,95 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
/* /*
* Configuration functions * Configuration functions
*/ */
static u8 sis_ata133_get_base(ide_drive_t *drive)
{
struct pci_dev *dev = drive->hwif->pci_dev;
u32 reg54 = 0;
pci_read_config_dword(dev, 0x54, &reg54);
return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
}
static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
{
struct pci_dev *dev = drive->hwif->pci_dev;
u16 t1 = 0;
u8 drive_pci = 0x40 + drive->dn * 2;
const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 };
const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 };
pci_read_config_word(dev, drive_pci, &t1);
/* clear active/recovery timings */
t1 &= ~0x070f;
if (mode >= XFER_MW_DMA_0) {
if (chipset_family > ATA_16)
t1 &= ~0x8000; /* disable UDMA */
t1 |= mwdma_timings[mode - XFER_MW_DMA_0];
} else
t1 |= pio_timings[mode - XFER_PIO_0];
pci_write_config_word(dev, drive_pci, t1);
}
static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
{
struct pci_dev *dev = drive->hwif->pci_dev;
u8 t1, drive_pci = 0x40 + drive->dn * 2;
/* timing bits: 7:4 active 3:0 recovery */
const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 };
if (mode >= XFER_MW_DMA_0) {
u8 t2 = 0;
pci_read_config_byte(dev, drive_pci, &t2);
t2 &= ~0x80; /* disable UDMA */
pci_write_config_byte(dev, drive_pci, t2);
t1 = mwdma_timings[mode - XFER_MW_DMA_0];
} else
t1 = pio_timings[mode - XFER_PIO_0];
pci_write_config_byte(dev, drive_pci + 1, t1);
}
static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
{
struct pci_dev *dev = drive->hwif->pci_dev;
u32 t1 = 0;
u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
pci_read_config_dword(dev, drive_pci, &t1);
t1 &= 0xc0c00fff;
clk = (t1 & 0x08) ? ATA_133 : ATA_100;
if (mode >= XFER_MW_DMA_0) {
t1 &= ~0x04; /* disable UDMA */
idx = mode - XFER_MW_DMA_0 + 5;
}
idx = mode - XFER_PIO_0;
t1 |= ini_time_value[clk][idx] << 12;
t1 |= act_time_value[clk][idx] << 16;
t1 |= rco_time_value[clk][idx] << 24;
pci_write_config_dword(dev, drive_pci, t1);
}
static void sis_program_timings(ide_drive_t *drive, const u8 mode)
{
if (chipset_family < ATA_100) /* ATA_16/33/66/100a */
sis_ata16_program_timings(drive, mode);
else if (chipset_family < ATA_133) /* ATA_100/133a */
sis_ata100_program_timings(drive, mode);
else /* ATA_133 */
sis_ata133_program_timings(drive, mode);
}
/* Enables per-drive prefetch and postwrite */ /* Enables per-drive prefetch and postwrite */
static void config_drive_art_rwp (ide_drive_t *drive) static void config_drive_art_rwp (ide_drive_t *drive)
{ {
...@@ -450,105 +539,16 @@ static void config_drive_art_rwp (ide_drive_t *drive) ...@@ -450,105 +539,16 @@ static void config_drive_art_rwp (ide_drive_t *drive)
pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
} }
/* Set per-drive active and recovery time */
static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
{ {
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u8 drive_pci, test1, test2;
config_drive_art_rwp(drive); config_drive_art_rwp(drive);
sis_program_timings(drive, XFER_PIO_0 + pio);
/* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */
drive_pci = 0x40;
/* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */
if (chipset_family >= ATA_133) {
u32 reg54h;
pci_read_config_dword(dev, 0x54, &reg54h);
if (reg54h & 0x40000000) drive_pci = 0x70;
drive_pci += ((drive->dn)*0x4);
} else {
drive_pci += ((drive->dn)*0x2);
}
/* register layout changed with newer ATA100 chips */
if (chipset_family < ATA_100) {
pci_read_config_byte(dev, drive_pci, &test1);
pci_read_config_byte(dev, drive_pci+1, &test2);
/* Clear active and recovery timings */
test1 &= ~0x0F;
test2 &= ~0x07;
switch(pio) {
case 4: test1 |= 0x01; test2 |= 0x03; break;
case 3: test1 |= 0x03; test2 |= 0x03; break;
case 2: test1 |= 0x04; test2 |= 0x04; break;
case 1: test1 |= 0x07; test2 |= 0x06; break;
case 0: /* PIO0: register setting == X000 */
default: break;
}
pci_write_config_byte(dev, drive_pci, test1);
pci_write_config_byte(dev, drive_pci+1, test2);
} else if (chipset_family < ATA_133) {
switch(pio) { /* active recovery
v v */
case 4: test1 = 0x30|0x01; break;
case 3: test1 = 0x30|0x03; break;
case 2: test1 = 0x40|0x04; break;
case 1: test1 = 0x60|0x07; break;
case 0: test1 = 0x00; break;
default: break;
}
pci_write_config_byte(dev, drive_pci, test1);
} else { /* ATA_133 */
u32 test3;
pci_read_config_dword(dev, drive_pci, &test3);
test3 &= 0xc0c00fff;
if (test3 & 0x08) {
test3 |= ini_time_value[ATA_133][pio] << 12;
test3 |= act_time_value[ATA_133][pio] << 16;
test3 |= rco_time_value[ATA_133][pio] << 24;
} else {
test3 |= ini_time_value[ATA_100][pio] << 12;
test3 |= act_time_value[ATA_100][pio] << 16;
test3 |= rco_time_value[ATA_100][pio] << 24;
}
pci_write_config_dword(dev, drive_pci, test3);
}
} }
static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
u32 regdw;
u8 drive_pci, reg;
/* See sis_set_pio_mode() for drive PCI config registers */
drive_pci = 0x40;
if (chipset_family >= ATA_133) {
u32 reg54h;
pci_read_config_dword(dev, 0x54, &reg54h);
if (reg54h & 0x40000000) drive_pci = 0x70;
drive_pci += ((drive->dn)*0x4);
pci_read_config_dword(dev, (unsigned long)drive_pci, &regdw);
/* Disable UDMA bit for non UDMA modes on UDMA chips */
if (speed < XFER_UDMA_0) {
regdw &= 0xfffffffb;
pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
}
} else {
drive_pci += ((drive->dn)*0x2);
pci_read_config_byte(dev, drive_pci+1, &reg);
/* Disable UDMA bit for non UDMA modes on UDMA chips */
if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
reg &= 0x7F;
pci_write_config_byte(dev, drive_pci+1, reg);
}
}
/* Config chip for mode */ /* Config chip for mode */
switch(speed) { switch(speed) {
...@@ -560,6 +560,10 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) ...@@ -560,6 +560,10 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
case XFER_UDMA_1: case XFER_UDMA_1:
case XFER_UDMA_0: case XFER_UDMA_0:
if (chipset_family >= ATA_133) { if (chipset_family >= ATA_133) {
u32 regdw = 0;
u8 drive_pci = sis_ata133_get_base(drive);
pci_read_config_dword(dev, drive_pci, &regdw);
regdw |= 0x04; regdw |= 0x04;
regdw &= 0xfffff00f; regdw &= 0xfffff00f;
/* check if ATA133 enable */ /* check if ATA133 enable */
...@@ -572,6 +576,9 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) ...@@ -572,6 +576,9 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
} }
pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
} else { } else {
u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
pci_read_config_byte(dev, drive_pci+1, &reg);
/* Force the UDMA bit on if we want to use UDMA */ /* Force the UDMA bit on if we want to use UDMA */
reg |= 0x80; reg |= 0x80;
/* clean reg cycle time bits */ /* clean reg cycle time bits */
...@@ -586,9 +593,7 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) ...@@ -586,9 +593,7 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
case XFER_MW_DMA_2: case XFER_MW_DMA_2:
case XFER_MW_DMA_1: case XFER_MW_DMA_1:
case XFER_MW_DMA_0: case XFER_MW_DMA_0:
case XFER_SW_DMA_2: sis_program_timings(drive, speed);
case XFER_SW_DMA_1:
case XFER_SW_DMA_0:
break; break;
default: default:
BUG(); BUG();
...@@ -617,11 +622,9 @@ static int sis5513_config_xfer_rate(ide_drive_t *drive) ...@@ -617,11 +622,9 @@ static int sis5513_config_xfer_rate(ide_drive_t *drive)
static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
{ {
struct pci_dev *dev = drive->hwif->pci_dev; struct pci_dev *dev = drive->hwif->pci_dev;
int drive_pci; u32 regdw = 0;
u32 reg54 = 0, regdw = 0; u8 drive_pci = sis_ata133_get_base(drive);
pci_read_config_dword(dev, 0x54, &reg54);
drive_pci = ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
pci_read_config_dword(dev, drive_pci, &regdw); pci_read_config_dword(dev, drive_pci, &regdw);
/* if ATA133 disable, we should not set speed above UDMA5 */ /* if ATA133 disable, we should not set speed above UDMA5 */
...@@ -848,22 +851,17 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) ...@@ -848,22 +851,17 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
hwif->ultra_mask = udma_rates[chipset_family]; hwif->ultra_mask = udma_rates[chipset_family];
hwif->mwdma_mask = 0x07; hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
if (!chipset_family)
return;
if (hwif->cbl != ATA_CBL_PATA40_SHORT) if (hwif->cbl != ATA_CBL_PATA40_SHORT)
hwif->cbl = ata66_sis5513(hwif); hwif->cbl = ata66_sis5513(hwif);
if (chipset_family > ATA_16) { hwif->ide_dma_check = &sis5513_config_xfer_rate;
hwif->ide_dma_check = &sis5513_config_xfer_rate;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
}
hwif->drives[0].autodma = hwif->autodma; hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma;
return;
} }
static ide_pci_device_t sis5513_chipset __devinitdata = { static ide_pci_device_t sis5513_chipset __devinitdata = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部