aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_mv.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2013-12-26 12:25:41 -0500
committerTejun Heo <tj@kernel.org>2014-01-20 07:46:15 -0500
commitb7db4f2e15603c394da56a0536a33669f4c87c4f (patch)
tree086a200e4a87f30ce62b16d489a7be3aa17e6c11 /drivers/ata/sata_mv.c
parent3a3a8cf51df49e61dce7e623fb2bcc1a9e560efe (diff)
SATA: MV: Add support for the optional PHYs
Some Marvell SoCs have a SATA PHY which can be powered off, in order to save power. Make use of the generic phy framework to control these phys. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r--drivers/ata/sata_mv.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index dc9d4b1ea4ec..20a7517bd339 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -60,6 +60,7 @@
60#include <linux/dma-mapping.h> 60#include <linux/dma-mapping.h>
61#include <linux/device.h> 61#include <linux/device.h>
62#include <linux/clk.h> 62#include <linux/clk.h>
63#include <linux/phy/phy.h>
63#include <linux/platform_device.h> 64#include <linux/platform_device.h>
64#include <linux/ata_platform.h> 65#include <linux/ata_platform.h>
65#include <linux/mbus.h> 66#include <linux/mbus.h>
@@ -565,6 +566,12 @@ struct mv_host_priv {
565 struct clk *clk; 566 struct clk *clk;
566 struct clk **port_clks; 567 struct clk **port_clks;
567 /* 568 /*
569 * Some devices have a SATA PHY which can be enabled/disabled
570 * in order to save power. These are optional: if the platform
571 * devices does not have any phy, they won't be used.
572 */
573 struct phy **port_phys;
574 /*
568 * These consistent DMA memory pools give us guaranteed 575 * These consistent DMA memory pools give us guaranteed
569 * alignment for hardware-accessed data structures, 576 * alignment for hardware-accessed data structures,
570 * and less memory waste in accomplishing the alignment. 577 * and less memory waste in accomplishing the alignment.
@@ -4091,6 +4098,11 @@ static int mv_platform_probe(struct platform_device *pdev)
4091 GFP_KERNEL); 4098 GFP_KERNEL);
4092 if (!hpriv->port_clks) 4099 if (!hpriv->port_clks)
4093 return -ENOMEM; 4100 return -ENOMEM;
4101 hpriv->port_phys = devm_kzalloc(&pdev->dev,
4102 sizeof(struct phy *) * n_ports,
4103 GFP_KERNEL);
4104 if (!hpriv->port_phys)
4105 return -ENOMEM;
4094 host->private_data = hpriv; 4106 host->private_data = hpriv;
4095 hpriv->n_ports = n_ports; 4107 hpriv->n_ports = n_ports;
4096 hpriv->board_idx = chip_soc; 4108 hpriv->board_idx = chip_soc;
@@ -4112,6 +4124,17 @@ static int mv_platform_probe(struct platform_device *pdev)
4112 hpriv->port_clks[port] = clk_get(&pdev->dev, port_number); 4124 hpriv->port_clks[port] = clk_get(&pdev->dev, port_number);
4113 if (!IS_ERR(hpriv->port_clks[port])) 4125 if (!IS_ERR(hpriv->port_clks[port]))
4114 clk_prepare_enable(hpriv->port_clks[port]); 4126 clk_prepare_enable(hpriv->port_clks[port]);
4127
4128 sprintf(port_number, "port%d", port);
4129 hpriv->port_phys[port] = devm_phy_get(&pdev->dev, port_number);
4130 if (IS_ERR(hpriv->port_phys[port])) {
4131 rc = PTR_ERR(hpriv->port_phys[port]);
4132 hpriv->port_phys[port] = NULL;
4133 if ((rc != -EPROBE_DEFER) && (rc != -ENODEV))
4134 dev_warn(&pdev->dev, "error getting phy");
4135 goto err;
4136 } else
4137 phy_power_on(hpriv->port_phys[port]);
4115 } 4138 }
4116 4139
4117 /* 4140 /*
@@ -4156,6 +4179,8 @@ err:
4156 clk_disable_unprepare(hpriv->port_clks[port]); 4179 clk_disable_unprepare(hpriv->port_clks[port]);
4157 clk_put(hpriv->port_clks[port]); 4180 clk_put(hpriv->port_clks[port]);
4158 } 4181 }
4182 if (hpriv->port_phys[port])
4183 phy_power_off(hpriv->port_phys[port]);
4159 } 4184 }
4160 4185
4161 return rc; 4186 return rc;
@@ -4185,6 +4210,8 @@ static int mv_platform_remove(struct platform_device *pdev)
4185 clk_disable_unprepare(hpriv->port_clks[port]); 4210 clk_disable_unprepare(hpriv->port_clks[port]);
4186 clk_put(hpriv->port_clks[port]); 4211 clk_put(hpriv->port_clks[port]);
4187 } 4212 }
4213 if (hpriv->port_phys[port])
4214 phy_power_off(hpriv->port_phys[port]);
4188 } 4215 }
4189 return 0; 4216 return 0;
4190} 4217}