diff options
Diffstat (limited to 'drivers/ide/via82cxxx.c')
-rw-r--r-- | drivers/ide/via82cxxx.c | 132 |
1 files changed, 108 insertions, 24 deletions
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 028de26a25fe..e65d010b708d 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * vt8235, vt8237, vt8237a | 6 | * vt8235, vt8237, vt8237a |
7 | * | 7 | * |
8 | * Copyright (c) 2000-2002 Vojtech Pavlik | 8 | * Copyright (c) 2000-2002 Vojtech Pavlik |
9 | * Copyright (c) 2007 Bartlomiej Zolnierkiewicz | 9 | * Copyright (c) 2007-2010 Bartlomiej Zolnierkiewicz |
10 | * | 10 | * |
11 | * Based on the work of: | 11 | * Based on the work of: |
12 | * Michel Aubry | 12 | * Michel Aubry |
@@ -54,6 +54,11 @@ | |||
54 | #define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */ | 54 | #define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */ |
55 | #define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */ | 55 | #define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */ |
56 | #define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */ | 56 | #define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */ |
57 | #define VIA_SATA_PATA 0x80 /* SATA/PATA combined configuration */ | ||
58 | |||
59 | enum { | ||
60 | VIA_IDFLAG_SINGLE = (1 << 1), /* single channel controller */ | ||
61 | }; | ||
57 | 62 | ||
58 | /* | 63 | /* |
59 | * VIA SouthBridge chips. | 64 | * VIA SouthBridge chips. |
@@ -67,11 +72,13 @@ static struct via_isa_bridge { | |||
67 | u8 udma_mask; | 72 | u8 udma_mask; |
68 | u8 flags; | 73 | u8 flags; |
69 | } via_isa_bridges[] = { | 74 | } via_isa_bridges[] = { |
70 | { "vx855", PCI_DEVICE_ID_VIA_VX855, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 75 | { "vx855", PCI_DEVICE_ID_VIA_VX855, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST | VIA_SATA_PATA }, |
71 | { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 76 | { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST | VIA_SATA_PATA }, |
72 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 77 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST | VIA_SATA_PATA }, |
78 | { "vt8261", PCI_DEVICE_ID_VIA_8261, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | ||
73 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 79 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
74 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 80 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
81 | { "vt6415", PCI_DEVICE_ID_VIA_6410, 0x00, 0xff, ATA_UDMA6, VIA_BAD_AST }, | ||
75 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 82 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
76 | { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 83 | { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
77 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 84 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
@@ -92,6 +99,7 @@ static struct via_isa_bridge { | |||
92 | { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO }, | 99 | { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO }, |
93 | { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK }, | 100 | { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK }, |
94 | { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, | 101 | { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, |
102 | { "vtxxxx", PCI_DEVICE_ID_VIA_ANON, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | ||
95 | { NULL } | 103 | { NULL } |
96 | }; | 104 | }; |
97 | 105 | ||
@@ -102,6 +110,7 @@ struct via82cxxx_dev | |||
102 | { | 110 | { |
103 | struct via_isa_bridge *via_config; | 111 | struct via_isa_bridge *via_config; |
104 | unsigned int via_80w; | 112 | unsigned int via_80w; |
113 | u8 cached_device[2]; | ||
105 | }; | 114 | }; |
106 | 115 | ||
107 | /** | 116 | /** |
@@ -137,30 +146,45 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) | |||
137 | case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break; | 146 | case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break; |
138 | case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; | 147 | case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; |
139 | case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; | 148 | case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break; |
140 | default: return; | ||
141 | } | 149 | } |
142 | 150 | ||
143 | pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t); | 151 | /* Set UDMA unless device is not UDMA capable */ |
152 | if (vdev->via_config->udma_mask) { | ||
153 | u8 udma_etc; | ||
154 | |||
155 | pci_read_config_byte(dev, VIA_UDMA_TIMING + 3 - dn, &udma_etc); | ||
156 | |||
157 | /* clear transfer mode bit */ | ||
158 | udma_etc &= ~0x20; | ||
159 | |||
160 | if (timing->udma) { | ||
161 | /* preserve 80-wire cable detection bit */ | ||
162 | udma_etc &= 0x10; | ||
163 | udma_etc |= t; | ||
164 | } | ||
165 | |||
166 | pci_write_config_byte(dev, VIA_UDMA_TIMING + 3 - dn, udma_etc); | ||
167 | } | ||
144 | } | 168 | } |
145 | 169 | ||
146 | /** | 170 | /** |
147 | * via_set_drive - configure transfer mode | 171 | * via_set_drive - configure transfer mode |
172 | * @hwif: port | ||
148 | * @drive: Drive to set up | 173 | * @drive: Drive to set up |
149 | * @speed: desired speed | ||
150 | * | 174 | * |
151 | * via_set_drive() computes timing values configures the chipset to | 175 | * via_set_drive() computes timing values configures the chipset to |
152 | * a desired transfer mode. It also can be called by upper layers. | 176 | * a desired transfer mode. It also can be called by upper layers. |
153 | */ | 177 | */ |
154 | 178 | ||
155 | static void via_set_drive(ide_drive_t *drive, const u8 speed) | 179 | static void via_set_drive(ide_hwif_t *hwif, ide_drive_t *drive) |
156 | { | 180 | { |
157 | ide_hwif_t *hwif = drive->hwif; | ||
158 | ide_drive_t *peer = ide_get_pair_dev(drive); | 181 | ide_drive_t *peer = ide_get_pair_dev(drive); |
159 | struct pci_dev *dev = to_pci_dev(hwif->dev); | 182 | struct pci_dev *dev = to_pci_dev(hwif->dev); |
160 | struct ide_host *host = pci_get_drvdata(dev); | 183 | struct ide_host *host = pci_get_drvdata(dev); |
161 | struct via82cxxx_dev *vdev = host->host_priv; | 184 | struct via82cxxx_dev *vdev = host->host_priv; |
162 | struct ide_timing t, p; | 185 | struct ide_timing t, p; |
163 | unsigned int T, UT; | 186 | unsigned int T, UT; |
187 | const u8 speed = drive->dma_mode; | ||
164 | 188 | ||
165 | T = 1000000000 / via_clock; | 189 | T = 1000000000 / via_clock; |
166 | 190 | ||
@@ -175,7 +199,7 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed) | |||
175 | ide_timing_compute(drive, speed, &t, T, UT); | 199 | ide_timing_compute(drive, speed, &t, T, UT); |
176 | 200 | ||
177 | if (peer) { | 201 | if (peer) { |
178 | ide_timing_compute(peer, peer->current_speed, &p, T, UT); | 202 | ide_timing_compute(peer, peer->pio_mode, &p, T, UT); |
179 | ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); | 203 | ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); |
180 | } | 204 | } |
181 | 205 | ||
@@ -184,22 +208,24 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed) | |||
184 | 208 | ||
185 | /** | 209 | /** |
186 | * via_set_pio_mode - set host controller for PIO mode | 210 | * via_set_pio_mode - set host controller for PIO mode |
211 | * @hwif: port | ||
187 | * @drive: drive | 212 | * @drive: drive |
188 | * @pio: PIO mode number | ||
189 | * | 213 | * |
190 | * A callback from the upper layers for PIO-only tuning. | 214 | * A callback from the upper layers for PIO-only tuning. |
191 | */ | 215 | */ |
192 | 216 | ||
193 | static void via_set_pio_mode(ide_drive_t *drive, const u8 pio) | 217 | static void via_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) |
194 | { | 218 | { |
195 | via_set_drive(drive, XFER_PIO_0 + pio); | 219 | drive->dma_mode = drive->pio_mode; |
220 | via_set_drive(hwif, drive); | ||
196 | } | 221 | } |
197 | 222 | ||
198 | static struct via_isa_bridge *via_config_find(struct pci_dev **isa) | 223 | static struct via_isa_bridge *via_config_find(struct pci_dev **isa) |
199 | { | 224 | { |
200 | struct via_isa_bridge *via_config; | 225 | struct via_isa_bridge *via_config; |
201 | 226 | ||
202 | for (via_config = via_isa_bridges; via_config->id; via_config++) | 227 | for (via_config = via_isa_bridges; |
228 | via_config->id != PCI_DEVICE_ID_VIA_ANON; via_config++) | ||
203 | if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA + | 229 | if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA + |
204 | !!(via_config->flags & VIA_BAD_ID), | 230 | !!(via_config->flags & VIA_BAD_ID), |
205 | via_config->id, NULL))) { | 231 | via_config->id, NULL))) { |
@@ -362,6 +388,9 @@ static u8 via82cxxx_cable_detect(ide_hwif_t *hwif) | |||
362 | if (via_cable_override(pdev)) | 388 | if (via_cable_override(pdev)) |
363 | return ATA_CBL_PATA40_SHORT; | 389 | return ATA_CBL_PATA40_SHORT; |
364 | 390 | ||
391 | if ((vdev->via_config->flags & VIA_SATA_PATA) && hwif->channel == 0) | ||
392 | return ATA_CBL_SATA; | ||
393 | |||
365 | if ((vdev->via_80w >> hwif->channel) & 1) | 394 | if ((vdev->via_80w >> hwif->channel) & 1) |
366 | return ATA_CBL_PATA80; | 395 | return ATA_CBL_PATA80; |
367 | else | 396 | else |
@@ -374,10 +403,66 @@ static const struct ide_port_ops via_port_ops = { | |||
374 | .cable_detect = via82cxxx_cable_detect, | 403 | .cable_detect = via82cxxx_cable_detect, |
375 | }; | 404 | }; |
376 | 405 | ||
406 | static void via_write_devctl(ide_hwif_t *hwif, u8 ctl) | ||
407 | { | ||
408 | struct via82cxxx_dev *vdev = hwif->host->host_priv; | ||
409 | |||
410 | outb(ctl, hwif->io_ports.ctl_addr); | ||
411 | outb(vdev->cached_device[hwif->channel], hwif->io_ports.device_addr); | ||
412 | } | ||
413 | |||
414 | static void __via_dev_select(ide_drive_t *drive, u8 select) | ||
415 | { | ||
416 | ide_hwif_t *hwif = drive->hwif; | ||
417 | struct via82cxxx_dev *vdev = hwif->host->host_priv; | ||
418 | |||
419 | outb(select, hwif->io_ports.device_addr); | ||
420 | vdev->cached_device[hwif->channel] = select; | ||
421 | } | ||
422 | |||
423 | static void via_dev_select(ide_drive_t *drive) | ||
424 | { | ||
425 | __via_dev_select(drive, drive->select | ATA_DEVICE_OBS); | ||
426 | } | ||
427 | |||
428 | static void via_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) | ||
429 | { | ||
430 | ide_hwif_t *hwif = drive->hwif; | ||
431 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
432 | |||
433 | if (valid & IDE_VALID_FEATURE) | ||
434 | outb(tf->feature, io_ports->feature_addr); | ||
435 | if (valid & IDE_VALID_NSECT) | ||
436 | outb(tf->nsect, io_ports->nsect_addr); | ||
437 | if (valid & IDE_VALID_LBAL) | ||
438 | outb(tf->lbal, io_ports->lbal_addr); | ||
439 | if (valid & IDE_VALID_LBAM) | ||
440 | outb(tf->lbam, io_ports->lbam_addr); | ||
441 | if (valid & IDE_VALID_LBAH) | ||
442 | outb(tf->lbah, io_ports->lbah_addr); | ||
443 | if (valid & IDE_VALID_DEVICE) | ||
444 | __via_dev_select(drive, tf->device); | ||
445 | } | ||
446 | |||
447 | const struct ide_tp_ops via_tp_ops = { | ||
448 | .exec_command = ide_exec_command, | ||
449 | .read_status = ide_read_status, | ||
450 | .read_altstatus = ide_read_altstatus, | ||
451 | .write_devctl = via_write_devctl, | ||
452 | |||
453 | .dev_select = via_dev_select, | ||
454 | .tf_load = via_tf_load, | ||
455 | .tf_read = ide_tf_read, | ||
456 | |||
457 | .input_data = ide_input_data, | ||
458 | .output_data = ide_output_data, | ||
459 | }; | ||
460 | |||
377 | static const struct ide_port_info via82cxxx_chipset __devinitdata = { | 461 | static const struct ide_port_info via82cxxx_chipset __devinitdata = { |
378 | .name = DRV_NAME, | 462 | .name = DRV_NAME, |
379 | .init_chipset = init_chipset_via82cxxx, | 463 | .init_chipset = init_chipset_via82cxxx, |
380 | .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, | 464 | .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, |
465 | .tp_ops = &via_tp_ops, | ||
381 | .port_ops = &via_port_ops, | 466 | .port_ops = &via_port_ops, |
382 | .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | | 467 | .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | |
383 | IDE_HFLAG_POST_SET_MODE | | 468 | IDE_HFLAG_POST_SET_MODE | |
@@ -402,11 +487,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i | |||
402 | * Find the ISA bridge and check we know what it is. | 487 | * Find the ISA bridge and check we know what it is. |
403 | */ | 488 | */ |
404 | via_config = via_config_find(&isa); | 489 | via_config = via_config_find(&isa); |
405 | if (!via_config->id) { | ||
406 | printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n", | ||
407 | pci_name(dev)); | ||
408 | return -ENODEV; | ||
409 | } | ||
410 | 490 | ||
411 | /* | 491 | /* |
412 | * Print the boot message. | 492 | * Print the boot message. |
@@ -436,10 +516,13 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i | |||
436 | via_clock = 33333; | 516 | via_clock = 33333; |
437 | } | 517 | } |
438 | 518 | ||
439 | if (idx == 0) | 519 | if (idx == 1) |
440 | d.host_flags |= IDE_HFLAG_NO_AUTODMA; | ||
441 | else | ||
442 | d.enablebits[1].reg = d.enablebits[0].reg = 0; | 520 | d.enablebits[1].reg = d.enablebits[0].reg = 0; |
521 | else | ||
522 | d.host_flags |= IDE_HFLAG_NO_AUTODMA; | ||
523 | |||
524 | if (idx == VIA_IDFLAG_SINGLE) | ||
525 | d.host_flags |= IDE_HFLAG_SINGLE; | ||
443 | 526 | ||
444 | if ((via_config->flags & VIA_NO_UNMASK) == 0) | 527 | if ((via_config->flags & VIA_NO_UNMASK) == 0) |
445 | d.host_flags |= IDE_HFLAG_UNMASK_IRQS; | 528 | d.host_flags |= IDE_HFLAG_UNMASK_IRQS; |
@@ -475,8 +558,9 @@ static const struct pci_device_id via_pci_tbl[] = { | |||
475 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 }, | 558 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 }, |
476 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 }, | 559 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 }, |
477 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 }, | 560 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 }, |
478 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_VX855_IDE), 0 }, | 561 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_VX855_IDE), VIA_IDFLAG_SINGLE }, |
479 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 }, | 562 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 }, |
563 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6415), 1 }, | ||
480 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 }, | 564 | { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 }, |
481 | { 0, }, | 565 | { 0, }, |
482 | }; | 566 | }; |
@@ -504,6 +588,6 @@ static void __exit via_ide_exit(void) | |||
504 | module_init(via_ide_init); | 588 | module_init(via_ide_init); |
505 | module_exit(via_ide_exit); | 589 | module_exit(via_ide_exit); |
506 | 590 | ||
507 | MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick"); | 591 | MODULE_AUTHOR("Vojtech Pavlik, Bartlomiej Zolnierkiewicz, Michel Aubry, Jeff Garzik, Andre Hedrick"); |
508 | MODULE_DESCRIPTION("PCI driver module for VIA IDE"); | 592 | MODULE_DESCRIPTION("PCI driver module for VIA IDE"); |
509 | MODULE_LICENSE("GPL"); | 593 | MODULE_LICENSE("GPL"); |