diff options
| author | Tejun Heo <htejun@gmail.com> | 2008-01-05 09:11:57 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2008-01-23 05:24:16 -0500 |
| commit | b710a1f4b34438b624e9c6c2dc8bcf54b0b0ba27 (patch) | |
| tree | f8bb87bd4cbc2591da8c0b9bdaf01b426902800b | |
| parent | c729072459446885c5c200137de1db32da5db4dc (diff) | |
ahci: factor out AHCI enabling and enable AHCI before reading CAP
Factor out AHCI enabling into ahci_enable_ahci() and enabling AHCI
before reading CAP in ahci_save_initial_config() as the spec requires
enabling AHCI mode before accessing any other registers.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/ata/ahci.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 49761bc12cf2..6f089b899a1a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -597,6 +597,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap) | |||
| 597 | return __ahci_port_base(ap->host, ap->port_no); | 597 | return __ahci_port_base(ap->host, ap->port_no); |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | static void ahci_enable_ahci(void __iomem *mmio) | ||
| 601 | { | ||
| 602 | u32 tmp; | ||
| 603 | |||
| 604 | /* turn on AHCI_EN */ | ||
| 605 | tmp = readl(mmio + HOST_CTL); | ||
| 606 | if (!(tmp & HOST_AHCI_EN)) { | ||
| 607 | tmp |= HOST_AHCI_EN; | ||
| 608 | writel(tmp, mmio + HOST_CTL); | ||
| 609 | tmp = readl(mmio + HOST_CTL); /* flush && sanity check */ | ||
| 610 | WARN_ON(!(tmp & HOST_AHCI_EN)); | ||
| 611 | } | ||
| 612 | } | ||
| 613 | |||
| 600 | /** | 614 | /** |
| 601 | * ahci_save_initial_config - Save and fixup initial config values | 615 | * ahci_save_initial_config - Save and fixup initial config values |
| 602 | * @pdev: target PCI device | 616 | * @pdev: target PCI device |
| @@ -619,6 +633,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
| 619 | u32 cap, port_map; | 633 | u32 cap, port_map; |
| 620 | int i; | 634 | int i; |
| 621 | 635 | ||
| 636 | /* make sure AHCI mode is enabled before accessing CAP */ | ||
| 637 | ahci_enable_ahci(mmio); | ||
| 638 | |||
| 622 | /* Values prefixed with saved_ are written back to host after | 639 | /* Values prefixed with saved_ are written back to host after |
| 623 | * reset. Values without are used for driver operation. | 640 | * reset. Values without are used for driver operation. |
| 624 | */ | 641 | */ |
| @@ -1043,13 +1060,10 @@ static int ahci_reset_controller(struct ata_host *host) | |||
| 1043 | /* we must be in AHCI mode, before using anything | 1060 | /* we must be in AHCI mode, before using anything |
| 1044 | * AHCI-specific, such as HOST_RESET. | 1061 | * AHCI-specific, such as HOST_RESET. |
| 1045 | */ | 1062 | */ |
| 1046 | tmp = readl(mmio + HOST_CTL); | 1063 | ahci_enable_ahci(mmio); |
| 1047 | if (!(tmp & HOST_AHCI_EN)) { | ||
| 1048 | tmp |= HOST_AHCI_EN; | ||
| 1049 | writel(tmp, mmio + HOST_CTL); | ||
| 1050 | } | ||
| 1051 | 1064 | ||
| 1052 | /* global controller reset */ | 1065 | /* global controller reset */ |
| 1066 | tmp = readl(mmio + HOST_CTL); | ||
| 1053 | if ((tmp & HOST_RESET) == 0) { | 1067 | if ((tmp & HOST_RESET) == 0) { |
| 1054 | writel(tmp | HOST_RESET, mmio + HOST_CTL); | 1068 | writel(tmp | HOST_RESET, mmio + HOST_CTL); |
| 1055 | readl(mmio + HOST_CTL); /* flush */ | 1069 | readl(mmio + HOST_CTL); /* flush */ |
| @@ -1068,8 +1082,7 @@ static int ahci_reset_controller(struct ata_host *host) | |||
| 1068 | } | 1082 | } |
| 1069 | 1083 | ||
| 1070 | /* turn on AHCI mode */ | 1084 | /* turn on AHCI mode */ |
| 1071 | writel(HOST_AHCI_EN, mmio + HOST_CTL); | 1085 | ahci_enable_ahci(mmio); |
| 1072 | (void) readl(mmio + HOST_CTL); /* flush */ | ||
| 1073 | 1086 | ||
| 1074 | /* some registers might be cleared on reset. restore initial values */ | 1087 | /* some registers might be cleared on reset. restore initial values */ |
| 1075 | ahci_restore_initial_config(host); | 1088 | ahci_restore_initial_config(host); |
