aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-03-18 09:15:33 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-28 14:16:01 -0400
commitd447df140d0f07a02bd221cb42eb0b61bce16042 (patch)
tree7ce228513178cdce89db5d93cb7bd4c04be1a771
parentce2d3abc292c1eecd9ddc6f03391a0a46c6561dc (diff)
ahci: implement ata_save/restore_initial_config()
There are several registers which describe how the controller is configured. These registers are sometimes implemented as r/w registers which are configured by firmware and get cleared on controller reset or after suspend/resume cycle. ahci saved and restored those values inside ahci_reset_controller() which is a bit messy and doesn't work over suspend/resume cycle. This patch implements ahci_save/restore_initial_config(). The save function is called during driver initialization and saves cap and port_map to hpriv. The restore function is called after the controller is reset to restore the initial values. Sometimes the initial firmware values are inconsistent and need to be fixed up. This is handled by ahci_save_initial_config(). For this, there are two versions of saved registers. One to write back to the hardware register, the other to use during driver operation. This is necessary to keep ahci's behavior unchanged (write back fixed up port_map while keeping cap as-is). This patch makes ahci save the register values once before the first controller reset, not after it's been reset. Also, the same stored values are used written back after each reset, so the register values are properly recovered after suspend/resume cycle. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/ahci.c95
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
190struct ahci_host_priv { 190struct 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
195struct ahci_port_priv { 197struct 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 */
496static 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 */
533static 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
480static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) 541static 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
656static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) 717static 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;