xref: /openbmc/linux/drivers/ata/ahci_imx.c (revision 483eb062)
1 /*
2  * copyright (c) 2013 Freescale Semiconductor, Inc.
3  * Freescale IMX AHCI SATA platform driver
4  *
5  * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/regmap.h>
24 #include <linux/ahci_platform.h>
25 #include <linux/of_device.h>
26 #include <linux/mfd/syscon.h>
27 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
28 #include <linux/libata.h>
29 #include "ahci.h"
30 
31 enum {
32 	PORT_PHY_CTL = 0x178,			/* Port0 PHY Control */
33 	PORT_PHY_CTL_PDDQ_LOC = 0x100000,	/* PORT_PHY_CTL bits */
34 	HOST_TIMER1MS = 0xe0,			/* Timer 1-ms */
35 };
36 
37 enum ahci_imx_type {
38 	AHCI_IMX53,
39 	AHCI_IMX6Q,
40 };
41 
42 struct imx_ahci_priv {
43 	struct platform_device *ahci_pdev;
44 	enum ahci_imx_type type;
45 
46 	/* i.MX53 clock */
47 	struct clk *sata_gate_clk;
48 	/* Common clock */
49 	struct clk *sata_ref_clk;
50 	struct clk *ahb_clk;
51 
52 	struct regmap *gpr;
53 	bool no_device;
54 	bool first_time;
55 };
56 
57 static int ahci_imx_hotplug;
58 module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
59 MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
60 
61 static int imx_sata_clock_enable(struct device *dev)
62 {
63 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
64 	int ret;
65 
66 	if (imxpriv->type == AHCI_IMX53) {
67 		ret = clk_prepare_enable(imxpriv->sata_gate_clk);
68 		if (ret < 0) {
69 			dev_err(dev, "prepare-enable sata_gate clock err:%d\n",
70 				ret);
71 			return ret;
72 		}
73 	}
74 
75 	ret = clk_prepare_enable(imxpriv->sata_ref_clk);
76 	if (ret < 0) {
77 		dev_err(dev, "prepare-enable sata_ref clock err:%d\n",
78 			ret);
79 		goto clk_err;
80 	}
81 
82 	if (imxpriv->type == AHCI_IMX6Q) {
83 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
84 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
85 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
86 	}
87 
88 	usleep_range(1000, 2000);
89 
90 	return 0;
91 
92 clk_err:
93 	if (imxpriv->type == AHCI_IMX53)
94 		clk_disable_unprepare(imxpriv->sata_gate_clk);
95 	return ret;
96 }
97 
98 static void imx_sata_clock_disable(struct device *dev)
99 {
100 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
101 
102 	if (imxpriv->type == AHCI_IMX6Q) {
103 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
104 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
105 				   !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
106 	}
107 
108 	clk_disable_unprepare(imxpriv->sata_ref_clk);
109 
110 	if (imxpriv->type == AHCI_IMX53)
111 		clk_disable_unprepare(imxpriv->sata_gate_clk);
112 }
113 
114 static void ahci_imx_error_handler(struct ata_port *ap)
115 {
116 	u32 reg_val;
117 	struct ata_device *dev;
118 	struct ata_host *host = dev_get_drvdata(ap->dev);
119 	struct ahci_host_priv *hpriv = host->private_data;
120 	void __iomem *mmio = hpriv->mmio;
121 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
122 
123 	ahci_error_handler(ap);
124 
125 	if (!(imxpriv->first_time) || ahci_imx_hotplug)
126 		return;
127 
128 	imxpriv->first_time = false;
129 
130 	ata_for_each_dev(dev, &ap->link, ENABLED)
131 		return;
132 	/*
133 	 * Disable link to save power.  An imx ahci port can't be recovered
134 	 * without full reset once the pddq mode is enabled making it
135 	 * impossible to use as part of libata LPM.
136 	 */
137 	reg_val = readl(mmio + PORT_PHY_CTL);
138 	writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
139 	imx_sata_clock_disable(ap->dev);
140 	imxpriv->no_device = true;
141 }
142 
143 static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
144 		       unsigned long deadline)
145 {
146 	struct ata_port *ap = link->ap;
147 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
148 	int ret = -EIO;
149 
150 	if (imxpriv->type == AHCI_IMX53)
151 		ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
152 	else if (imxpriv->type == AHCI_IMX6Q)
153 		ret = ahci_ops.softreset(link, class, deadline);
154 
155 	return ret;
156 }
157 
158 static struct ata_port_operations ahci_imx_ops = {
159 	.inherits	= &ahci_platform_ops,
160 	.error_handler	= ahci_imx_error_handler,
161 	.softreset	= ahci_imx_softreset,
162 };
163 
164 static const struct ata_port_info ahci_imx_port_info = {
165 	.flags		= AHCI_FLAG_COMMON,
166 	.pio_mask	= ATA_PIO4,
167 	.udma_mask	= ATA_UDMA6,
168 	.port_ops	= &ahci_imx_ops,
169 };
170 
171 static int imx_sata_init(struct device *dev, void __iomem *mmio)
172 {
173 	int ret = 0;
174 	unsigned int reg_val;
175 	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
176 
177 	ret = imx_sata_clock_enable(dev);
178 	if (ret < 0)
179 		return ret;
180 
181 	/*
182 	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
183 	 * and IP vendor specific register HOST_TIMER1MS.
184 	 * Configure CAP_SSS (support stagered spin up).
185 	 * Implement the port0.
186 	 * Get the ahb clock rate, and configure the TIMER1MS register.
187 	 */
188 	reg_val = readl(mmio + HOST_CAP);
189 	if (!(reg_val & HOST_CAP_SSS)) {
190 		reg_val |= HOST_CAP_SSS;
191 		writel(reg_val, mmio + HOST_CAP);
192 	}
193 	reg_val = readl(mmio + HOST_PORTS_IMPL);
194 	if (!(reg_val & 0x1)) {
195 		reg_val |= 0x1;
196 		writel(reg_val, mmio + HOST_PORTS_IMPL);
197 	}
198 
199 	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
200 	writel(reg_val, mmio + HOST_TIMER1MS);
201 
202 	return 0;
203 }
204 
205 static void imx_sata_exit(struct device *dev)
206 {
207 	imx_sata_clock_disable(dev);
208 }
209 
210 static int imx_ahci_suspend(struct device *dev)
211 {
212 	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
213 
214 	/*
215 	 * If no_device is set, The CLKs had been gated off in the
216 	 * initialization so don't do it again here.
217 	 */
218 	if (!imxpriv->no_device)
219 		imx_sata_clock_disable(dev);
220 
221 	return 0;
222 }
223 
224 static int imx_ahci_resume(struct device *dev)
225 {
226 	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
227 	int ret = 0;
228 
229 	if (!imxpriv->no_device)
230 		ret = imx_sata_clock_enable(dev);
231 
232 	return ret;
233 }
234 
235 static struct ahci_platform_data imx_sata_pdata = {
236 	.init		= imx_sata_init,
237 	.exit		= imx_sata_exit,
238 	.ata_port_info	= &ahci_imx_port_info,
239 	.suspend	= imx_ahci_suspend,
240 	.resume		= imx_ahci_resume,
241 
242 };
243 
244 static const struct of_device_id imx_ahci_of_match[] = {
245 	{ .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
246 	{ .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
247 	{},
248 };
249 MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
250 
251 static int imx_ahci_probe(struct platform_device *pdev)
252 {
253 	struct device *dev = &pdev->dev;
254 	struct resource *mem, *irq, res[2];
255 	const struct of_device_id *of_id;
256 	enum ahci_imx_type type;
257 	const struct ahci_platform_data *pdata = NULL;
258 	struct imx_ahci_priv *imxpriv;
259 	struct device *ahci_dev;
260 	struct platform_device *ahci_pdev;
261 	int ret;
262 
263 	of_id = of_match_device(imx_ahci_of_match, dev);
264 	if (!of_id)
265 		return -EINVAL;
266 
267 	type = (enum ahci_imx_type)of_id->data;
268 	pdata = &imx_sata_pdata;
269 
270 	imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
271 	if (!imxpriv) {
272 		dev_err(dev, "can't alloc ahci_host_priv\n");
273 		return -ENOMEM;
274 	}
275 
276 	ahci_pdev = platform_device_alloc("ahci", -1);
277 	if (!ahci_pdev)
278 		return -ENODEV;
279 
280 	ahci_dev = &ahci_pdev->dev;
281 	ahci_dev->parent = dev;
282 
283 	imxpriv->no_device = false;
284 	imxpriv->first_time = true;
285 	imxpriv->type = type;
286 
287 	imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
288 	if (IS_ERR(imxpriv->ahb_clk)) {
289 		dev_err(dev, "can't get ahb clock.\n");
290 		ret = PTR_ERR(imxpriv->ahb_clk);
291 		goto err_out;
292 	}
293 
294 	if (type == AHCI_IMX53) {
295 		imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate");
296 		if (IS_ERR(imxpriv->sata_gate_clk)) {
297 			dev_err(dev, "can't get sata_gate clock.\n");
298 			ret = PTR_ERR(imxpriv->sata_gate_clk);
299 			goto err_out;
300 		}
301 	}
302 
303 	imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
304 	if (IS_ERR(imxpriv->sata_ref_clk)) {
305 		dev_err(dev, "can't get sata_ref clock.\n");
306 		ret = PTR_ERR(imxpriv->sata_ref_clk);
307 		goto err_out;
308 	}
309 
310 	imxpriv->ahci_pdev = ahci_pdev;
311 	platform_set_drvdata(pdev, imxpriv);
312 
313 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
314 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
315 	if (!mem || !irq) {
316 		dev_err(dev, "no mmio/irq resource\n");
317 		ret = -ENOMEM;
318 		goto err_out;
319 	}
320 
321 	res[0] = *mem;
322 	res[1] = *irq;
323 
324 	ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
325 	ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
326 	ahci_dev->of_node = dev->of_node;
327 
328 	if (type == AHCI_IMX6Q) {
329 		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
330 							"fsl,imx6q-iomuxc-gpr");
331 		if (IS_ERR(imxpriv->gpr)) {
332 			dev_err(dev,
333 				"failed to find fsl,imx6q-iomux-gpr regmap\n");
334 			ret = PTR_ERR(imxpriv->gpr);
335 			goto err_out;
336 		}
337 
338 		/*
339 		 * Set PHY Paremeters, two steps to configure the GPR13,
340 		 * one write for rest of parameters, mask of first write
341 		 * is 0x07fffffe, and the other one write for setting
342 		 * the mpll_clk_en happens in imx_sata_clock_enable().
343 		 */
344 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
345 				   IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
346 				   IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
347 				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
348 				   IMX6Q_GPR13_SATA_SPD_MODE_MASK |
349 				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
350 				   IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
351 				   IMX6Q_GPR13_SATA_TX_BOOST_MASK |
352 				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
353 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
354 				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
355 				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
356 				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
357 				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
358 				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
359 				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
360 				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
361 				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
362 				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
363 	}
364 
365 	ret = platform_device_add_resources(ahci_pdev, res, 2);
366 	if (ret)
367 		goto err_out;
368 
369 	ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
370 	if (ret)
371 		goto err_out;
372 
373 	ret = platform_device_add(ahci_pdev);
374 	if (ret) {
375 err_out:
376 		platform_device_put(ahci_pdev);
377 		return ret;
378 	}
379 
380 	return 0;
381 }
382 
383 static int imx_ahci_remove(struct platform_device *pdev)
384 {
385 	struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
386 	struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
387 
388 	platform_device_unregister(ahci_pdev);
389 	return 0;
390 }
391 
392 static struct platform_driver imx_ahci_driver = {
393 	.probe = imx_ahci_probe,
394 	.remove = imx_ahci_remove,
395 	.driver = {
396 		.name = "ahci-imx",
397 		.owner = THIS_MODULE,
398 		.of_match_table = imx_ahci_of_match,
399 	},
400 };
401 module_platform_driver(imx_ahci_driver);
402 
403 MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
404 MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
405 MODULE_LICENSE("GPL");
406 MODULE_ALIAS("ahci:imx");
407