diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fd27227771b4..c31b66366326 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -188,8 +188,10 @@ struct ahci_sg { | |||
188 | }; | 188 | }; |
189 | 189 | ||
190 | struct ahci_host_priv { | 190 | struct ahci_host_priv { |
191 | u32 cap; /* cache of HOST_CAP register */ | 191 | u32 cap; /* cap to use */ |
192 | u32 port_map; /* cache of HOST_PORTS_IMPL reg */ | 192 | u32 port_map; /* port map to use */ |
193 | u32 saved_cap; /* saved initial cap */ | ||
194 | u32 saved_port_map; /* saved initial port_map */ | ||
193 | }; | 195 | }; |
194 | 196 | ||
195 | struct ahci_port_priv { | 197 | struct ahci_port_priv { |
@@ -477,6 +479,65 @@ static inline void __iomem *ahci_port_base(void __iomem *base, | |||
477 | return base + 0x100 + (port * 0x80); | 479 | return base + 0x100 + (port * 0x80); |
478 | } | 480 | } |
479 | 481 | ||
482 | /** | ||
483 | * ahci_save_initial_config - Save and fixup initial config values | ||
484 | * @probe_ent: probe_ent of target device | ||
485 | * | ||
486 | * Some registers containing configuration info might be setup by | ||
487 | * BIOS and might be cleared on reset. This function saves the | ||
488 | * initial values of those registers into @hpriv such that they | ||
489 | * can be restored after controller reset. | ||
490 | * | ||
491 | * If inconsistent, config values are fixed up by this function. | ||
492 | * | ||
493 | * LOCKING: | ||
494 | * None. | ||
495 | */ | ||
496 | static void ahci_save_initial_config(struct ata_probe_ent *probe_ent) | ||
497 | { | ||
498 | struct ahci_host_priv *hpriv = probe_ent->private_data; | ||
499 | void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR]; | ||
500 | u32 cap, port_map; | ||
501 | |||
502 | /* Values prefixed with saved_ are written back to host after | ||
503 | * reset. Values without are used for driver operation. | ||
504 | */ | ||
505 | hpriv->saved_cap = cap = readl(mmio + HOST_CAP); | ||
506 | hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); | ||
507 | |||
508 | /* fixup zero port_map */ | ||
509 | if (!port_map) { | ||
510 | port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1; | ||
511 | dev_printk(KERN_WARNING, probe_ent->dev, | ||
512 | "PORTS_IMPL is zero, forcing 0x%x\n", port_map); | ||
513 | |||
514 | /* write the fixed up value to the PI register */ | ||
515 | hpriv->saved_port_map = port_map; | ||
516 | } | ||
517 | |||
518 | /* record values to use during operation */ | ||
519 | hpriv->cap = cap; | ||
520 | hpriv->port_map = port_map; | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * ahci_restore_initial_config - Restore initial config | ||
525 | * @mmio: MMIO base for the host | ||
526 | * @hpriv: host private data | ||
527 | * | ||
528 | * Restore initial config stored by ahci_save_initial_config(). | ||
529 | * | ||
530 | * LOCKING: | ||
531 | * None. | ||
532 | */ | ||
533 | static void ahci_restore_initial_config(void __iomem *mmio, | ||
534 | struct ahci_host_priv *hpriv) | ||
535 | { | ||
536 | writel(hpriv->saved_cap, mmio + HOST_CAP); | ||
537 | writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); | ||
538 | (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ | ||
539 | } | ||
540 | |||
480 | static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) | 541 | static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) |
481 | { | 542 | { |
482 | unsigned int sc_reg; | 543 | unsigned int sc_reg; |
@@ -653,12 +714,10 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) | |||
653 | return 0; | 714 | return 0; |
654 | } | 715 | } |
655 | 716 | ||
656 | static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) | 717 | static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev, |
718 | struct ahci_host_priv *hpriv) | ||
657 | { | 719 | { |
658 | u32 cap_save, impl_save, tmp; | 720 | u32 tmp; |
659 | |||
660 | cap_save = readl(mmio + HOST_CAP); | ||
661 | impl_save = readl(mmio + HOST_PORTS_IMPL); | ||
662 | 721 | ||
663 | /* global controller reset */ | 722 | /* global controller reset */ |
664 | tmp = readl(mmio + HOST_CTL); | 723 | tmp = readl(mmio + HOST_CTL); |
@@ -683,18 +742,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) | |||
683 | writel(HOST_AHCI_EN, mmio + HOST_CTL); | 742 | writel(HOST_AHCI_EN, mmio + HOST_CTL); |
684 | (void) readl(mmio + HOST_CTL); /* flush */ | 743 | (void) readl(mmio + HOST_CTL); /* flush */ |
685 | 744 | ||
686 | /* These write-once registers are normally cleared on reset. | 745 | /* some registers might be cleared on reset. restore initial values */ |
687 | * Restore BIOS values... which we HOPE were present before | 746 | ahci_restore_initial_config(mmio, hpriv); |
688 | * reset. | ||
689 | */ | ||
690 | if (!impl_save) { | ||
691 | impl_save = (1 << ahci_nr_ports(cap_save)) - 1; | ||
692 | dev_printk(KERN_WARNING, &pdev->dev, | ||
693 | "PORTS_IMPL is zero, forcing 0x%x\n", impl_save); | ||
694 | } | ||
695 | writel(cap_save, mmio + HOST_CAP); | ||
696 | writel(impl_save, mmio + HOST_PORTS_IMPL); | ||
697 | (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ | ||
698 | 747 | ||
699 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) { | 748 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) { |
700 | u16 tmp16; | 749 | u16 tmp16; |
@@ -1432,7 +1481,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) | |||
1432 | return rc; | 1481 | return rc; |
1433 | 1482 | ||
1434 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | 1483 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { |
1435 | rc = ahci_reset_controller(mmio, pdev); | 1484 | rc = ahci_reset_controller(mmio, pdev, hpriv); |
1436 | if (rc) | 1485 | if (rc) |
1437 | return rc; | 1486 | return rc; |
1438 | 1487 | ||
@@ -1543,12 +1592,10 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
1543 | unsigned int i, cap_n_ports, using_dac; | 1592 | unsigned int i, cap_n_ports, using_dac; |
1544 | int rc; | 1593 | int rc; |
1545 | 1594 | ||
1546 | rc = ahci_reset_controller(mmio, pdev); | 1595 | rc = ahci_reset_controller(mmio, pdev, hpriv); |
1547 | if (rc) | 1596 | if (rc) |
1548 | return rc; | 1597 | return rc; |
1549 | 1598 | ||
1550 | hpriv->cap = readl(mmio + HOST_CAP); | ||
1551 | hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); | ||
1552 | cap_n_ports = ahci_nr_ports(hpriv->cap); | 1599 | cap_n_ports = ahci_nr_ports(hpriv->cap); |
1553 | 1600 | ||
1554 | VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", | 1601 | VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", |
@@ -1739,6 +1786,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1739 | probe_ent->private_data = hpriv; | 1786 | probe_ent->private_data = hpriv; |
1740 | 1787 | ||
1741 | /* initialize adapter */ | 1788 | /* initialize adapter */ |
1789 | ahci_save_initial_config(probe_ent); | ||
1790 | |||
1742 | rc = ahci_host_init(probe_ent); | 1791 | rc = ahci_host_init(probe_ent); |
1743 | if (rc) | 1792 | if (rc) |
1744 | return rc; | 1793 | return rc; |