diff options
author | Marek Vasut <marex@denx.de> | 2013-11-25 03:47:01 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-12-03 07:40:57 -0500 |
commit | 8403e2ec8d4c759f821996d3bc43ca7c512ac9a0 (patch) | |
tree | 39192b6bfe266f23882bee90f0441128b2f30a62 /drivers | |
parent | c869325a45ce3369d456d7632409b675c3adb7ce (diff) |
ahci: imx: Pull out the clock enable/disable calls
The same code for enabling and disabling SATA clock was found in multiple
places in the driver. Implement functions that enable/disable the SATA clock
and use them in such places instead of duplicating the code.
Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Richard Zhu <r65037@freescale.com>
Cc: Linux-IDE <linux-ide@vger.kernel.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/ahci_imx.c | 143 |
1 files changed, 75 insertions, 68 deletions
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 3e23e9941dad..6214411349de 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c | |||
@@ -47,6 +47,36 @@ static int ahci_imx_hotplug; | |||
47 | module_param_named(hotplug, ahci_imx_hotplug, int, 0644); | 47 | module_param_named(hotplug, ahci_imx_hotplug, int, 0644); |
48 | MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); | 48 | MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); |
49 | 49 | ||
50 | static int imx_sata_clock_enable(struct device *dev) | ||
51 | { | ||
52 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | ||
53 | int ret; | ||
54 | |||
55 | ret = clk_prepare_enable(imxpriv->sata_ref_clk); | ||
56 | if (ret < 0) { | ||
57 | dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | ||
62 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
63 | IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
64 | |||
65 | usleep_range(1000, 2000); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static void imx_sata_clock_disable(struct device *dev) | ||
71 | { | ||
72 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | ||
73 | |||
74 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | ||
75 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
76 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
77 | clk_disable_unprepare(imxpriv->sata_ref_clk); | ||
78 | } | ||
79 | |||
50 | static void ahci_imx_error_handler(struct ata_port *ap) | 80 | static void ahci_imx_error_handler(struct ata_port *ap) |
51 | { | 81 | { |
52 | u32 reg_val; | 82 | u32 reg_val; |
@@ -72,10 +102,7 @@ static void ahci_imx_error_handler(struct ata_port *ap) | |||
72 | */ | 102 | */ |
73 | reg_val = readl(mmio + PORT_PHY_CTL); | 103 | reg_val = readl(mmio + PORT_PHY_CTL); |
74 | writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); | 104 | writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); |
75 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | 105 | imx_sata_clock_disable(ap->dev); |
76 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
77 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
78 | clk_disable_unprepare(imxpriv->sata_ref_clk); | ||
79 | imxpriv->no_device = true; | 106 | imxpriv->no_device = true; |
80 | } | 107 | } |
81 | 108 | ||
@@ -97,46 +124,9 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) | |||
97 | unsigned int reg_val; | 124 | unsigned int reg_val; |
98 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | 125 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); |
99 | 126 | ||
100 | imxpriv->gpr = | 127 | ret = imx_sata_clock_enable(dev); |
101 | syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); | 128 | if (ret < 0) |
102 | if (IS_ERR(imxpriv->gpr)) { | ||
103 | dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); | ||
104 | return PTR_ERR(imxpriv->gpr); | ||
105 | } | ||
106 | |||
107 | ret = clk_prepare_enable(imxpriv->sata_ref_clk); | ||
108 | if (ret < 0) { | ||
109 | dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); | ||
110 | return ret; | 129 | return ret; |
111 | } | ||
112 | |||
113 | /* | ||
114 | * set PHY Paremeters, two steps to configure the GPR13, | ||
115 | * one write for rest of parameters, mask of first write | ||
116 | * is 0x07ffffff, and the other one write for setting | ||
117 | * the mpll_clk_en. | ||
118 | */ | ||
119 | regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | ||
120 | | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | ||
121 | | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | ||
122 | | IMX6Q_GPR13_SATA_SPD_MODE_MASK | ||
123 | | IMX6Q_GPR13_SATA_MPLL_SS_EN | ||
124 | | IMX6Q_GPR13_SATA_TX_ATTEN_MASK | ||
125 | | IMX6Q_GPR13_SATA_TX_BOOST_MASK | ||
126 | | IMX6Q_GPR13_SATA_TX_LVL_MASK | ||
127 | | IMX6Q_GPR13_SATA_MPLL_CLK_EN | ||
128 | | IMX6Q_GPR13_SATA_TX_EDGE_RATE | ||
129 | , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | ||
130 | | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | ||
131 | | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | ||
132 | | IMX6Q_GPR13_SATA_SPD_MODE_3P0G | ||
133 | | IMX6Q_GPR13_SATA_MPLL_SS_EN | ||
134 | | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | ||
135 | | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | ||
136 | | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); | ||
137 | regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
138 | IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
139 | usleep_range(100, 200); | ||
140 | 130 | ||
141 | /* | 131 | /* |
142 | * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, | 132 | * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, |
@@ -164,11 +154,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) | |||
164 | 154 | ||
165 | static void imx6q_sata_exit(struct device *dev) | 155 | static void imx6q_sata_exit(struct device *dev) |
166 | { | 156 | { |
167 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | 157 | imx_sata_clock_disable(dev); |
168 | |||
169 | regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
170 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
171 | clk_disable_unprepare(imxpriv->sata_ref_clk); | ||
172 | } | 158 | } |
173 | 159 | ||
174 | static int imx_ahci_suspend(struct device *dev) | 160 | static int imx_ahci_suspend(struct device *dev) |
@@ -179,12 +165,8 @@ static int imx_ahci_suspend(struct device *dev) | |||
179 | * If no_device is set, The CLKs had been gated off in the | 165 | * If no_device is set, The CLKs had been gated off in the |
180 | * initialization so don't do it again here. | 166 | * initialization so don't do it again here. |
181 | */ | 167 | */ |
182 | if (!imxpriv->no_device) { | 168 | if (!imxpriv->no_device) |
183 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | 169 | imx_sata_clock_disable(dev); |
184 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
185 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
186 | clk_disable_unprepare(imxpriv->sata_ref_clk); | ||
187 | } | ||
188 | 170 | ||
189 | return 0; | 171 | return 0; |
190 | } | 172 | } |
@@ -192,22 +174,12 @@ static int imx_ahci_suspend(struct device *dev) | |||
192 | static int imx_ahci_resume(struct device *dev) | 174 | static int imx_ahci_resume(struct device *dev) |
193 | { | 175 | { |
194 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | 176 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); |
195 | int ret; | 177 | int ret = 0; |
196 | 178 | ||
197 | if (!imxpriv->no_device) { | 179 | if (!imxpriv->no_device) |
198 | ret = clk_prepare_enable(imxpriv->sata_ref_clk); | 180 | ret = imx_sata_clock_enable(dev); |
199 | if (ret < 0) { | ||
200 | dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret); | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | ||
205 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | ||
206 | IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
207 | usleep_range(1000, 2000); | ||
208 | } | ||
209 | 181 | ||
210 | return 0; | 182 | return ret; |
211 | } | 183 | } |
212 | 184 | ||
213 | static struct ahci_platform_data imx6q_sata_pdata = { | 185 | static struct ahci_platform_data imx6q_sata_pdata = { |
@@ -290,6 +262,41 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
290 | ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; | 262 | ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; |
291 | ahci_dev->of_node = dev->of_node; | 263 | ahci_dev->of_node = dev->of_node; |
292 | 264 | ||
265 | imxpriv->gpr = | ||
266 | syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); | ||
267 | |||
268 | if (IS_ERR(imxpriv->gpr)) { | ||
269 | dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); | ||
270 | ret = PTR_ERR(imxpriv->gpr); | ||
271 | goto err_out; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Set PHY Paremeters, two steps to configure the GPR13, | ||
276 | * one write for rest of parameters, mask of first write | ||
277 | * is 0x07ffffff, and the other one write for setting | ||
278 | * the mpll_clk_en happens in imx_sata_clock_enable(). | ||
279 | */ | ||
280 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | ||
281 | IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | | ||
282 | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | | ||
283 | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | | ||
284 | IMX6Q_GPR13_SATA_SPD_MODE_MASK | | ||
285 | IMX6Q_GPR13_SATA_MPLL_SS_EN | | ||
286 | IMX6Q_GPR13_SATA_TX_ATTEN_MASK | | ||
287 | IMX6Q_GPR13_SATA_TX_BOOST_MASK | | ||
288 | IMX6Q_GPR13_SATA_TX_LVL_MASK | | ||
289 | IMX6Q_GPR13_SATA_MPLL_CLK_EN | | ||
290 | IMX6Q_GPR13_SATA_TX_EDGE_RATE, | ||
291 | IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | | ||
292 | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | | ||
293 | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | | ||
294 | IMX6Q_GPR13_SATA_SPD_MODE_3P0G | | ||
295 | IMX6Q_GPR13_SATA_MPLL_SS_EN | | ||
296 | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | | ||
297 | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | | ||
298 | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); | ||
299 | |||
293 | ret = platform_device_add_resources(ahci_pdev, res, 2); | 300 | ret = platform_device_add_resources(ahci_pdev, res, 2); |
294 | if (ret) | 301 | if (ret) |
295 | goto err_out; | 302 | goto err_out; |