aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sata_sil24.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sata_sil24.c')
-rw-r--r--drivers/scsi/sata_sil24.c76
1 files changed, 66 insertions, 10 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index a6836a07a9eb..59aab163bcdc 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -333,7 +333,7 @@ static struct ata_port_info sil24_port_info[] = {
333 { 333 {
334 .sht = &sil24_sht, 334 .sht = &sil24_sht,
335 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 335 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
336 ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 336 ATA_FLAG_SRST | ATA_FLAG_MMIO |
337 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4), 337 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
338 .pio_mask = 0x1f, /* pio0-4 */ 338 .pio_mask = 0x1f, /* pio0-4 */
339 .mwdma_mask = 0x07, /* mwdma0-2 */ 339 .mwdma_mask = 0x07, /* mwdma0-2 */
@@ -344,7 +344,7 @@ static struct ata_port_info sil24_port_info[] = {
344 { 344 {
345 .sht = &sil24_sht, 345 .sht = &sil24_sht,
346 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 346 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
347 ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 347 ATA_FLAG_SRST | ATA_FLAG_MMIO |
348 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2), 348 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
349 .pio_mask = 0x1f, /* pio0-4 */ 349 .pio_mask = 0x1f, /* pio0-4 */
350 .mwdma_mask = 0x07, /* mwdma0-2 */ 350 .mwdma_mask = 0x07, /* mwdma0-2 */
@@ -355,7 +355,7 @@ static struct ata_port_info sil24_port_info[] = {
355 { 355 {
356 .sht = &sil24_sht, 356 .sht = &sil24_sht,
357 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 357 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
358 ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 358 ATA_FLAG_SRST | ATA_FLAG_MMIO |
359 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1), 359 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
360 .pio_mask = 0x1f, /* pio0-4 */ 360 .pio_mask = 0x1f, /* pio0-4 */
361 .mwdma_mask = 0x07, /* mwdma0-2 */ 361 .mwdma_mask = 0x07, /* mwdma0-2 */
@@ -415,16 +415,72 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
415 *tf = pp->tf; 415 *tf = pp->tf;
416} 416}
417 417
418static void sil24_phy_reset(struct ata_port *ap) 418static int sil24_issue_SRST(struct ata_port *ap)
419{ 419{
420 __sata_phy_reset(ap); 420 void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
421 struct sil24_port_priv *pp = ap->private_data;
422 struct sil24_prb *prb = &pp->cmd_block[0].prb;
423 dma_addr_t paddr = pp->cmd_block_dma;
424 u32 irq_enable, irq_stat;
425 int cnt;
426
427 /* temporarily turn off IRQs during SRST */
428 irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
429 writel(irq_enable, port + PORT_IRQ_ENABLE_CLR);
430
421 /* 431 /*
422 * No ATAPI yet. Just unconditionally indicate ATA device. 432 * XXX: Not sure whether the following sleep is needed or not.
423 * If ATAPI device is attached, it will fail ATA_CMD_ID_ATA 433 * The original driver had it. So....
424 * and libata core will ignore the device.
425 */ 434 */
426 if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) 435 msleep(10);
427 ap->device[0].class = ATA_DEV_ATA; 436
437 prb->ctrl = PRB_CTRL_SRST;
438 prb->fis[1] = 0; /* no PM yet */
439
440 writel((u32)paddr, port + PORT_CMD_ACTIVATE);
441
442 for (cnt = 0; cnt < 100; cnt++) {
443 irq_stat = readl(port + PORT_IRQ_STAT);
444 writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
445
446 irq_stat >>= PORT_IRQ_RAW_SHIFT;
447 if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
448 break;
449
450 msleep(1);
451 }
452
453 /* restore IRQs */
454 writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
455
456 if (!(irq_stat & PORT_IRQ_COMPLETE))
457 return -1;
458
459 /* update TF */
460 sil24_update_tf(ap);
461 return 0;
462}
463
464static void sil24_phy_reset(struct ata_port *ap)
465{
466 struct sil24_port_priv *pp = ap->private_data;
467
468 __sata_phy_reset(ap);
469 if (ap->flags & ATA_FLAG_PORT_DISABLED)
470 return;
471
472 if (sil24_issue_SRST(ap) < 0) {
473 printk(KERN_ERR DRV_NAME
474 " ata%u: SRST failed, disabling port\n", ap->id);
475 ap->ops->port_disable(ap);
476 return;
477 }
478
479 ap->device->class = ata_dev_classify(&pp->tf);
480
481 /* No ATAPI yet */
482 if (ap->device->class == ATA_DEV_ATAPI)
483 ap->ops->port_disable(ap);
428} 484}
429 485
430static inline void sil24_fill_sg(struct ata_queued_cmd *qc, 486static inline void sil24_fill_sg(struct ata_queued_cmd *qc,