diff options
-rw-r--r-- | drivers/ata/sata_promise.c | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 6f7bc5b0ef4a..f055874a6ec5 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c | |||
@@ -71,9 +71,12 @@ enum { | |||
71 | 71 | ||
72 | PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ | 72 | PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ |
73 | 73 | ||
74 | /* PDC_CTLSTAT bit definitions */ | ||
75 | PDC_DMA_ENABLE = (1 << 7), | ||
76 | PDC_IRQ_DISABLE = (1 << 10), | ||
74 | PDC_RESET = (1 << 11), /* HDMA reset */ | 77 | PDC_RESET = (1 << 11), /* HDMA reset */ |
75 | 78 | ||
76 | PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | | 79 | PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | |
77 | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | | 80 | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | |
78 | ATA_FLAG_PIO_POLLING, | 81 | ATA_FLAG_PIO_POLLING, |
79 | 82 | ||
@@ -99,13 +102,16 @@ static void pdc_eng_timeout(struct ata_port *ap); | |||
99 | static int pdc_port_start(struct ata_port *ap); | 102 | static int pdc_port_start(struct ata_port *ap); |
100 | static void pdc_port_stop(struct ata_port *ap); | 103 | static void pdc_port_stop(struct ata_port *ap); |
101 | static void pdc_pata_phy_reset(struct ata_port *ap); | 104 | static void pdc_pata_phy_reset(struct ata_port *ap); |
102 | static void pdc_sata_phy_reset(struct ata_port *ap); | ||
103 | static void pdc_qc_prep(struct ata_queued_cmd *qc); | 105 | static void pdc_qc_prep(struct ata_queued_cmd *qc); |
104 | static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); | 106 | static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); |
105 | static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); | 107 | static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); |
106 | static void pdc_irq_clear(struct ata_port *ap); | 108 | static void pdc_irq_clear(struct ata_port *ap); |
107 | static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); | 109 | static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); |
108 | static void pdc_host_stop(struct ata_host *host); | 110 | static void pdc_host_stop(struct ata_host *host); |
111 | static void pdc_freeze(struct ata_port *ap); | ||
112 | static void pdc_thaw(struct ata_port *ap); | ||
113 | static void pdc_error_handler(struct ata_port *ap); | ||
114 | static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); | ||
109 | 115 | ||
110 | 116 | ||
111 | static struct scsi_host_template pdc_ata_sht = { | 117 | static struct scsi_host_template pdc_ata_sht = { |
@@ -134,11 +140,12 @@ static const struct ata_port_operations pdc_sata_ops = { | |||
134 | .exec_command = pdc_exec_command_mmio, | 140 | .exec_command = pdc_exec_command_mmio, |
135 | .dev_select = ata_std_dev_select, | 141 | .dev_select = ata_std_dev_select, |
136 | 142 | ||
137 | .phy_reset = pdc_sata_phy_reset, | ||
138 | |||
139 | .qc_prep = pdc_qc_prep, | 143 | .qc_prep = pdc_qc_prep, |
140 | .qc_issue = pdc_qc_issue_prot, | 144 | .qc_issue = pdc_qc_issue_prot, |
141 | .eng_timeout = pdc_eng_timeout, | 145 | .freeze = pdc_freeze, |
146 | .thaw = pdc_thaw, | ||
147 | .error_handler = pdc_error_handler, | ||
148 | .post_internal_cmd = pdc_post_internal_cmd, | ||
142 | .data_xfer = ata_mmio_data_xfer, | 149 | .data_xfer = ata_mmio_data_xfer, |
143 | .irq_handler = pdc_interrupt, | 150 | .irq_handler = pdc_interrupt, |
144 | .irq_clear = pdc_irq_clear, | 151 | .irq_clear = pdc_irq_clear, |
@@ -196,7 +203,7 @@ static const struct ata_port_info pdc_port_info[] = { | |||
196 | /* board_20619 */ | 203 | /* board_20619 */ |
197 | { | 204 | { |
198 | .sht = &pdc_ata_sht, | 205 | .sht = &pdc_ata_sht, |
199 | .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, | 206 | .flags = PDC_COMMON_FLAGS | ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, |
200 | .pio_mask = 0x1f, /* pio0-4 */ | 207 | .pio_mask = 0x1f, /* pio0-4 */ |
201 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 208 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
202 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 209 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
@@ -346,12 +353,6 @@ static void pdc_reset_port(struct ata_port *ap) | |||
346 | readl(mmio); /* flush */ | 353 | readl(mmio); /* flush */ |
347 | } | 354 | } |
348 | 355 | ||
349 | static void pdc_sata_phy_reset(struct ata_port *ap) | ||
350 | { | ||
351 | pdc_reset_port(ap); | ||
352 | sata_phy_reset(ap); | ||
353 | } | ||
354 | |||
355 | static void pdc_pata_cbl_detect(struct ata_port *ap) | 356 | static void pdc_pata_cbl_detect(struct ata_port *ap) |
356 | { | 357 | { |
357 | u8 tmp; | 358 | u8 tmp; |
@@ -419,6 +420,61 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) | |||
419 | } | 420 | } |
420 | } | 421 | } |
421 | 422 | ||
423 | static void pdc_freeze(struct ata_port *ap) | ||
424 | { | ||
425 | void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; | ||
426 | u32 tmp; | ||
427 | |||
428 | tmp = readl(mmio + PDC_CTLSTAT); | ||
429 | tmp |= PDC_IRQ_DISABLE; | ||
430 | tmp &= ~PDC_DMA_ENABLE; | ||
431 | writel(tmp, mmio + PDC_CTLSTAT); | ||
432 | readl(mmio + PDC_CTLSTAT); /* flush */ | ||
433 | } | ||
434 | |||
435 | static void pdc_thaw(struct ata_port *ap) | ||
436 | { | ||
437 | void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; | ||
438 | u32 tmp; | ||
439 | |||
440 | /* clear IRQ */ | ||
441 | readl(mmio + PDC_INT_SEQMASK); | ||
442 | |||
443 | /* turn IRQ back on */ | ||
444 | tmp = readl(mmio + PDC_CTLSTAT); | ||
445 | tmp &= ~PDC_IRQ_DISABLE; | ||
446 | writel(tmp, mmio + PDC_CTLSTAT); | ||
447 | readl(mmio + PDC_CTLSTAT); /* flush */ | ||
448 | } | ||
449 | |||
450 | static void pdc_error_handler(struct ata_port *ap) | ||
451 | { | ||
452 | ata_reset_fn_t hardreset; | ||
453 | |||
454 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) | ||
455 | pdc_reset_port(ap); | ||
456 | |||
457 | hardreset = NULL; | ||
458 | if (sata_scr_valid(ap)) | ||
459 | hardreset = sata_std_hardreset; | ||
460 | |||
461 | /* perform recovery */ | ||
462 | ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, | ||
463 | ata_std_postreset); | ||
464 | } | ||
465 | |||
466 | static void pdc_post_internal_cmd(struct ata_queued_cmd *qc) | ||
467 | { | ||
468 | struct ata_port *ap = qc->ap; | ||
469 | |||
470 | if (qc->flags & ATA_QCFLAG_FAILED) | ||
471 | qc->err_mask |= AC_ERR_OTHER; | ||
472 | |||
473 | /* make DMA engine forget about the failed command */ | ||
474 | if (qc->err_mask) | ||
475 | pdc_reset_port(ap); | ||
476 | } | ||
477 | |||
422 | static void pdc_eng_timeout(struct ata_port *ap) | 478 | static void pdc_eng_timeout(struct ata_port *ap) |
423 | { | 479 | { |
424 | struct ata_host *host = ap->host; | 480 | struct ata_host *host = ap->host; |