diff options
Diffstat (limited to 'drivers/ata/pata_icside.c')
-rw-r--r-- | drivers/ata/pata_icside.c | 142 |
1 files changed, 86 insertions, 56 deletions
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index d323e75b05d5..c791a46df461 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c | |||
@@ -60,6 +60,18 @@ struct pata_icside_state { | |||
60 | struct scatterlist sg[PATA_ICSIDE_MAX_SG]; | 60 | struct scatterlist sg[PATA_ICSIDE_MAX_SG]; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | struct pata_icside_info { | ||
64 | struct pata_icside_state *state; | ||
65 | struct expansion_card *ec; | ||
66 | void __iomem *base; | ||
67 | void __iomem *irqaddr; | ||
68 | unsigned int irqmask; | ||
69 | const expansioncard_ops_t *irqops; | ||
70 | unsigned int mwdma_mask; | ||
71 | unsigned int nr_ports; | ||
72 | const struct portinfo *port[2]; | ||
73 | }; | ||
74 | |||
63 | #define ICS_TYPE_A3IN 0 | 75 | #define ICS_TYPE_A3IN 0 |
64 | #define ICS_TYPE_A3USER 1 | 76 | #define ICS_TYPE_A3USER 1 |
65 | #define ICS_TYPE_V6 3 | 77 | #define ICS_TYPE_V6 3 |
@@ -269,9 +281,10 @@ static u8 pata_icside_bmdma_status(struct ata_port *ap) | |||
269 | return readb(irq_port) & 1 ? ATA_DMA_INTR : 0; | 281 | return readb(irq_port) & 1 ? ATA_DMA_INTR : 0; |
270 | } | 282 | } |
271 | 283 | ||
272 | static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec) | 284 | static int icside_dma_init(struct pata_icside_info *info) |
273 | { | 285 | { |
274 | struct pata_icside_state *state = ae->private_data; | 286 | struct pata_icside_state *state = info->state; |
287 | struct expansion_card *ec = info->ec; | ||
275 | int i; | 288 | int i; |
276 | 289 | ||
277 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 290 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
@@ -281,7 +294,7 @@ static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec) | |||
281 | 294 | ||
282 | if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { | 295 | if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { |
283 | state->dma = ec->dma; | 296 | state->dma = ec->dma; |
284 | ae->mwdma_mask = 0x07; /* MW0..2 */ | 297 | info->mwdma_mask = 0x07; /* MW0..2 */ |
285 | } | 298 | } |
286 | 299 | ||
287 | return 0; | 300 | return 0; |
@@ -371,6 +384,8 @@ static struct ata_port_operations pata_icside_port_ops = { | |||
371 | .check_status = ata_check_status, | 384 | .check_status = ata_check_status, |
372 | .dev_select = ata_std_dev_select, | 385 | .dev_select = ata_std_dev_select, |
373 | 386 | ||
387 | .cable_detect = ata_cable_40wire, | ||
388 | |||
374 | .bmdma_setup = pata_icside_bmdma_setup, | 389 | .bmdma_setup = pata_icside_bmdma_setup, |
375 | .bmdma_start = pata_icside_bmdma_start, | 390 | .bmdma_start = pata_icside_bmdma_start, |
376 | 391 | ||
@@ -385,7 +400,6 @@ static struct ata_port_operations pata_icside_port_ops = { | |||
385 | .error_handler = ata_bmdma_error_handler, | 400 | .error_handler = ata_bmdma_error_handler, |
386 | .post_internal_cmd = pata_icside_bmdma_stop, | 401 | .post_internal_cmd = pata_icside_bmdma_stop, |
387 | 402 | ||
388 | .irq_handler = ata_interrupt, | ||
389 | .irq_clear = ata_dummy_noret, | 403 | .irq_clear = ata_dummy_noret, |
390 | .irq_on = ata_irq_on, | 404 | .irq_on = ata_irq_on, |
391 | .irq_ack = pata_icside_irq_ack, | 405 | .irq_ack = pata_icside_irq_ack, |
@@ -396,11 +410,10 @@ static struct ata_port_operations pata_icside_port_ops = { | |||
396 | .bmdma_status = pata_icside_bmdma_status, | 410 | .bmdma_status = pata_icside_bmdma_status, |
397 | }; | 411 | }; |
398 | 412 | ||
399 | static void | 413 | static void __devinit |
400 | pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base, | 414 | pata_icside_setup_ioaddr(struct ata_ioports *ioaddr, void __iomem *base, |
401 | const struct portinfo *info) | 415 | const struct portinfo *info) |
402 | { | 416 | { |
403 | struct ata_ioports *ioaddr = &ae->port[ae->n_ports++]; | ||
404 | void __iomem *cmd = base + info->dataoffset; | 417 | void __iomem *cmd = base + info->dataoffset; |
405 | 418 | ||
406 | ioaddr->cmd_addr = cmd; | 419 | ioaddr->cmd_addr = cmd; |
@@ -419,10 +432,9 @@ pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base, | |||
419 | ioaddr->altstatus_addr = ioaddr->ctl_addr; | 432 | ioaddr->altstatus_addr = ioaddr->ctl_addr; |
420 | } | 433 | } |
421 | 434 | ||
422 | static int __init | 435 | static int __devinit pata_icside_register_v5(struct pata_icside_info *info) |
423 | pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec) | ||
424 | { | 436 | { |
425 | struct pata_icside_state *state = ae->private_data; | 437 | struct pata_icside_state *state = info->state; |
426 | void __iomem *base; | 438 | void __iomem *base; |
427 | 439 | ||
428 | base = ecardm_iomap(info->ec, ECARD_RES_MEMC, 0, 0); | 440 | base = ecardm_iomap(info->ec, ECARD_RES_MEMC, 0, 0); |
@@ -431,25 +443,20 @@ pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec) | |||
431 | 443 | ||
432 | state->irq_port = base; | 444 | state->irq_port = base; |
433 | 445 | ||
434 | ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; | 446 | info->base = base; |
435 | ec->irqmask = 1; | 447 | info->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; |
436 | 448 | info->irqmask = 1; | |
437 | ecard_setirq(ec, &pata_icside_ops_arcin_v5, state); | 449 | info->irqops = &pata_icside_ops_arcin_v5; |
438 | 450 | info->nr_ports = 1; | |
439 | /* | 451 | info->port[0] = &pata_icside_portinfo_v5; |
440 | * Be on the safe side - disable interrupts | ||
441 | */ | ||
442 | ec->ops->irqdisable(ec, ec->irq); | ||
443 | |||
444 | pata_icside_add_port(ae, base, &pata_icside_portinfo_v5); | ||
445 | 452 | ||
446 | return 0; | 453 | return 0; |
447 | } | 454 | } |
448 | 455 | ||
449 | static int __init | 456 | static int __devinit pata_icside_register_v6(struct pata_icside_info *info) |
450 | pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec) | ||
451 | { | 457 | { |
452 | struct pata_icside_state *state = ae->private_data; | 458 | struct pata_icside_state *state = info->state; |
459 | struct expansion_card *ec = info->ec; | ||
453 | void __iomem *ioc_base, *easi_base; | 460 | void __iomem *ioc_base, *easi_base; |
454 | unsigned int sel = 0; | 461 | unsigned int sel = 0; |
455 | 462 | ||
@@ -472,40 +479,72 @@ pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec) | |||
472 | 479 | ||
473 | writeb(sel, ioc_base); | 480 | writeb(sel, ioc_base); |
474 | 481 | ||
475 | ecard_setirq(ec, &pata_icside_ops_arcin_v6, state); | ||
476 | |||
477 | state->irq_port = easi_base; | 482 | state->irq_port = easi_base; |
478 | state->ioc_base = ioc_base; | 483 | state->ioc_base = ioc_base; |
479 | state->port[0].port_sel = sel; | 484 | state->port[0].port_sel = sel; |
480 | state->port[1].port_sel = sel | 1; | 485 | state->port[1].port_sel = sel | 1; |
481 | 486 | ||
482 | /* | 487 | /* |
483 | * Be on the safe side - disable interrupts | ||
484 | */ | ||
485 | ec->ops->irqdisable(ec, ec->irq); | ||
486 | |||
487 | /* | ||
488 | * Find and register the interfaces. | ||
489 | */ | ||
490 | pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1); | ||
491 | pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2); | ||
492 | |||
493 | /* | ||
494 | * FIXME: work around libata's aversion to calling port_disable. | 488 | * FIXME: work around libata's aversion to calling port_disable. |
495 | * This permanently disables interrupts on port 0 - bad luck if | 489 | * This permanently disables interrupts on port 0 - bad luck if |
496 | * you have a drive on that port. | 490 | * you have a drive on that port. |
497 | */ | 491 | */ |
498 | state->port[0].disabled = 1; | 492 | state->port[0].disabled = 1; |
499 | 493 | ||
500 | return icside_dma_init(ae, ec); | 494 | info->base = easi_base; |
495 | info->irqops = &pata_icside_ops_arcin_v6; | ||
496 | info->nr_ports = 2; | ||
497 | info->port[0] = &pata_icside_portinfo_v6_1; | ||
498 | info->port[1] = &pata_icside_portinfo_v6_2; | ||
499 | |||
500 | return icside_dma_init(info); | ||
501 | } | ||
502 | |||
503 | static int __devinit pata_icside_add_ports(struct pata_icside_info *info) | ||
504 | { | ||
505 | struct expansion_card *ec = info->ec; | ||
506 | struct ata_host *host; | ||
507 | int i; | ||
508 | |||
509 | if (info->irqaddr) { | ||
510 | ec->irqaddr = info->irqaddr; | ||
511 | ec->irqmask = info->irqmask; | ||
512 | } | ||
513 | if (info->irqops) | ||
514 | ecard_setirq(ec, info->irqops, info->state); | ||
515 | |||
516 | /* | ||
517 | * Be on the safe side - disable interrupts | ||
518 | */ | ||
519 | ec->ops->irqdisable(ec, ec->irq); | ||
520 | |||
521 | host = ata_host_alloc(&ec->dev, info->nr_ports); | ||
522 | if (!host) | ||
523 | return -ENOMEM; | ||
524 | |||
525 | host->private_data = info->state; | ||
526 | host->flags = ATA_HOST_SIMPLEX; | ||
527 | |||
528 | for (i = 0; i < info->nr_ports; i++) { | ||
529 | struct ata_port *ap = host->ports[i]; | ||
530 | |||
531 | ap->pio_mask = 0x1f; | ||
532 | ap->mwdma_mask = info->mwdma_mask; | ||
533 | ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; | ||
534 | ap->ops = &pata_icside_port_ops; | ||
535 | |||
536 | pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]); | ||
537 | } | ||
501 | 538 | ||
539 | return ata_host_activate(host, ec->irq, ata_interrupt, 0, | ||
540 | &pata_icside_sht); | ||
502 | } | 541 | } |
503 | 542 | ||
504 | static int __devinit | 543 | static int __devinit |
505 | pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) | 544 | pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) |
506 | { | 545 | { |
507 | struct pata_icside_state *state; | 546 | struct pata_icside_state *state; |
508 | struct ata_probe_ent ae; | 547 | struct pata_icside_info info; |
509 | void __iomem *idmem; | 548 | void __iomem *idmem; |
510 | int ret; | 549 | int ret; |
511 | 550 | ||
@@ -513,7 +552,7 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
513 | if (ret) | 552 | if (ret) |
514 | goto out; | 553 | goto out; |
515 | 554 | ||
516 | state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL); | 555 | state = devm_kzalloc(&ec->dev, sizeof(*state), GFP_KERNEL); |
517 | if (!state) { | 556 | if (!state) { |
518 | ret = -ENOMEM; | 557 | ret = -ENOMEM; |
519 | goto release; | 558 | goto release; |
@@ -535,16 +574,9 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
535 | state->type = type; | 574 | state->type = type; |
536 | } | 575 | } |
537 | 576 | ||
538 | memset(&ae, 0, sizeof(ae)); | 577 | memset(&info, 0, sizeof(info)); |
539 | INIT_LIST_HEAD(&ae.node); | 578 | info.state = state; |
540 | ae.dev = &ec->dev; | 579 | info.ec = ec; |
541 | ae.port_ops = &pata_icside_port_ops; | ||
542 | ae.sht = &pata_icside_sht; | ||
543 | ae.pio_mask = 0x1f; | ||
544 | ae.irq = ec->irq; | ||
545 | ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; | ||
546 | ae._host_flags = ATA_HOST_SIMPLEX; | ||
547 | ae.private_data = state; | ||
548 | 580 | ||
549 | switch (state->type) { | 581 | switch (state->type) { |
550 | case ICS_TYPE_A3IN: | 582 | case ICS_TYPE_A3IN: |
@@ -558,11 +590,11 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
558 | break; | 590 | break; |
559 | 591 | ||
560 | case ICS_TYPE_V5: | 592 | case ICS_TYPE_V5: |
561 | ret = pata_icside_register_v5(&ae, ec); | 593 | ret = pata_icside_register_v5(&info); |
562 | break; | 594 | break; |
563 | 595 | ||
564 | case ICS_TYPE_V6: | 596 | case ICS_TYPE_V6: |
565 | ret = pata_icside_register_v6(&ae, ec); | 597 | ret = pata_icside_register_v6(&info); |
566 | break; | 598 | break; |
567 | 599 | ||
568 | default: | 600 | default: |
@@ -572,12 +604,11 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
572 | } | 604 | } |
573 | 605 | ||
574 | if (ret == 0) | 606 | if (ret == 0) |
575 | ret = ata_device_add(&ae) == 0 ? -ENODEV : 0; | 607 | ret = pata_icside_add_ports(&info); |
576 | 608 | ||
577 | if (ret == 0) | 609 | if (ret == 0) |
578 | goto out; | 610 | goto out; |
579 | 611 | ||
580 | kfree(state); | ||
581 | release: | 612 | release: |
582 | ecard_release_resources(ec); | 613 | ecard_release_resources(ec); |
583 | out: | 614 | out: |
@@ -626,7 +657,6 @@ static void __devexit pata_icside_remove(struct expansion_card *ec) | |||
626 | if (state->dma != NO_DMA) | 657 | if (state->dma != NO_DMA) |
627 | free_dma(state->dma); | 658 | free_dma(state->dma); |
628 | 659 | ||
629 | kfree(state); | ||
630 | ecard_release_resources(ec); | 660 | ecard_release_resources(ec); |
631 | } | 661 | } |
632 | 662 | ||