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 /drivers/ata/ahci.c | |
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>
Diffstat (limited to 'drivers/ata/ahci.c')
-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); |