diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/ahci_imx.c | 180 |
1 files changed, 122 insertions, 58 deletions
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 6214411349de..8cb89655cf06 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c | |||
@@ -34,10 +34,21 @@ enum { | |||
34 | HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ | 34 | HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ |
35 | }; | 35 | }; |
36 | 36 | ||
37 | enum ahci_imx_type { | ||
38 | AHCI_IMX53, | ||
39 | AHCI_IMX6Q, | ||
40 | }; | ||
41 | |||
37 | struct imx_ahci_priv { | 42 | struct imx_ahci_priv { |
38 | struct platform_device *ahci_pdev; | 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 */ | ||
39 | struct clk *sata_ref_clk; | 49 | struct clk *sata_ref_clk; |
40 | struct clk *ahb_clk; | 50 | struct clk *ahb_clk; |
51 | |||
41 | struct regmap *gpr; | 52 | struct regmap *gpr; |
42 | bool no_device; | 53 | bool no_device; |
43 | bool first_time; | 54 | bool first_time; |
@@ -52,29 +63,52 @@ static int imx_sata_clock_enable(struct device *dev) | |||
52 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | 63 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); |
53 | int ret; | 64 | int ret; |
54 | 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 | |||
55 | ret = clk_prepare_enable(imxpriv->sata_ref_clk); | 75 | ret = clk_prepare_enable(imxpriv->sata_ref_clk); |
56 | if (ret < 0) { | 76 | if (ret < 0) { |
57 | dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); | 77 | dev_err(dev, "prepare-enable sata_ref clock err:%d\n", |
58 | return ret; | 78 | ret); |
79 | goto clk_err; | ||
59 | } | 80 | } |
60 | 81 | ||
61 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | 82 | if (imxpriv->type == AHCI_IMX6Q) { |
62 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | 83 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, |
63 | IMX6Q_GPR13_SATA_MPLL_CLK_EN); | 84 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, |
85 | IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
86 | } | ||
64 | 87 | ||
65 | usleep_range(1000, 2000); | 88 | usleep_range(1000, 2000); |
66 | 89 | ||
67 | return 0; | 90 | return 0; |
91 | |||
92 | clk_err: | ||
93 | if (imxpriv->type == AHCI_IMX53) | ||
94 | clk_disable_unprepare(imxpriv->sata_gate_clk); | ||
95 | return ret; | ||
68 | } | 96 | } |
69 | 97 | ||
70 | static void imx_sata_clock_disable(struct device *dev) | 98 | static void imx_sata_clock_disable(struct device *dev) |
71 | { | 99 | { |
72 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); | 100 | struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); |
73 | 101 | ||
74 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | 102 | if (imxpriv->type == AHCI_IMX6Q) { |
75 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, | 103 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, |
76 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | 104 | IMX6Q_GPR13_SATA_MPLL_CLK_EN, |
105 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | ||
106 | } | ||
107 | |||
77 | clk_disable_unprepare(imxpriv->sata_ref_clk); | 108 | clk_disable_unprepare(imxpriv->sata_ref_clk); |
109 | |||
110 | if (imxpriv->type == AHCI_IMX53) | ||
111 | clk_disable_unprepare(imxpriv->sata_gate_clk); | ||
78 | } | 112 | } |
79 | 113 | ||
80 | static void ahci_imx_error_handler(struct ata_port *ap) | 114 | static void ahci_imx_error_handler(struct ata_port *ap) |
@@ -106,9 +140,25 @@ static void ahci_imx_error_handler(struct ata_port *ap) | |||
106 | imxpriv->no_device = true; | 140 | imxpriv->no_device = true; |
107 | } | 141 | } |
108 | 142 | ||
143 | 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 | |||
109 | static struct ata_port_operations ahci_imx_ops = { | 158 | static struct ata_port_operations ahci_imx_ops = { |
110 | .inherits = &ahci_platform_ops, | 159 | .inherits = &ahci_platform_ops, |
111 | .error_handler = ahci_imx_error_handler, | 160 | .error_handler = ahci_imx_error_handler, |
161 | .softreset = ahci_imx_softreset, | ||
112 | }; | 162 | }; |
113 | 163 | ||
114 | static const struct ata_port_info ahci_imx_port_info = { | 164 | static const struct ata_port_info ahci_imx_port_info = { |
@@ -118,7 +168,7 @@ static const struct ata_port_info ahci_imx_port_info = { | |||
118 | .port_ops = &ahci_imx_ops, | 168 | .port_ops = &ahci_imx_ops, |
119 | }; | 169 | }; |
120 | 170 | ||
121 | static int imx6q_sata_init(struct device *dev, void __iomem *mmio) | 171 | static int imx_sata_init(struct device *dev, void __iomem *mmio) |
122 | { | 172 | { |
123 | int ret = 0; | 173 | int ret = 0; |
124 | unsigned int reg_val; | 174 | unsigned int reg_val; |
@@ -152,7 +202,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) | |||
152 | return 0; | 202 | return 0; |
153 | } | 203 | } |
154 | 204 | ||
155 | static void imx6q_sata_exit(struct device *dev) | 205 | static void imx_sata_exit(struct device *dev) |
156 | { | 206 | { |
157 | imx_sata_clock_disable(dev); | 207 | imx_sata_clock_disable(dev); |
158 | } | 208 | } |
@@ -182,16 +232,18 @@ static int imx_ahci_resume(struct device *dev) | |||
182 | return ret; | 232 | return ret; |
183 | } | 233 | } |
184 | 234 | ||
185 | static struct ahci_platform_data imx6q_sata_pdata = { | 235 | static struct ahci_platform_data imx_sata_pdata = { |
186 | .init = imx6q_sata_init, | 236 | .init = imx_sata_init, |
187 | .exit = imx6q_sata_exit, | 237 | .exit = imx_sata_exit, |
188 | .ata_port_info = &ahci_imx_port_info, | 238 | .ata_port_info = &ahci_imx_port_info, |
189 | .suspend = imx_ahci_suspend, | 239 | .suspend = imx_ahci_suspend, |
190 | .resume = imx_ahci_resume, | 240 | .resume = imx_ahci_resume, |
241 | |||
191 | }; | 242 | }; |
192 | 243 | ||
193 | static const struct of_device_id imx_ahci_of_match[] = { | 244 | static const struct of_device_id imx_ahci_of_match[] = { |
194 | { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata}, | 245 | { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, |
246 | { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, | ||
195 | {}, | 247 | {}, |
196 | }; | 248 | }; |
197 | MODULE_DEVICE_TABLE(of, imx_ahci_of_match); | 249 | MODULE_DEVICE_TABLE(of, imx_ahci_of_match); |
@@ -201,12 +253,20 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
201 | struct device *dev = &pdev->dev; | 253 | struct device *dev = &pdev->dev; |
202 | struct resource *mem, *irq, res[2]; | 254 | struct resource *mem, *irq, res[2]; |
203 | const struct of_device_id *of_id; | 255 | const struct of_device_id *of_id; |
256 | enum ahci_imx_type type; | ||
204 | const struct ahci_platform_data *pdata = NULL; | 257 | const struct ahci_platform_data *pdata = NULL; |
205 | struct imx_ahci_priv *imxpriv; | 258 | struct imx_ahci_priv *imxpriv; |
206 | struct device *ahci_dev; | 259 | struct device *ahci_dev; |
207 | struct platform_device *ahci_pdev; | 260 | struct platform_device *ahci_pdev; |
208 | int ret; | 261 | int ret; |
209 | 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 | |||
210 | imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); | 270 | imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); |
211 | if (!imxpriv) { | 271 | if (!imxpriv) { |
212 | dev_err(dev, "can't alloc ahci_host_priv\n"); | 272 | dev_err(dev, "can't alloc ahci_host_priv\n"); |
@@ -222,6 +282,8 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
222 | 282 | ||
223 | imxpriv->no_device = false; | 283 | imxpriv->no_device = false; |
224 | imxpriv->first_time = true; | 284 | imxpriv->first_time = true; |
285 | imxpriv->type = type; | ||
286 | |||
225 | imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); | 287 | imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); |
226 | if (IS_ERR(imxpriv->ahb_clk)) { | 288 | if (IS_ERR(imxpriv->ahb_clk)) { |
227 | dev_err(dev, "can't get ahb clock.\n"); | 289 | dev_err(dev, "can't get ahb clock.\n"); |
@@ -229,6 +291,15 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
229 | goto err_out; | 291 | goto err_out; |
230 | } | 292 | } |
231 | 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 | |||
232 | imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); | 303 | imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); |
233 | if (IS_ERR(imxpriv->sata_ref_clk)) { | 304 | if (IS_ERR(imxpriv->sata_ref_clk)) { |
234 | dev_err(dev, "can't get sata_ref clock.\n"); | 305 | dev_err(dev, "can't get sata_ref clock.\n"); |
@@ -239,14 +310,6 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
239 | imxpriv->ahci_pdev = ahci_pdev; | 310 | imxpriv->ahci_pdev = ahci_pdev; |
240 | platform_set_drvdata(pdev, imxpriv); | 311 | platform_set_drvdata(pdev, imxpriv); |
241 | 312 | ||
242 | of_id = of_match_device(imx_ahci_of_match, dev); | ||
243 | if (of_id) { | ||
244 | pdata = of_id->data; | ||
245 | } else { | ||
246 | ret = -EINVAL; | ||
247 | goto err_out; | ||
248 | } | ||
249 | |||
250 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 313 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
251 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 314 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
252 | if (!mem || !irq) { | 315 | if (!mem || !irq) { |
@@ -262,41 +325,42 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
262 | ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; | 325 | ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; |
263 | ahci_dev->of_node = dev->of_node; | 326 | ahci_dev->of_node = dev->of_node; |
264 | 327 | ||
265 | imxpriv->gpr = | 328 | if (type == AHCI_IMX6Q) { |
266 | syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); | 329 | imxpriv->gpr = syscon_regmap_lookup_by_compatible( |
267 | 330 | "fsl,imx6q-iomuxc-gpr"); | |
268 | if (IS_ERR(imxpriv->gpr)) { | 331 | if (IS_ERR(imxpriv->gpr)) { |
269 | dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); | 332 | dev_err(dev, |
270 | ret = PTR_ERR(imxpriv->gpr); | 333 | "failed to find fsl,imx6q-iomux-gpr regmap\n"); |
271 | goto err_out; | 334 | return PTR_ERR(imxpriv->gpr); |
335 | } | ||
336 | |||
337 | /* | ||
338 | * Set PHY Paremeters, two steps to configure the GPR13, | ||
339 | * one write for rest of parameters, mask of first write | ||
340 | * is 0x07fffffe, and the other one write for setting | ||
341 | * the mpll_clk_en happens in imx_sata_clock_enable(). | ||
342 | */ | ||
343 | regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, | ||
344 | IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | | ||
345 | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | | ||
346 | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | | ||
347 | IMX6Q_GPR13_SATA_SPD_MODE_MASK | | ||
348 | IMX6Q_GPR13_SATA_MPLL_SS_EN | | ||
349 | IMX6Q_GPR13_SATA_TX_ATTEN_MASK | | ||
350 | IMX6Q_GPR13_SATA_TX_BOOST_MASK | | ||
351 | IMX6Q_GPR13_SATA_TX_LVL_MASK | | ||
352 | IMX6Q_GPR13_SATA_MPLL_CLK_EN | | ||
353 | IMX6Q_GPR13_SATA_TX_EDGE_RATE, | ||
354 | IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | | ||
355 | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | | ||
356 | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | | ||
357 | IMX6Q_GPR13_SATA_SPD_MODE_3P0G | | ||
358 | IMX6Q_GPR13_SATA_MPLL_SS_EN | | ||
359 | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | | ||
360 | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | | ||
361 | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); | ||
272 | } | 362 | } |
273 | 363 | ||
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 | |||
300 | ret = platform_device_add_resources(ahci_pdev, res, 2); | 364 | ret = platform_device_add_resources(ahci_pdev, res, 2); |
301 | if (ret) | 365 | if (ret) |
302 | goto err_out; | 366 | goto err_out; |