diff options
Diffstat (limited to 'drivers/scsi/sata_sil24.c')
-rw-r--r-- | drivers/scsi/sata_sil24.c | 76 |
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 | ||
418 | static void sil24_phy_reset(struct ata_port *ap) | 418 | static 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 | |||
464 | static 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 | ||
430 | static inline void sil24_fill_sg(struct ata_queued_cmd *qc, | 486 | static inline void sil24_fill_sg(struct ata_queued_cmd *qc, |