diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_promise.c | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 4d18d5a59afe..07d8d00b4d34 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c | |||
@@ -56,6 +56,7 @@ enum { | |||
56 | /* host register offsets (from host->iomap[PDC_MMIO_BAR]) */ | 56 | /* host register offsets (from host->iomap[PDC_MMIO_BAR]) */ |
57 | PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ | 57 | PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ |
58 | PDC_FLASH_CTL = 0x44, /* Flash control register */ | 58 | PDC_FLASH_CTL = 0x44, /* Flash control register */ |
59 | PDC_PCI_CTL = 0x48, /* PCI control/status reg */ | ||
59 | PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ | 60 | PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ |
60 | PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ | 61 | PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ |
61 | PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ | 62 | PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ |
@@ -75,7 +76,17 @@ enum { | |||
75 | PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ | 76 | PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ |
76 | 77 | ||
77 | /* per-port SATA register offsets (from ap->ioaddr.scr_addr) */ | 78 | /* per-port SATA register offsets (from ap->ioaddr.scr_addr) */ |
79 | PDC_SATA_ERROR = 0x04, | ||
78 | PDC_PHYMODE4 = 0x14, | 80 | PDC_PHYMODE4 = 0x14, |
81 | PDC_LINK_LAYER_ERRORS = 0x6C, | ||
82 | PDC_FPDMA_CTLSTAT = 0xD8, | ||
83 | PDC_INTERNAL_DEBUG_1 = 0xF8, /* also used for PATA */ | ||
84 | PDC_INTERNAL_DEBUG_2 = 0xFC, /* also used for PATA */ | ||
85 | |||
86 | /* PDC_FPDMA_CTLSTAT bit definitions */ | ||
87 | PDC_FPDMA_CTLSTAT_RESET = 1 << 3, | ||
88 | PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG = 1 << 10, | ||
89 | PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG = 1 << 11, | ||
79 | 90 | ||
80 | /* PDC_GLOBAL_CTL bit definitions */ | 91 | /* PDC_GLOBAL_CTL bit definitions */ |
81 | PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */ | 92 | PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */ |
@@ -359,12 +370,76 @@ static int pdc_sata_port_start(struct ata_port *ap) | |||
359 | return 0; | 370 | return 0; |
360 | } | 371 | } |
361 | 372 | ||
373 | static void pdc_fpdma_clear_interrupt_flag(struct ata_port *ap) | ||
374 | { | ||
375 | void __iomem *sata_mmio = ap->ioaddr.scr_addr; | ||
376 | u32 tmp; | ||
377 | |||
378 | tmp = readl(sata_mmio + PDC_FPDMA_CTLSTAT); | ||
379 | tmp |= PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG; | ||
380 | tmp |= PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG; | ||
381 | |||
382 | /* It's not allowed to write to the entire FPDMA_CTLSTAT register | ||
383 | when NCQ is running. So do a byte-sized write to bits 10 and 11. */ | ||
384 | writeb(tmp >> 8, sata_mmio + PDC_FPDMA_CTLSTAT + 1); | ||
385 | readb(sata_mmio + PDC_FPDMA_CTLSTAT + 1); /* flush */ | ||
386 | } | ||
387 | |||
388 | static void pdc_fpdma_reset(struct ata_port *ap) | ||
389 | { | ||
390 | void __iomem *sata_mmio = ap->ioaddr.scr_addr; | ||
391 | u8 tmp; | ||
392 | |||
393 | tmp = (u8)readl(sata_mmio + PDC_FPDMA_CTLSTAT); | ||
394 | tmp &= 0x7F; | ||
395 | tmp |= PDC_FPDMA_CTLSTAT_RESET; | ||
396 | writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT); | ||
397 | readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */ | ||
398 | udelay(100); | ||
399 | tmp &= ~PDC_FPDMA_CTLSTAT_RESET; | ||
400 | writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT); | ||
401 | readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */ | ||
402 | |||
403 | pdc_fpdma_clear_interrupt_flag(ap); | ||
404 | } | ||
405 | |||
406 | static void pdc_not_at_command_packet_phase(struct ata_port *ap) | ||
407 | { | ||
408 | void __iomem *sata_mmio = ap->ioaddr.scr_addr; | ||
409 | unsigned int i; | ||
410 | u32 tmp; | ||
411 | |||
412 | /* check not at ASIC packet command phase */ | ||
413 | for (i = 0; i < 100; ++i) { | ||
414 | writel(0, sata_mmio + PDC_INTERNAL_DEBUG_1); | ||
415 | tmp = readl(sata_mmio + PDC_INTERNAL_DEBUG_2); | ||
416 | if ((tmp & 0xF) != 1) | ||
417 | break; | ||
418 | udelay(100); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | static void pdc_clear_internal_debug_record_error_register(struct ata_port *ap) | ||
423 | { | ||
424 | void __iomem *sata_mmio = ap->ioaddr.scr_addr; | ||
425 | |||
426 | writel(0xffffffff, sata_mmio + PDC_SATA_ERROR); | ||
427 | writel(0xffff0000, sata_mmio + PDC_LINK_LAYER_ERRORS); | ||
428 | } | ||
429 | |||
362 | static void pdc_reset_port(struct ata_port *ap) | 430 | static void pdc_reset_port(struct ata_port *ap) |
363 | { | 431 | { |
364 | void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; | 432 | void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; |
365 | unsigned int i; | 433 | unsigned int i; |
366 | u32 tmp; | 434 | u32 tmp; |
367 | 435 | ||
436 | if (ap->flags & PDC_FLAG_GEN_II) | ||
437 | pdc_not_at_command_packet_phase(ap); | ||
438 | |||
439 | tmp = readl(ata_ctlstat_mmio); | ||
440 | tmp |= PDC_RESET; | ||
441 | writel(tmp, ata_ctlstat_mmio); | ||
442 | |||
368 | for (i = 11; i > 0; i--) { | 443 | for (i = 11; i > 0; i--) { |
369 | tmp = readl(ata_ctlstat_mmio); | 444 | tmp = readl(ata_ctlstat_mmio); |
370 | if (tmp & PDC_RESET) | 445 | if (tmp & PDC_RESET) |
@@ -379,6 +454,11 @@ static void pdc_reset_port(struct ata_port *ap) | |||
379 | tmp &= ~PDC_RESET; | 454 | tmp &= ~PDC_RESET; |
380 | writel(tmp, ata_ctlstat_mmio); | 455 | writel(tmp, ata_ctlstat_mmio); |
381 | readl(ata_ctlstat_mmio); /* flush */ | 456 | readl(ata_ctlstat_mmio); /* flush */ |
457 | |||
458 | if (sata_scr_valid(&ap->link) && (ap->flags & PDC_FLAG_GEN_II)) { | ||
459 | pdc_fpdma_reset(ap); | ||
460 | pdc_clear_internal_debug_record_error_register(ap); | ||
461 | } | ||
382 | } | 462 | } |
383 | 463 | ||
384 | static int pdc_pata_cable_detect(struct ata_port *ap) | 464 | static int pdc_pata_cable_detect(struct ata_port *ap) |
@@ -706,11 +786,50 @@ static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, | |||
706 | return ata_sff_softreset(link, class, deadline); | 786 | return ata_sff_softreset(link, class, deadline); |
707 | } | 787 | } |
708 | 788 | ||
789 | static unsigned int pdc_ata_port_to_ata_no(const struct ata_port *ap) | ||
790 | { | ||
791 | void __iomem *ata_mmio = ap->ioaddr.cmd_addr; | ||
792 | void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; | ||
793 | |||
794 | /* ata_mmio == host_mmio + 0x200 + ata_no * 0x80 */ | ||
795 | return (ata_mmio - host_mmio - 0x200) / 0x80; | ||
796 | } | ||
797 | |||
798 | static void pdc_hard_reset_port(struct ata_port *ap) | ||
799 | { | ||
800 | void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; | ||
801 | void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; | ||
802 | unsigned int ata_no = pdc_ata_port_to_ata_no(ap); | ||
803 | u8 tmp; | ||
804 | |||
805 | spin_lock(&ap->host->lock); | ||
806 | |||
807 | tmp = readb(pcictl_b1_mmio); | ||
808 | tmp &= ~(0x10 << ata_no); | ||
809 | writeb(tmp, pcictl_b1_mmio); | ||
810 | readb(pcictl_b1_mmio); /* flush */ | ||
811 | udelay(100); | ||
812 | tmp |= (0x10 << ata_no); | ||
813 | writeb(tmp, pcictl_b1_mmio); | ||
814 | readb(pcictl_b1_mmio); /* flush */ | ||
815 | |||
816 | spin_unlock(&ap->host->lock); | ||
817 | } | ||
818 | |||
709 | static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, | 819 | static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, |
710 | unsigned long deadline) | 820 | unsigned long deadline) |
711 | { | 821 | { |
822 | if (link->ap->flags & PDC_FLAG_GEN_II) | ||
823 | pdc_not_at_command_packet_phase(link->ap); | ||
824 | /* hotplug IRQs should have been masked by pdc_sata_freeze() */ | ||
825 | pdc_hard_reset_port(link->ap); | ||
712 | pdc_reset_port(link->ap); | 826 | pdc_reset_port(link->ap); |
713 | return sata_sff_hardreset(link, class, deadline); | 827 | |
828 | /* sata_promise can't reliably acquire the first D2H Reg FIS | ||
829 | * after hardreset. Do non-waiting hardreset and request | ||
830 | * follow-up SRST. | ||
831 | */ | ||
832 | return sata_std_hardreset(link, class, deadline); | ||
714 | } | 833 | } |
715 | 834 | ||
716 | static void pdc_error_handler(struct ata_port *ap) | 835 | static void pdc_error_handler(struct ata_port *ap) |