summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2011-12-14 12:54:11 +0800
committerRichard Zhu <r65037@freescale.com>2011-12-15 10:14:16 +0800
commit1f6ec0deec61b2d5c61859fb4d7445c54b70811b (patch)
treef725043d049bb8eb325acc4d9cb3f80d482402d5 /arch
parentbbce72cd663e8b82054ae4de7119929bb29a5fce (diff)
ENGR00170244-1 ARM: AHCI: Enable PDDQ mode when no disk is attached
In order to save the power consumption, enable the PDDQ mode of AHCI PHY when there is no sata disk on the port Signed-off-by: Richard Zhu <r65037@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-mxc/ahci_sata.c23
-rw-r--r--arch/arm/plat-mxc/include/mach/ahci_sata.h1
2 files changed, 22 insertions, 2 deletions
diff --git a/arch/arm/plat-mxc/ahci_sata.c b/arch/arm/plat-mxc/ahci_sata.c
index ab4fcf86bc4c..0d78a123a469 100644
--- a/arch/arm/plat-mxc/ahci_sata.c
+++ b/arch/arm/plat-mxc/ahci_sata.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/delay.h>
+#include <asm/errno.h>
#include <mach/ahci_sata.h>
int write_phy_ctl_ack_polling(u32 data, void __iomem *mmio,
@@ -37,7 +38,7 @@ int write_phy_ctl_ack_polling(u32 data, void __iomem *mmio,
if (val == exp_val)
return 0;
if (i == max_iterations) {
- printk(KERN_ERR "Wait for CR ACK error!\n");
+ pr_err("Wait for CR ACK error!\n");
return 1;
}
usleep_range(100, 200);
@@ -137,6 +138,7 @@ int sata_phy_cr_read(u32 *data, void __iomem *mmio)
int sata_init(void __iomem *addr, unsigned long timer1ms)
{
u32 tmpdata;
+ int iterations = 20;
/* Reset HBA */
writel(HOST_RESET, addr + HOST_CTL);
@@ -146,7 +148,7 @@ int sata_init(void __iomem *addr, unsigned long timer1ms)
while (readl(addr + HOST_VERSIONR) == 0) {
tmpdata++;
if (tmpdata > 100000) {
- printk(KERN_ERR "Can't recover from RESET HBA!\n");
+ pr_err("Can't recover from RESET HBA!\n");
break;
}
}
@@ -164,5 +166,22 @@ int sata_init(void __iomem *addr, unsigned long timer1ms)
writel(timer1ms, addr + HOST_TIMER1MS);
+ /* Release resources when there is no device on the port */
+ do {
+ if ((readl(addr + PORT_SATA_SR) & 0xF) == 0)
+ msleep(25);
+ else
+ break;
+
+ if (iterations == 0) {
+ pr_info("No sata disk.\n");
+ /* Enter into PDDQ mode, save power */
+ tmpdata = readl(addr + PORT_PHY_CTL);
+ writel(tmpdata | PORT_PHY_CTL_PDDQ_LOC,
+ addr + PORT_PHY_CTL);
+ return -ENODEV;
+ }
+ } while (iterations-- > 0);
+
return 0;
}
diff --git a/arch/arm/plat-mxc/include/mach/ahci_sata.h b/arch/arm/plat-mxc/include/mach/ahci_sata.h
index edca22b4fc04..48b93e55eea0 100644
--- a/arch/arm/plat-mxc/include/mach/ahci_sata.h
+++ b/arch/arm/plat-mxc/include/mach/ahci_sata.h
@@ -39,6 +39,7 @@ enum {
PORT_PHY_CTL_CAP_DAT_LOC = 0x20000,
PORT_PHY_CTL_WRITE_LOC = 0x40000,
PORT_PHY_CTL_READ_LOC = 0x80000,
+ PORT_PHY_CTL_PDDQ_LOC = 0x100000,
/* Port0 PHY Status */
PORT_PHY_SR = 0x17c,
/* PORT_PHY_SR */