diff options
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r-- | drivers/ata/sata_via.c | 217 |
1 files changed, 88 insertions, 129 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 598e6a26a481..1d855f55f5f7 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -64,8 +64,6 @@ enum { | |||
64 | PORT0 = (1 << 1), | 64 | PORT0 = (1 << 1), |
65 | PORT1 = (1 << 0), | 65 | PORT1 = (1 << 0), |
66 | ALL_PORTS = PORT0 | PORT1, | 66 | ALL_PORTS = PORT0 | PORT1, |
67 | PATA_PORT = 2, /* PATA is port 2 */ | ||
68 | N_PORTS = 3, | ||
69 | 67 | ||
70 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), | 68 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), |
71 | 69 | ||
@@ -78,11 +76,9 @@ static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); | |||
78 | static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 76 | static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
79 | static void svia_noop_freeze(struct ata_port *ap); | 77 | static void svia_noop_freeze(struct ata_port *ap); |
80 | static void vt6420_error_handler(struct ata_port *ap); | 78 | static void vt6420_error_handler(struct ata_port *ap); |
81 | static void vt6421_sata_error_handler(struct ata_port *ap); | 79 | static int vt6421_pata_cable_detect(struct ata_port *ap); |
82 | static void vt6421_pata_error_handler(struct ata_port *ap); | ||
83 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); | 80 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); |
84 | static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); | 81 | static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); |
85 | static int vt6421_port_start(struct ata_port *ap); | ||
86 | 82 | ||
87 | static const struct pci_device_id svia_pci_tbl[] = { | 83 | static const struct pci_device_id svia_pci_tbl[] = { |
88 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, | 84 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, |
@@ -141,7 +137,6 @@ static const struct ata_port_operations vt6420_sata_ops = { | |||
141 | .error_handler = vt6420_error_handler, | 137 | .error_handler = vt6420_error_handler, |
142 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 138 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
143 | 139 | ||
144 | .irq_handler = ata_interrupt, | ||
145 | .irq_clear = ata_bmdma_irq_clear, | 140 | .irq_clear = ata_bmdma_irq_clear, |
146 | .irq_on = ata_irq_on, | 141 | .irq_on = ata_irq_on, |
147 | .irq_ack = ata_irq_ack, | 142 | .irq_ack = ata_irq_ack, |
@@ -172,15 +167,15 @@ static const struct ata_port_operations vt6421_pata_ops = { | |||
172 | 167 | ||
173 | .freeze = ata_bmdma_freeze, | 168 | .freeze = ata_bmdma_freeze, |
174 | .thaw = ata_bmdma_thaw, | 169 | .thaw = ata_bmdma_thaw, |
175 | .error_handler = vt6421_pata_error_handler, | 170 | .error_handler = ata_bmdma_error_handler, |
176 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 171 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
172 | .cable_detect = vt6421_pata_cable_detect, | ||
177 | 173 | ||
178 | .irq_handler = ata_interrupt, | ||
179 | .irq_clear = ata_bmdma_irq_clear, | 174 | .irq_clear = ata_bmdma_irq_clear, |
180 | .irq_on = ata_irq_on, | 175 | .irq_on = ata_irq_on, |
181 | .irq_ack = ata_irq_ack, | 176 | .irq_ack = ata_irq_ack, |
182 | 177 | ||
183 | .port_start = vt6421_port_start, | 178 | .port_start = ata_port_start, |
184 | }; | 179 | }; |
185 | 180 | ||
186 | static const struct ata_port_operations vt6421_sata_ops = { | 181 | static const struct ata_port_operations vt6421_sata_ops = { |
@@ -203,10 +198,10 @@ static const struct ata_port_operations vt6421_sata_ops = { | |||
203 | 198 | ||
204 | .freeze = ata_bmdma_freeze, | 199 | .freeze = ata_bmdma_freeze, |
205 | .thaw = ata_bmdma_thaw, | 200 | .thaw = ata_bmdma_thaw, |
206 | .error_handler = vt6421_sata_error_handler, | 201 | .error_handler = ata_bmdma_error_handler, |
207 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 202 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
203 | .cable_detect = ata_cable_sata, | ||
208 | 204 | ||
209 | .irq_handler = ata_interrupt, | ||
210 | .irq_clear = ata_bmdma_irq_clear, | 205 | .irq_clear = ata_bmdma_irq_clear, |
211 | .irq_on = ata_irq_on, | 206 | .irq_on = ata_irq_on, |
212 | .irq_ack = ata_irq_ack, | 207 | .irq_ack = ata_irq_ack, |
@@ -214,11 +209,10 @@ static const struct ata_port_operations vt6421_sata_ops = { | |||
214 | .scr_read = svia_scr_read, | 209 | .scr_read = svia_scr_read, |
215 | .scr_write = svia_scr_write, | 210 | .scr_write = svia_scr_write, |
216 | 211 | ||
217 | .port_start = vt6421_port_start, | 212 | .port_start = ata_port_start, |
218 | }; | 213 | }; |
219 | 214 | ||
220 | static struct ata_port_info vt6420_port_info = { | 215 | static const struct ata_port_info vt6420_port_info = { |
221 | .sht = &svia_sht, | ||
222 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 216 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
223 | .pio_mask = 0x1f, | 217 | .pio_mask = 0x1f, |
224 | .mwdma_mask = 0x07, | 218 | .mwdma_mask = 0x07, |
@@ -226,6 +220,22 @@ static struct ata_port_info vt6420_port_info = { | |||
226 | .port_ops = &vt6420_sata_ops, | 220 | .port_ops = &vt6420_sata_ops, |
227 | }; | 221 | }; |
228 | 222 | ||
223 | static struct ata_port_info vt6421_sport_info = { | ||
224 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | ||
225 | .pio_mask = 0x1f, | ||
226 | .mwdma_mask = 0x07, | ||
227 | .udma_mask = 0x7f, | ||
228 | .port_ops = &vt6421_sata_ops, | ||
229 | }; | ||
230 | |||
231 | static struct ata_port_info vt6421_pport_info = { | ||
232 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, | ||
233 | .pio_mask = 0x1f, | ||
234 | .mwdma_mask = 0, | ||
235 | .udma_mask = 0x7f, | ||
236 | .port_ops = &vt6421_pata_ops, | ||
237 | }; | ||
238 | |||
229 | MODULE_AUTHOR("Jeff Garzik"); | 239 | MODULE_AUTHOR("Jeff Garzik"); |
230 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); | 240 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); |
231 | MODULE_LICENSE("GPL"); | 241 | MODULE_LICENSE("GPL"); |
@@ -330,35 +340,15 @@ static void vt6420_error_handler(struct ata_port *ap) | |||
330 | NULL, ata_std_postreset); | 340 | NULL, ata_std_postreset); |
331 | } | 341 | } |
332 | 342 | ||
333 | static int vt6421_pata_prereset(struct ata_port *ap) | 343 | static int vt6421_pata_cable_detect(struct ata_port *ap) |
334 | { | 344 | { |
335 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 345 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
336 | u8 tmp; | 346 | u8 tmp; |
337 | 347 | ||
338 | pci_read_config_byte(pdev, PATA_UDMA_TIMING, &tmp); | 348 | pci_read_config_byte(pdev, PATA_UDMA_TIMING, &tmp); |
339 | if (tmp & 0x10) | 349 | if (tmp & 0x10) |
340 | ap->cbl = ATA_CBL_PATA40; | 350 | return ATA_CBL_PATA40; |
341 | else | 351 | return ATA_CBL_PATA80; |
342 | ap->cbl = ATA_CBL_PATA80; | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static void vt6421_pata_error_handler(struct ata_port *ap) | ||
347 | { | ||
348 | return ata_bmdma_drive_eh(ap, vt6421_pata_prereset, ata_std_softreset, | ||
349 | NULL, ata_std_postreset); | ||
350 | } | ||
351 | |||
352 | static int vt6421_sata_prereset(struct ata_port *ap) | ||
353 | { | ||
354 | ap->cbl = ATA_CBL_SATA; | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static void vt6421_sata_error_handler(struct ata_port *ap) | ||
359 | { | ||
360 | return ata_bmdma_drive_eh(ap, vt6421_sata_prereset, ata_std_softreset, | ||
361 | NULL, ata_std_postreset); | ||
362 | } | 352 | } |
363 | 353 | ||
364 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev) | 354 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev) |
@@ -375,16 +365,6 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev) | |||
375 | pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]); | 365 | pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]); |
376 | } | 366 | } |
377 | 367 | ||
378 | static int vt6421_port_start(struct ata_port *ap) | ||
379 | { | ||
380 | if (ap->port_no == PATA_PORT) { | ||
381 | ap->ops = &vt6421_pata_ops; | ||
382 | ap->mwdma_mask = 0; | ||
383 | ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST; | ||
384 | } | ||
385 | return ata_port_start(ap); | ||
386 | } | ||
387 | |||
388 | static const unsigned int svia_bar_sizes[] = { | 368 | static const unsigned int svia_bar_sizes[] = { |
389 | 8, 4, 8, 4, 16, 256 | 369 | 8, 4, 8, 4, 16, 256 |
390 | }; | 370 | }; |
@@ -403,79 +383,78 @@ static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port) | |||
403 | return addr + (port * 64); | 383 | return addr + (port * 64); |
404 | } | 384 | } |
405 | 385 | ||
406 | static void vt6421_init_addrs(struct ata_probe_ent *probe_ent, | 386 | static void vt6421_init_addrs(struct ata_port *ap) |
407 | void __iomem * const *iomap, unsigned int port) | ||
408 | { | 387 | { |
409 | void __iomem *reg_addr = iomap[port]; | 388 | void __iomem * const * iomap = ap->host->iomap; |
410 | void __iomem *bmdma_addr = iomap[4] + (port * 8); | 389 | void __iomem *reg_addr = iomap[ap->port_no]; |
411 | 390 | void __iomem *bmdma_addr = iomap[4] + (ap->port_no * 8); | |
412 | probe_ent->port[port].cmd_addr = reg_addr; | 391 | struct ata_ioports *ioaddr = &ap->ioaddr; |
413 | probe_ent->port[port].altstatus_addr = | 392 | |
414 | probe_ent->port[port].ctl_addr = (void __iomem *) | 393 | ioaddr->cmd_addr = reg_addr; |
394 | ioaddr->altstatus_addr = | ||
395 | ioaddr->ctl_addr = (void __iomem *) | ||
415 | ((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS); | 396 | ((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS); |
416 | probe_ent->port[port].bmdma_addr = bmdma_addr; | 397 | ioaddr->bmdma_addr = bmdma_addr; |
417 | probe_ent->port[port].scr_addr = vt6421_scr_addr(iomap[5], port); | 398 | ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no); |
418 | 399 | ||
419 | ata_std_ports(&probe_ent->port[port]); | 400 | ata_std_ports(ioaddr); |
420 | } | 401 | } |
421 | 402 | ||
422 | static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev) | 403 | static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) |
423 | { | 404 | { |
424 | struct ata_probe_ent *probe_ent; | 405 | const struct ata_port_info *ppi[] = { &vt6420_port_info, NULL }; |
425 | struct ata_port_info *ppi[2]; | 406 | struct ata_host *host; |
426 | void __iomem *bar5; | 407 | int rc; |
427 | 408 | ||
428 | ppi[0] = ppi[1] = &vt6420_port_info; | 409 | rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host); |
429 | probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); | 410 | if (rc) |
430 | if (!probe_ent) | 411 | return rc; |
431 | return NULL; | 412 | *r_host = host; |
432 | 413 | ||
433 | bar5 = pcim_iomap(pdev, 5, 0); | 414 | rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); |
434 | if (!bar5) { | 415 | if (rc) { |
435 | dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); | 416 | dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); |
436 | return NULL; | 417 | return rc; |
437 | } | 418 | } |
438 | 419 | ||
439 | probe_ent->port[0].scr_addr = svia_scr_addr(bar5, 0); | 420 | host->ports[0]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 0); |
440 | probe_ent->port[1].scr_addr = svia_scr_addr(bar5, 1); | 421 | host->ports[1]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 1); |
441 | 422 | ||
442 | return probe_ent; | 423 | return 0; |
443 | } | 424 | } |
444 | 425 | ||
445 | static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) | 426 | static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) |
446 | { | 427 | { |
447 | struct ata_probe_ent *probe_ent; | 428 | const struct ata_port_info *ppi[] = |
448 | unsigned int i; | 429 | { &vt6421_sport_info, &vt6421_sport_info, &vt6421_pport_info }; |
430 | struct ata_host *host; | ||
431 | int i, rc; | ||
432 | |||
433 | *r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi)); | ||
434 | if (!host) { | ||
435 | dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n"); | ||
436 | return -ENOMEM; | ||
437 | } | ||
449 | 438 | ||
450 | probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL); | 439 | rc = pcim_iomap_regions(pdev, 0x1f, DRV_NAME); |
451 | if (!probe_ent) | 440 | if (rc) { |
452 | return NULL; | 441 | dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap " |
453 | 442 | "PCI BARs (errno=%d)\n", rc); | |
454 | memset(probe_ent, 0, sizeof(*probe_ent)); | 443 | return rc; |
455 | probe_ent->dev = pci_dev_to_dev(pdev); | 444 | } |
456 | INIT_LIST_HEAD(&probe_ent->node); | 445 | host->iomap = pcim_iomap_table(pdev); |
457 | |||
458 | probe_ent->sht = &svia_sht; | ||
459 | probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; | ||
460 | probe_ent->port_ops = &vt6421_sata_ops; | ||
461 | probe_ent->n_ports = N_PORTS; | ||
462 | probe_ent->irq = pdev->irq; | ||
463 | probe_ent->irq_flags = IRQF_SHARED; | ||
464 | probe_ent->pio_mask = 0x1f; | ||
465 | probe_ent->mwdma_mask = 0x07; | ||
466 | probe_ent->udma_mask = 0x7f; | ||
467 | |||
468 | for (i = 0; i < 6; i++) | ||
469 | if (!pcim_iomap(pdev, i, 0)) { | ||
470 | dev_printk(KERN_ERR, &pdev->dev, | ||
471 | "failed to iomap PCI BAR %d\n", i); | ||
472 | return NULL; | ||
473 | } | ||
474 | 446 | ||
475 | for (i = 0; i < N_PORTS; i++) | 447 | for (i = 0; i < host->n_ports; i++) |
476 | vt6421_init_addrs(probe_ent, pcim_iomap_table(pdev), i); | 448 | vt6421_init_addrs(host->ports[i]); |
477 | 449 | ||
478 | return probe_ent; | 450 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); |
451 | if (rc) | ||
452 | return rc; | ||
453 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
454 | if (rc) | ||
455 | return rc; | ||
456 | |||
457 | return 0; | ||
479 | } | 458 | } |
480 | 459 | ||
481 | static void svia_configure(struct pci_dev *pdev) | 460 | static void svia_configure(struct pci_dev *pdev) |
@@ -522,7 +501,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
522 | static int printed_version; | 501 | static int printed_version; |
523 | unsigned int i; | 502 | unsigned int i; |
524 | int rc; | 503 | int rc; |
525 | struct ata_probe_ent *probe_ent; | 504 | struct ata_host *host; |
526 | int board_id = (int) ent->driver_data; | 505 | int board_id = (int) ent->driver_data; |
527 | const int *bar_sizes; | 506 | const int *bar_sizes; |
528 | u8 tmp8; | 507 | u8 tmp8; |
@@ -534,12 +513,6 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
534 | if (rc) | 513 | if (rc) |
535 | return rc; | 514 | return rc; |
536 | 515 | ||
537 | rc = pci_request_regions(pdev, DRV_NAME); | ||
538 | if (rc) { | ||
539 | pcim_pin_device(pdev); | ||
540 | return rc; | ||
541 | } | ||
542 | |||
543 | if (board_id == vt6420) { | 516 | if (board_id == vt6420) { |
544 | pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); | 517 | pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); |
545 | if (tmp8 & SATA_2DEV) { | 518 | if (tmp8 & SATA_2DEV) { |
@@ -565,32 +538,18 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
565 | return -ENODEV; | 538 | return -ENODEV; |
566 | } | 539 | } |
567 | 540 | ||
568 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
569 | if (rc) | ||
570 | return rc; | ||
571 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
572 | if (rc) | ||
573 | return rc; | ||
574 | |||
575 | if (board_id == vt6420) | 541 | if (board_id == vt6420) |
576 | probe_ent = vt6420_init_probe_ent(pdev); | 542 | rc = vt6420_prepare_host(pdev, &host); |
577 | else | 543 | else |
578 | probe_ent = vt6421_init_probe_ent(pdev); | 544 | rc = vt6421_prepare_host(pdev, &host); |
579 | 545 | if (rc) | |
580 | if (!probe_ent) { | 546 | return rc; |
581 | dev_printk(KERN_ERR, &pdev->dev, "out of memory\n"); | ||
582 | return -ENOMEM; | ||
583 | } | ||
584 | 547 | ||
585 | svia_configure(pdev); | 548 | svia_configure(pdev); |
586 | 549 | ||
587 | pci_set_master(pdev); | 550 | pci_set_master(pdev); |
588 | 551 | return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, | |
589 | if (!ata_device_add(probe_ent)) | 552 | &svia_sht); |
590 | return -ENODEV; | ||
591 | |||
592 | devm_kfree(&pdev->dev, probe_ent); | ||
593 | return 0; | ||
594 | } | 553 | } |
595 | 554 | ||
596 | static int __init svia_init(void) | 555 | static int __init svia_init(void) |