diff options
author | JosephChan@via.com.tw <JosephChan@via.com.tw> | 2008-07-30 15:32:48 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-07-31 01:39:31 -0400 |
commit | bfce5e0179ad059035df28558724ff60af708e09 (patch) | |
tree | 0b00598e38e57559f48983ee22039e589278fbcb /drivers/ata/pata_via.c | |
parent | e8389f0c44652ee63d95bc0a7f8d565ac25dac77 (diff) |
pata_via: add VX800 flag; add function for fixing h/w bugs
Add flag VIA_SATA_PATA for vx800, VX800 uses the same
chipset(0x0581/0x5324) as CX700, which has 1 PATA channel(Master/Slave)
and 1 SATA channel(Master/Slave) Add function <via_ata_tf_load>. This is
to fix the internal bug of VIA chipsets, which will reset the device
register after changing the IEN bit in CTL register
Signed-off-by: Joseph Chan <josephchan@via.com.tw>
Cc: Tejun Heo <tj@kernel.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_via.c')
-rw-r--r-- | drivers/ata/pata_via.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 708ed144ede9..57d951b11f2d 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c | |||
@@ -98,7 +98,8 @@ static const struct via_isa_bridge { | |||
98 | u8 rev_max; | 98 | u8 rev_max; |
99 | u16 flags; | 99 | u16 flags; |
100 | } via_isa_bridges[] = { | 100 | } via_isa_bridges[] = { |
101 | { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 101 | { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, VIA_UDMA_133 | |
102 | VIA_BAD_AST | VIA_SATA_PATA }, | ||
102 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 103 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
103 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 104 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
104 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA }, | 105 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA }, |
@@ -322,6 +323,65 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
322 | via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); | 323 | via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); |
323 | } | 324 | } |
324 | 325 | ||
326 | /** | ||
327 | * via_ata_sff_tf_load - send taskfile registers to host controller | ||
328 | * @ap: Port to which output is sent | ||
329 | * @tf: ATA taskfile register set | ||
330 | * | ||
331 | * Outputs ATA taskfile to standard ATA host controller. | ||
332 | * | ||
333 | * Note: This is to fix the internal bug of via chipsets, which | ||
334 | * will reset the device register after changing the IEN bit on | ||
335 | * ctl register | ||
336 | */ | ||
337 | static void via_ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) | ||
338 | { | ||
339 | struct ata_ioports *ioaddr = &ap->ioaddr; | ||
340 | unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; | ||
341 | |||
342 | if (tf->ctl != ap->last_ctl) { | ||
343 | iowrite8(tf->ctl, ioaddr->ctl_addr); | ||
344 | iowrite8(tf->device, ioaddr->device_addr); | ||
345 | ap->last_ctl = tf->ctl; | ||
346 | ata_wait_idle(ap); | ||
347 | } | ||
348 | |||
349 | if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { | ||
350 | iowrite8(tf->hob_feature, ioaddr->feature_addr); | ||
351 | iowrite8(tf->hob_nsect, ioaddr->nsect_addr); | ||
352 | iowrite8(tf->hob_lbal, ioaddr->lbal_addr); | ||
353 | iowrite8(tf->hob_lbam, ioaddr->lbam_addr); | ||
354 | iowrite8(tf->hob_lbah, ioaddr->lbah_addr); | ||
355 | VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", | ||
356 | tf->hob_feature, | ||
357 | tf->hob_nsect, | ||
358 | tf->hob_lbal, | ||
359 | tf->hob_lbam, | ||
360 | tf->hob_lbah); | ||
361 | } | ||
362 | |||
363 | if (is_addr) { | ||
364 | iowrite8(tf->feature, ioaddr->feature_addr); | ||
365 | iowrite8(tf->nsect, ioaddr->nsect_addr); | ||
366 | iowrite8(tf->lbal, ioaddr->lbal_addr); | ||
367 | iowrite8(tf->lbam, ioaddr->lbam_addr); | ||
368 | iowrite8(tf->lbah, ioaddr->lbah_addr); | ||
369 | VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", | ||
370 | tf->feature, | ||
371 | tf->nsect, | ||
372 | tf->lbal, | ||
373 | tf->lbam, | ||
374 | tf->lbah); | ||
375 | } | ||
376 | |||
377 | if (tf->flags & ATA_TFLAG_DEVICE) { | ||
378 | iowrite8(tf->device, ioaddr->device_addr); | ||
379 | VPRINTK("device 0x%X\n", tf->device); | ||
380 | } | ||
381 | |||
382 | ata_wait_idle(ap); | ||
383 | } | ||
384 | |||
325 | static struct scsi_host_template via_sht = { | 385 | static struct scsi_host_template via_sht = { |
326 | ATA_BMDMA_SHT(DRV_NAME), | 386 | ATA_BMDMA_SHT(DRV_NAME), |
327 | }; | 387 | }; |
@@ -332,11 +392,13 @@ static struct ata_port_operations via_port_ops = { | |||
332 | .set_piomode = via_set_piomode, | 392 | .set_piomode = via_set_piomode, |
333 | .set_dmamode = via_set_dmamode, | 393 | .set_dmamode = via_set_dmamode, |
334 | .prereset = via_pre_reset, | 394 | .prereset = via_pre_reset, |
395 | .sff_tf_load = via_ata_tf_load, | ||
335 | }; | 396 | }; |
336 | 397 | ||
337 | static struct ata_port_operations via_port_ops_noirq = { | 398 | static struct ata_port_operations via_port_ops_noirq = { |
338 | .inherits = &via_port_ops, | 399 | .inherits = &via_port_ops, |
339 | .sff_data_xfer = ata_sff_data_xfer_noirq, | 400 | .sff_data_xfer = ata_sff_data_xfer_noirq, |
401 | .sff_tf_load = via_ata_tf_load, | ||
340 | }; | 402 | }; |
341 | 403 | ||
342 | /** | 404 | /** |