diff options
Diffstat (limited to 'drivers/ata/pata_via.c')
-rw-r--r-- | drivers/ata/pata_via.c | 109 |
1 files changed, 84 insertions, 25 deletions
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index c5f1616d224d..cc09d47fb927 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * VIA VT8233c - UDMA100 | 23 | * VIA VT8233c - UDMA100 |
24 | * VIA VT8235 - UDMA133 | 24 | * VIA VT8235 - UDMA133 |
25 | * VIA VT8237 - UDMA133 | 25 | * VIA VT8237 - UDMA133 |
26 | * VIA VT8251 - UDMA133 | ||
26 | * | 27 | * |
27 | * Most registers remain compatible across chips. Others start reserved | 28 | * Most registers remain compatible across chips. Others start reserved |
28 | * and acquire sensible semantics if set to 1 (eg cable detect). A few | 29 | * and acquire sensible semantics if set to 1 (eg cable detect). A few |
@@ -60,7 +61,7 @@ | |||
60 | #include <linux/libata.h> | 61 | #include <linux/libata.h> |
61 | 62 | ||
62 | #define DRV_NAME "pata_via" | 63 | #define DRV_NAME "pata_via" |
63 | #define DRV_VERSION "0.1.14" | 64 | #define DRV_VERSION "0.2.0" |
64 | 65 | ||
65 | /* | 66 | /* |
66 | * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx | 67 | * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx |
@@ -94,6 +95,7 @@ static const struct via_isa_bridge { | |||
94 | u8 rev_max; | 95 | u8 rev_max; |
95 | u16 flags; | 96 | u16 flags; |
96 | } via_isa_bridges[] = { | 97 | } via_isa_bridges[] = { |
98 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | ||
97 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 99 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
98 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, | 100 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, |
99 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 101 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
@@ -288,7 +290,6 @@ static struct scsi_host_template via_sht = { | |||
288 | .can_queue = ATA_DEF_QUEUE, | 290 | .can_queue = ATA_DEF_QUEUE, |
289 | .this_id = ATA_SHT_THIS_ID, | 291 | .this_id = ATA_SHT_THIS_ID, |
290 | .sg_tablesize = LIBATA_MAX_PRD, | 292 | .sg_tablesize = LIBATA_MAX_PRD, |
291 | .max_sectors = ATA_MAX_SECTORS, | ||
292 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 293 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
293 | .emulated = ATA_SHT_EMULATED, | 294 | .emulated = ATA_SHT_EMULATED, |
294 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 295 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
@@ -297,6 +298,8 @@ static struct scsi_host_template via_sht = { | |||
297 | .slave_configure = ata_scsi_slave_config, | 298 | .slave_configure = ata_scsi_slave_config, |
298 | .slave_destroy = ata_scsi_slave_destroy, | 299 | .slave_destroy = ata_scsi_slave_destroy, |
299 | .bios_param = ata_std_bios_param, | 300 | .bios_param = ata_std_bios_param, |
301 | .resume = ata_scsi_device_resume, | ||
302 | .suspend = ata_scsi_device_suspend, | ||
300 | }; | 303 | }; |
301 | 304 | ||
302 | static struct ata_port_operations via_port_ops = { | 305 | static struct ata_port_operations via_port_ops = { |
@@ -370,8 +373,42 @@ static struct ata_port_operations via_port_ops_noirq = { | |||
370 | }; | 373 | }; |
371 | 374 | ||
372 | /** | 375 | /** |
376 | * via_config_fifo - set up the FIFO | ||
377 | * @pdev: PCI device | ||
378 | * @flags: configuration flags | ||
379 | * | ||
380 | * Set the FIFO properties for this device if neccessary. Used both on | ||
381 | * set up and on and the resume path | ||
382 | */ | ||
383 | |||
384 | static void via_config_fifo(struct pci_dev *pdev, unsigned int flags) | ||
385 | { | ||
386 | u8 enable; | ||
387 | |||
388 | /* 0x40 low bits indicate enabled channels */ | ||
389 | pci_read_config_byte(pdev, 0x40 , &enable); | ||
390 | enable &= 3; | ||
391 | |||
392 | if (flags & VIA_SET_FIFO) { | ||
393 | u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; | ||
394 | u8 fifo; | ||
395 | |||
396 | pci_read_config_byte(pdev, 0x43, &fifo); | ||
397 | |||
398 | /* Clear PREQ# until DDACK# for errata */ | ||
399 | if (flags & VIA_BAD_PREQ) | ||
400 | fifo &= 0x7F; | ||
401 | else | ||
402 | fifo &= 0x9f; | ||
403 | /* Turn on FIFO for enabled channels */ | ||
404 | fifo |= fifo_setting[enable]; | ||
405 | pci_write_config_byte(pdev, 0x43, fifo); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | /** | ||
373 | * via_init_one - discovery callback | 410 | * via_init_one - discovery callback |
374 | * @pdev: PCI device ID | 411 | * @pdev: PCI device |
375 | * @id: PCI table info | 412 | * @id: PCI table info |
376 | * | 413 | * |
377 | * A VIA IDE interface has been discovered. Figure out what revision | 414 | * A VIA IDE interface has been discovered. Figure out what revision |
@@ -383,7 +420,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
383 | /* Early VIA without UDMA support */ | 420 | /* Early VIA without UDMA support */ |
384 | static struct ata_port_info via_mwdma_info = { | 421 | static struct ata_port_info via_mwdma_info = { |
385 | .sht = &via_sht, | 422 | .sht = &via_sht, |
386 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 423 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
387 | .pio_mask = 0x1f, | 424 | .pio_mask = 0x1f, |
388 | .mwdma_mask = 0x07, | 425 | .mwdma_mask = 0x07, |
389 | .port_ops = &via_port_ops | 426 | .port_ops = &via_port_ops |
@@ -391,7 +428,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
391 | /* Ditto with IRQ masking required */ | 428 | /* Ditto with IRQ masking required */ |
392 | static struct ata_port_info via_mwdma_info_borked = { | 429 | static struct ata_port_info via_mwdma_info_borked = { |
393 | .sht = &via_sht, | 430 | .sht = &via_sht, |
394 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 431 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
395 | .pio_mask = 0x1f, | 432 | .pio_mask = 0x1f, |
396 | .mwdma_mask = 0x07, | 433 | .mwdma_mask = 0x07, |
397 | .port_ops = &via_port_ops_noirq, | 434 | .port_ops = &via_port_ops_noirq, |
@@ -399,7 +436,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
399 | /* VIA UDMA 33 devices (and borked 66) */ | 436 | /* VIA UDMA 33 devices (and borked 66) */ |
400 | static struct ata_port_info via_udma33_info = { | 437 | static struct ata_port_info via_udma33_info = { |
401 | .sht = &via_sht, | 438 | .sht = &via_sht, |
402 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 439 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
403 | .pio_mask = 0x1f, | 440 | .pio_mask = 0x1f, |
404 | .mwdma_mask = 0x07, | 441 | .mwdma_mask = 0x07, |
405 | .udma_mask = 0x7, | 442 | .udma_mask = 0x7, |
@@ -408,7 +445,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
408 | /* VIA UDMA 66 devices */ | 445 | /* VIA UDMA 66 devices */ |
409 | static struct ata_port_info via_udma66_info = { | 446 | static struct ata_port_info via_udma66_info = { |
410 | .sht = &via_sht, | 447 | .sht = &via_sht, |
411 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 448 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
412 | .pio_mask = 0x1f, | 449 | .pio_mask = 0x1f, |
413 | .mwdma_mask = 0x07, | 450 | .mwdma_mask = 0x07, |
414 | .udma_mask = 0x1f, | 451 | .udma_mask = 0x1f, |
@@ -417,7 +454,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
417 | /* VIA UDMA 100 devices */ | 454 | /* VIA UDMA 100 devices */ |
418 | static struct ata_port_info via_udma100_info = { | 455 | static struct ata_port_info via_udma100_info = { |
419 | .sht = &via_sht, | 456 | .sht = &via_sht, |
420 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 457 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
421 | .pio_mask = 0x1f, | 458 | .pio_mask = 0x1f, |
422 | .mwdma_mask = 0x07, | 459 | .mwdma_mask = 0x07, |
423 | .udma_mask = 0x3f, | 460 | .udma_mask = 0x3f, |
@@ -426,7 +463,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
426 | /* UDMA133 with bad AST (All current 133) */ | 463 | /* UDMA133 with bad AST (All current 133) */ |
427 | static struct ata_port_info via_udma133_info = { | 464 | static struct ata_port_info via_udma133_info = { |
428 | .sht = &via_sht, | 465 | .sht = &via_sht, |
429 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 466 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, |
430 | .pio_mask = 0x1f, | 467 | .pio_mask = 0x1f, |
431 | .mwdma_mask = 0x07, | 468 | .mwdma_mask = 0x07, |
432 | .udma_mask = 0x7f, /* FIXME: should check north bridge */ | 469 | .udma_mask = 0x7f, /* FIXME: should check north bridge */ |
@@ -471,21 +508,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
471 | } | 508 | } |
472 | 509 | ||
473 | /* Initialise the FIFO for the enabled channels. */ | 510 | /* Initialise the FIFO for the enabled channels. */ |
474 | if (config->flags & VIA_SET_FIFO) { | 511 | via_config_fifo(pdev, config->flags); |
475 | u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; | 512 | |
476 | u8 fifo; | ||
477 | |||
478 | pci_read_config_byte(pdev, 0x43, &fifo); | ||
479 | |||
480 | /* Clear PREQ# until DDACK# for errata */ | ||
481 | if (config->flags & VIA_BAD_PREQ) | ||
482 | fifo &= 0x7F; | ||
483 | else | ||
484 | fifo &= 0x9f; | ||
485 | /* Turn on FIFO for enabled channels */ | ||
486 | fifo |= fifo_setting[enable]; | ||
487 | pci_write_config_byte(pdev, 0x43, fifo); | ||
488 | } | ||
489 | /* Clock set up */ | 513 | /* Clock set up */ |
490 | switch(config->flags & VIA_UDMA) { | 514 | switch(config->flags & VIA_UDMA) { |
491 | case VIA_UDMA_NONE: | 515 | case VIA_UDMA_NONE: |
@@ -529,6 +553,39 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
529 | return ata_pci_init_one(pdev, port_info, 2); | 553 | return ata_pci_init_one(pdev, port_info, 2); |
530 | } | 554 | } |
531 | 555 | ||
556 | /** | ||
557 | * via_reinit_one - reinit after resume | ||
558 | * @pdev; PCI device | ||
559 | * | ||
560 | * Called when the VIA PATA device is resumed. We must then | ||
561 | * reconfigure the fifo and other setup we may have altered. In | ||
562 | * addition the kernel needs to have the resume methods on PCI | ||
563 | * quirk supported. | ||
564 | */ | ||
565 | |||
566 | static int via_reinit_one(struct pci_dev *pdev) | ||
567 | { | ||
568 | u32 timing; | ||
569 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
570 | const struct via_isa_bridge *config = host->private_data; | ||
571 | |||
572 | via_config_fifo(pdev, config->flags); | ||
573 | |||
574 | if ((config->flags & VIA_UDMA) == VIA_UDMA_66) { | ||
575 | /* The 66 MHz devices require we enable the clock */ | ||
576 | pci_read_config_dword(pdev, 0x50, &timing); | ||
577 | timing |= 0x80008; | ||
578 | pci_write_config_dword(pdev, 0x50, timing); | ||
579 | } | ||
580 | if (config->flags & VIA_BAD_CLK66) { | ||
581 | /* Disable the 66MHz clock on problem devices */ | ||
582 | pci_read_config_dword(pdev, 0x50, &timing); | ||
583 | timing &= ~0x80008; | ||
584 | pci_write_config_dword(pdev, 0x50, timing); | ||
585 | } | ||
586 | return ata_pci_device_resume(pdev); | ||
587 | } | ||
588 | |||
532 | static const struct pci_device_id via[] = { | 589 | static const struct pci_device_id via[] = { |
533 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, | 590 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, |
534 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), }, | 591 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), }, |
@@ -542,7 +599,9 @@ static struct pci_driver via_pci_driver = { | |||
542 | .name = DRV_NAME, | 599 | .name = DRV_NAME, |
543 | .id_table = via, | 600 | .id_table = via, |
544 | .probe = via_init_one, | 601 | .probe = via_init_one, |
545 | .remove = ata_pci_remove_one | 602 | .remove = ata_pci_remove_one, |
603 | .suspend = ata_pci_device_suspend, | ||
604 | .resume = via_reinit_one, | ||
546 | }; | 605 | }; |
547 | 606 | ||
548 | static int __init via_init(void) | 607 | static int __init via_init(void) |