ipq806x: Add support for IPQ806x chip family
[openwrt/openwrt.git] / target / linux / ipq806x / patches / 0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch
1 From 04800db1047afbf6701379435bff1a6fa64215f7 Mon Sep 17 00:00:00 2001
2 From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
3 Date: Tue, 25 Mar 2014 19:51:39 +0100
4 Subject: [PATCH 124/182] ata: move library code from ahci_platform.c to
5 libahci_platform.c
6
7 Move AHCI platform library code from ahci_platform.c to
8 libahci_platform.c and fix dependencies for ahci_st,
9 ahci_imx and ahci_sunxi drivers.
10
11 Acked-by: Hans de Goede <hdegoede@redhat.com>
12 Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
13 Signed-off-by: Tejun Heo <tj@kernel.org>
14
15 Conflicts:
16 drivers/ata/Kconfig
17 drivers/ata/Makefile
18 ---
19 drivers/ata/Kconfig | 2 +-
20 drivers/ata/Makefile | 4 +-
21 drivers/ata/ahci_platform.c | 515 --------------------------------------
22 drivers/ata/libahci_platform.c | 541 ++++++++++++++++++++++++++++++++++++++++
23 4 files changed, 544 insertions(+), 518 deletions(-)
24 create mode 100644 drivers/ata/libahci_platform.c
25
26 diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
27 index 868429a..dc950f3 100644
28 --- a/drivers/ata/Kconfig
29 +++ b/drivers/ata/Kconfig
30 @@ -99,7 +99,7 @@ config SATA_AHCI_PLATFORM
31
32 config AHCI_IMX
33 tristate "Freescale i.MX AHCI SATA support"
34 - depends on SATA_AHCI_PLATFORM && MFD_SYSCON
35 + depends on MFD_SYSCON
36 help
37 This option enables support for the Freescale i.MX SoC's
38 onboard AHCI SATA.
39 diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
40 index 46518c6..366b743 100644
41 --- a/drivers/ata/Makefile
42 +++ b/drivers/ata/Makefile
43 @@ -4,13 +4,13 @@ obj-$(CONFIG_ATA) += libata.o
44 # non-SFF interface
45 obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
46 obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
47 -obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
48 +obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
49 obj-$(CONFIG_SATA_FSL) += sata_fsl.o
50 obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
51 obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
52 obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
53 obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
54 -obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
55 +obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
56
57 # SFF w/ custom DMA
58 obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
59 diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
60 index 7bd6adf..ef67e79 100644
61 --- a/drivers/ata/ahci_platform.c
62 +++ b/drivers/ata/ahci_platform.c
63 @@ -12,28 +12,15 @@
64 * any later version.
65 */
66
67 -#include <linux/clk.h>
68 #include <linux/kernel.h>
69 -#include <linux/gfp.h>
70 #include <linux/module.h>
71 #include <linux/pm.h>
72 -#include <linux/interrupt.h>
73 #include <linux/device.h>
74 #include <linux/platform_device.h>
75 #include <linux/libata.h>
76 #include <linux/ahci_platform.h>
77 -#include <linux/phy/phy.h>
78 -#include <linux/pm_runtime.h>
79 #include "ahci.h"
80
81 -static void ahci_host_stop(struct ata_host *host);
82 -
83 -struct ata_port_operations ahci_platform_ops = {
84 - .inherits = &ahci_ops,
85 - .host_stop = ahci_host_stop,
86 -};
87 -EXPORT_SYMBOL_GPL(ahci_platform_ops);
88 -
89 static const struct ata_port_info ahci_port_info = {
90 .flags = AHCI_FLAG_COMMON,
91 .pio_mask = ATA_PIO4,
92 @@ -41,345 +28,6 @@ static const struct ata_port_info ahci_port_info = {
93 .port_ops = &ahci_platform_ops,
94 };
95
96 -static struct scsi_host_template ahci_platform_sht = {
97 - AHCI_SHT("ahci_platform"),
98 -};
99 -
100 -/**
101 - * ahci_platform_enable_clks - Enable platform clocks
102 - * @hpriv: host private area to store config values
103 - *
104 - * This function enables all the clks found in hpriv->clks, starting at
105 - * index 0. If any clk fails to enable it disables all the clks already
106 - * enabled in reverse order, and then returns an error.
107 - *
108 - * RETURNS:
109 - * 0 on success otherwise a negative error code
110 - */
111 -int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
112 -{
113 - int c, rc;
114 -
115 - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
116 - rc = clk_prepare_enable(hpriv->clks[c]);
117 - if (rc)
118 - goto disable_unprepare_clk;
119 - }
120 - return 0;
121 -
122 -disable_unprepare_clk:
123 - while (--c >= 0)
124 - clk_disable_unprepare(hpriv->clks[c]);
125 - return rc;
126 -}
127 -EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
128 -
129 -/**
130 - * ahci_platform_disable_clks - Disable platform clocks
131 - * @hpriv: host private area to store config values
132 - *
133 - * This function disables all the clks found in hpriv->clks, in reverse
134 - * order of ahci_platform_enable_clks (starting at the end of the array).
135 - */
136 -void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
137 -{
138 - int c;
139 -
140 - for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
141 - if (hpriv->clks[c])
142 - clk_disable_unprepare(hpriv->clks[c]);
143 -}
144 -EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
145 -
146 -/**
147 - * ahci_platform_enable_resources - Enable platform resources
148 - * @hpriv: host private area to store config values
149 - *
150 - * This function enables all ahci_platform managed resources in the
151 - * following order:
152 - * 1) Regulator
153 - * 2) Clocks (through ahci_platform_enable_clks)
154 - * 3) Phy
155 - *
156 - * If resource enabling fails at any point the previous enabled resources
157 - * are disabled in reverse order.
158 - *
159 - * RETURNS:
160 - * 0 on success otherwise a negative error code
161 - */
162 -int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
163 -{
164 - int rc;
165 -
166 - if (hpriv->target_pwr) {
167 - rc = regulator_enable(hpriv->target_pwr);
168 - if (rc)
169 - return rc;
170 - }
171 -
172 - rc = ahci_platform_enable_clks(hpriv);
173 - if (rc)
174 - goto disable_regulator;
175 -
176 - if (hpriv->phy) {
177 - rc = phy_init(hpriv->phy);
178 - if (rc)
179 - goto disable_clks;
180 -
181 - rc = phy_power_on(hpriv->phy);
182 - if (rc) {
183 - phy_exit(hpriv->phy);
184 - goto disable_clks;
185 - }
186 - }
187 -
188 - return 0;
189 -
190 -disable_clks:
191 - ahci_platform_disable_clks(hpriv);
192 -
193 -disable_regulator:
194 - if (hpriv->target_pwr)
195 - regulator_disable(hpriv->target_pwr);
196 - return rc;
197 -}
198 -EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
199 -
200 -/**
201 - * ahci_platform_disable_resources - Disable platform resources
202 - * @hpriv: host private area to store config values
203 - *
204 - * This function disables all ahci_platform managed resources in the
205 - * following order:
206 - * 1) Phy
207 - * 2) Clocks (through ahci_platform_disable_clks)
208 - * 3) Regulator
209 - */
210 -void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
211 -{
212 - if (hpriv->phy) {
213 - phy_power_off(hpriv->phy);
214 - phy_exit(hpriv->phy);
215 - }
216 -
217 - ahci_platform_disable_clks(hpriv);
218 -
219 - if (hpriv->target_pwr)
220 - regulator_disable(hpriv->target_pwr);
221 -}
222 -EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
223 -
224 -static void ahci_platform_put_resources(struct device *dev, void *res)
225 -{
226 - struct ahci_host_priv *hpriv = res;
227 - int c;
228 -
229 - if (hpriv->got_runtime_pm) {
230 - pm_runtime_put_sync(dev);
231 - pm_runtime_disable(dev);
232 - }
233 -
234 - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
235 - clk_put(hpriv->clks[c]);
236 -}
237 -
238 -/**
239 - * ahci_platform_get_resources - Get platform resources
240 - * @pdev: platform device to get resources for
241 - *
242 - * This function allocates an ahci_host_priv struct, and gets the following
243 - * resources, storing a reference to them inside the returned struct:
244 - *
245 - * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
246 - * 2) regulator for controlling the targets power (optional)
247 - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
248 - * or for non devicetree enabled platforms a single clock
249 - * 4) phy (optional)
250 - *
251 - * RETURNS:
252 - * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
253 - */
254 -struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
255 -{
256 - struct device *dev = &pdev->dev;
257 - struct ahci_host_priv *hpriv;
258 - struct clk *clk;
259 - int i, rc = -ENOMEM;
260 -
261 - if (!devres_open_group(dev, NULL, GFP_KERNEL))
262 - return ERR_PTR(-ENOMEM);
263 -
264 - hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
265 - GFP_KERNEL);
266 - if (!hpriv)
267 - goto err_out;
268 -
269 - devres_add(dev, hpriv);
270 -
271 - hpriv->mmio = devm_ioremap_resource(dev,
272 - platform_get_resource(pdev, IORESOURCE_MEM, 0));
273 - if (IS_ERR(hpriv->mmio)) {
274 - dev_err(dev, "no mmio space\n");
275 - rc = PTR_ERR(hpriv->mmio);
276 - goto err_out;
277 - }
278 -
279 - hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
280 - if (IS_ERR(hpriv->target_pwr)) {
281 - rc = PTR_ERR(hpriv->target_pwr);
282 - if (rc == -EPROBE_DEFER)
283 - goto err_out;
284 - hpriv->target_pwr = NULL;
285 - }
286 -
287 - for (i = 0; i < AHCI_MAX_CLKS; i++) {
288 - /*
289 - * For now we must use clk_get(dev, NULL) for the first clock,
290 - * because some platforms (da850, spear13xx) are not yet
291 - * converted to use devicetree for clocks. For new platforms
292 - * this is equivalent to of_clk_get(dev->of_node, 0).
293 - */
294 - if (i == 0)
295 - clk = clk_get(dev, NULL);
296 - else
297 - clk = of_clk_get(dev->of_node, i);
298 -
299 - if (IS_ERR(clk)) {
300 - rc = PTR_ERR(clk);
301 - if (rc == -EPROBE_DEFER)
302 - goto err_out;
303 - break;
304 - }
305 - hpriv->clks[i] = clk;
306 - }
307 -
308 - hpriv->phy = devm_phy_get(dev, "sata-phy");
309 - if (IS_ERR(hpriv->phy)) {
310 - rc = PTR_ERR(hpriv->phy);
311 - switch (rc) {
312 - case -ENODEV:
313 - case -ENOSYS:
314 - /* continue normally */
315 - hpriv->phy = NULL;
316 - break;
317 -
318 - case -EPROBE_DEFER:
319 - goto err_out;
320 -
321 - default:
322 - dev_err(dev, "couldn't get sata-phy\n");
323 - goto err_out;
324 - }
325 - }
326 -
327 - pm_runtime_enable(dev);
328 - pm_runtime_get_sync(dev);
329 - hpriv->got_runtime_pm = true;
330 -
331 - devres_remove_group(dev, NULL);
332 - return hpriv;
333 -
334 -err_out:
335 - devres_release_group(dev, NULL);
336 - return ERR_PTR(rc);
337 -}
338 -EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
339 -
340 -/**
341 - * ahci_platform_init_host - Bring up an ahci-platform host
342 - * @pdev: platform device pointer for the host
343 - * @hpriv: ahci-host private data for the host
344 - * @pi_template: template for the ata_port_info to use
345 - * @force_port_map: param passed to ahci_save_initial_config
346 - * @mask_port_map: param passed to ahci_save_initial_config
347 - *
348 - * This function does all the usual steps needed to bring up an
349 - * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
350 - * must be initialized / enabled before calling this.
351 - *
352 - * RETURNS:
353 - * 0 on success otherwise a negative error code
354 - */
355 -int ahci_platform_init_host(struct platform_device *pdev,
356 - struct ahci_host_priv *hpriv,
357 - const struct ata_port_info *pi_template,
358 - unsigned int force_port_map,
359 - unsigned int mask_port_map)
360 -{
361 - struct device *dev = &pdev->dev;
362 - struct ata_port_info pi = *pi_template;
363 - const struct ata_port_info *ppi[] = { &pi, NULL };
364 - struct ata_host *host;
365 - int i, irq, n_ports, rc;
366 -
367 - irq = platform_get_irq(pdev, 0);
368 - if (irq <= 0) {
369 - dev_err(dev, "no irq\n");
370 - return -EINVAL;
371 - }
372 -
373 - /* prepare host */
374 - hpriv->flags |= (unsigned long)pi.private_data;
375 -
376 - ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
377 -
378 - if (hpriv->cap & HOST_CAP_NCQ)
379 - pi.flags |= ATA_FLAG_NCQ;
380 -
381 - if (hpriv->cap & HOST_CAP_PMP)
382 - pi.flags |= ATA_FLAG_PMP;
383 -
384 - ahci_set_em_messages(hpriv, &pi);
385 -
386 - /* CAP.NP sometimes indicate the index of the last enabled
387 - * port, at other times, that of the last possible port, so
388 - * determining the maximum port number requires looking at
389 - * both CAP.NP and port_map.
390 - */
391 - n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
392 -
393 - host = ata_host_alloc_pinfo(dev, ppi, n_ports);
394 - if (!host)
395 - return -ENOMEM;
396 -
397 - host->private_data = hpriv;
398 -
399 - if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
400 - host->flags |= ATA_HOST_PARALLEL_SCAN;
401 - else
402 - dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
403 -
404 - if (pi.flags & ATA_FLAG_EM)
405 - ahci_reset_em(host);
406 -
407 - for (i = 0; i < host->n_ports; i++) {
408 - struct ata_port *ap = host->ports[i];
409 -
410 - ata_port_desc(ap, "mmio %pR",
411 - platform_get_resource(pdev, IORESOURCE_MEM, 0));
412 - ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
413 -
414 - /* set enclosure management message type */
415 - if (ap->flags & ATA_FLAG_EM)
416 - ap->em_message_type = hpriv->em_msg_type;
417 -
418 - /* disabled/not-implemented port */
419 - if (!(hpriv->port_map & (1 << i)))
420 - ap->ops = &ata_dummy_port_ops;
421 - }
422 -
423 - rc = ahci_reset_controller(host);
424 - if (rc)
425 - return rc;
426 -
427 - ahci_init_controller(host);
428 - ahci_print_info(host, "platform");
429 -
430 - return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
431 - &ahci_platform_sht);
432 -}
433 -EXPORT_SYMBOL_GPL(ahci_platform_init_host);
434 -
435 static int ahci_probe(struct platform_device *pdev)
436 {
437 struct device *dev = &pdev->dev;
438 @@ -420,169 +68,6 @@ disable_resources:
439 return rc;
440 }
441
442 -static void ahci_host_stop(struct ata_host *host)
443 -{
444 - struct device *dev = host->dev;
445 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
446 - struct ahci_host_priv *hpriv = host->private_data;
447 -
448 - if (pdata && pdata->exit)
449 - pdata->exit(dev);
450 -
451 - ahci_platform_disable_resources(hpriv);
452 -}
453 -
454 -#ifdef CONFIG_PM_SLEEP
455 -/**
456 - * ahci_platform_suspend_host - Suspend an ahci-platform host
457 - * @dev: device pointer for the host
458 - *
459 - * This function does all the usual steps needed to suspend an
460 - * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
461 - * must be disabled after calling this.
462 - *
463 - * RETURNS:
464 - * 0 on success otherwise a negative error code
465 - */
466 -int ahci_platform_suspend_host(struct device *dev)
467 -{
468 - struct ata_host *host = dev_get_drvdata(dev);
469 - struct ahci_host_priv *hpriv = host->private_data;
470 - void __iomem *mmio = hpriv->mmio;
471 - u32 ctl;
472 -
473 - if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
474 - dev_err(dev, "firmware update required for suspend/resume\n");
475 - return -EIO;
476 - }
477 -
478 - /*
479 - * AHCI spec rev1.1 section 8.3.3:
480 - * Software must disable interrupts prior to requesting a
481 - * transition of the HBA to D3 state.
482 - */
483 - ctl = readl(mmio + HOST_CTL);
484 - ctl &= ~HOST_IRQ_EN;
485 - writel(ctl, mmio + HOST_CTL);
486 - readl(mmio + HOST_CTL); /* flush */
487 -
488 - return ata_host_suspend(host, PMSG_SUSPEND);
489 -}
490 -EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
491 -
492 -/**
493 - * ahci_platform_resume_host - Resume an ahci-platform host
494 - * @dev: device pointer for the host
495 - *
496 - * This function does all the usual steps needed to resume an ahci-platform
497 - * host, note any necessary resources (ie clks, phy, etc.) must be
498 - * initialized / enabled before calling this.
499 - *
500 - * RETURNS:
501 - * 0 on success otherwise a negative error code
502 - */
503 -int ahci_platform_resume_host(struct device *dev)
504 -{
505 - struct ata_host *host = dev_get_drvdata(dev);
506 - int rc;
507 -
508 - if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
509 - rc = ahci_reset_controller(host);
510 - if (rc)
511 - return rc;
512 -
513 - ahci_init_controller(host);
514 - }
515 -
516 - ata_host_resume(host);
517 -
518 - return 0;
519 -}
520 -EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
521 -
522 -/**
523 - * ahci_platform_suspend - Suspend an ahci-platform device
524 - * @dev: the platform device to suspend
525 - *
526 - * This function suspends the host associated with the device, followed by
527 - * disabling all the resources of the device.
528 - *
529 - * RETURNS:
530 - * 0 on success otherwise a negative error code
531 - */
532 -int ahci_platform_suspend(struct device *dev)
533 -{
534 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
535 - struct ata_host *host = dev_get_drvdata(dev);
536 - struct ahci_host_priv *hpriv = host->private_data;
537 - int rc;
538 -
539 - rc = ahci_platform_suspend_host(dev);
540 - if (rc)
541 - return rc;
542 -
543 - if (pdata && pdata->suspend) {
544 - rc = pdata->suspend(dev);
545 - if (rc)
546 - goto resume_host;
547 - }
548 -
549 - ahci_platform_disable_resources(hpriv);
550 -
551 - return 0;
552 -
553 -resume_host:
554 - ahci_platform_resume_host(dev);
555 - return rc;
556 -}
557 -EXPORT_SYMBOL_GPL(ahci_platform_suspend);
558 -
559 -/**
560 - * ahci_platform_resume - Resume an ahci-platform device
561 - * @dev: the platform device to resume
562 - *
563 - * This function enables all the resources of the device followed by
564 - * resuming the host associated with the device.
565 - *
566 - * RETURNS:
567 - * 0 on success otherwise a negative error code
568 - */
569 -int ahci_platform_resume(struct device *dev)
570 -{
571 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
572 - struct ata_host *host = dev_get_drvdata(dev);
573 - struct ahci_host_priv *hpriv = host->private_data;
574 - int rc;
575 -
576 - rc = ahci_platform_enable_resources(hpriv);
577 - if (rc)
578 - return rc;
579 -
580 - if (pdata && pdata->resume) {
581 - rc = pdata->resume(dev);
582 - if (rc)
583 - goto disable_resources;
584 - }
585 -
586 - rc = ahci_platform_resume_host(dev);
587 - if (rc)
588 - goto disable_resources;
589 -
590 - /* We resumed so update PM runtime state */
591 - pm_runtime_disable(dev);
592 - pm_runtime_set_active(dev);
593 - pm_runtime_enable(dev);
594 -
595 - return 0;
596 -
597 -disable_resources:
598 - ahci_platform_disable_resources(hpriv);
599 -
600 - return rc;
601 -}
602 -EXPORT_SYMBOL_GPL(ahci_platform_resume);
603 -#endif
604 -
605 static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
606 ahci_platform_resume);
607
608 diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
609 new file mode 100644
610 index 0000000..7cb3a85
611 --- /dev/null
612 +++ b/drivers/ata/libahci_platform.c
613 @@ -0,0 +1,541 @@
614 +/*
615 + * AHCI SATA platform library
616 + *
617 + * Copyright 2004-2005 Red Hat, Inc.
618 + * Jeff Garzik <jgarzik@pobox.com>
619 + * Copyright 2010 MontaVista Software, LLC.
620 + * Anton Vorontsov <avorontsov@ru.mvista.com>
621 + *
622 + * This program is free software; you can redistribute it and/or modify
623 + * it under the terms of the GNU General Public License as published by
624 + * the Free Software Foundation; either version 2, or (at your option)
625 + * any later version.
626 + */
627 +
628 +#include <linux/clk.h>
629 +#include <linux/kernel.h>
630 +#include <linux/gfp.h>
631 +#include <linux/module.h>
632 +#include <linux/pm.h>
633 +#include <linux/interrupt.h>
634 +#include <linux/device.h>
635 +#include <linux/platform_device.h>
636 +#include <linux/libata.h>
637 +#include <linux/ahci_platform.h>
638 +#include <linux/phy/phy.h>
639 +#include <linux/pm_runtime.h>
640 +#include "ahci.h"
641 +
642 +static void ahci_host_stop(struct ata_host *host);
643 +
644 +struct ata_port_operations ahci_platform_ops = {
645 + .inherits = &ahci_ops,
646 + .host_stop = ahci_host_stop,
647 +};
648 +EXPORT_SYMBOL_GPL(ahci_platform_ops);
649 +
650 +static struct scsi_host_template ahci_platform_sht = {
651 + AHCI_SHT("ahci_platform"),
652 +};
653 +
654 +/**
655 + * ahci_platform_enable_clks - Enable platform clocks
656 + * @hpriv: host private area to store config values
657 + *
658 + * This function enables all the clks found in hpriv->clks, starting at
659 + * index 0. If any clk fails to enable it disables all the clks already
660 + * enabled in reverse order, and then returns an error.
661 + *
662 + * RETURNS:
663 + * 0 on success otherwise a negative error code
664 + */
665 +int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
666 +{
667 + int c, rc;
668 +
669 + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
670 + rc = clk_prepare_enable(hpriv->clks[c]);
671 + if (rc)
672 + goto disable_unprepare_clk;
673 + }
674 + return 0;
675 +
676 +disable_unprepare_clk:
677 + while (--c >= 0)
678 + clk_disable_unprepare(hpriv->clks[c]);
679 + return rc;
680 +}
681 +EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
682 +
683 +/**
684 + * ahci_platform_disable_clks - Disable platform clocks
685 + * @hpriv: host private area to store config values
686 + *
687 + * This function disables all the clks found in hpriv->clks, in reverse
688 + * order of ahci_platform_enable_clks (starting at the end of the array).
689 + */
690 +void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
691 +{
692 + int c;
693 +
694 + for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
695 + if (hpriv->clks[c])
696 + clk_disable_unprepare(hpriv->clks[c]);
697 +}
698 +EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
699 +
700 +/**
701 + * ahci_platform_enable_resources - Enable platform resources
702 + * @hpriv: host private area to store config values
703 + *
704 + * This function enables all ahci_platform managed resources in the
705 + * following order:
706 + * 1) Regulator
707 + * 2) Clocks (through ahci_platform_enable_clks)
708 + * 3) Phy
709 + *
710 + * If resource enabling fails at any point the previous enabled resources
711 + * are disabled in reverse order.
712 + *
713 + * RETURNS:
714 + * 0 on success otherwise a negative error code
715 + */
716 +int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
717 +{
718 + int rc;
719 +
720 + if (hpriv->target_pwr) {
721 + rc = regulator_enable(hpriv->target_pwr);
722 + if (rc)
723 + return rc;
724 + }
725 +
726 + rc = ahci_platform_enable_clks(hpriv);
727 + if (rc)
728 + goto disable_regulator;
729 +
730 + if (hpriv->phy) {
731 + rc = phy_init(hpriv->phy);
732 + if (rc)
733 + goto disable_clks;
734 +
735 + rc = phy_power_on(hpriv->phy);
736 + if (rc) {
737 + phy_exit(hpriv->phy);
738 + goto disable_clks;
739 + }
740 + }
741 +
742 + return 0;
743 +
744 +disable_clks:
745 + ahci_platform_disable_clks(hpriv);
746 +
747 +disable_regulator:
748 + if (hpriv->target_pwr)
749 + regulator_disable(hpriv->target_pwr);
750 + return rc;
751 +}
752 +EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
753 +
754 +/**
755 + * ahci_platform_disable_resources - Disable platform resources
756 + * @hpriv: host private area to store config values
757 + *
758 + * This function disables all ahci_platform managed resources in the
759 + * following order:
760 + * 1) Phy
761 + * 2) Clocks (through ahci_platform_disable_clks)
762 + * 3) Regulator
763 + */
764 +void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
765 +{
766 + if (hpriv->phy) {
767 + phy_power_off(hpriv->phy);
768 + phy_exit(hpriv->phy);
769 + }
770 +
771 + ahci_platform_disable_clks(hpriv);
772 +
773 + if (hpriv->target_pwr)
774 + regulator_disable(hpriv->target_pwr);
775 +}
776 +EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
777 +
778 +static void ahci_platform_put_resources(struct device *dev, void *res)
779 +{
780 + struct ahci_host_priv *hpriv = res;
781 + int c;
782 +
783 + if (hpriv->got_runtime_pm) {
784 + pm_runtime_put_sync(dev);
785 + pm_runtime_disable(dev);
786 + }
787 +
788 + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
789 + clk_put(hpriv->clks[c]);
790 +}
791 +
792 +/**
793 + * ahci_platform_get_resources - Get platform resources
794 + * @pdev: platform device to get resources for
795 + *
796 + * This function allocates an ahci_host_priv struct, and gets the following
797 + * resources, storing a reference to them inside the returned struct:
798 + *
799 + * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
800 + * 2) regulator for controlling the targets power (optional)
801 + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
802 + * or for non devicetree enabled platforms a single clock
803 + * 4) phy (optional)
804 + *
805 + * RETURNS:
806 + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
807 + */
808 +struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
809 +{
810 + struct device *dev = &pdev->dev;
811 + struct ahci_host_priv *hpriv;
812 + struct clk *clk;
813 + int i, rc = -ENOMEM;
814 +
815 + if (!devres_open_group(dev, NULL, GFP_KERNEL))
816 + return ERR_PTR(-ENOMEM);
817 +
818 + hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
819 + GFP_KERNEL);
820 + if (!hpriv)
821 + goto err_out;
822 +
823 + devres_add(dev, hpriv);
824 +
825 + hpriv->mmio = devm_ioremap_resource(dev,
826 + platform_get_resource(pdev, IORESOURCE_MEM, 0));
827 + if (IS_ERR(hpriv->mmio)) {
828 + dev_err(dev, "no mmio space\n");
829 + rc = PTR_ERR(hpriv->mmio);
830 + goto err_out;
831 + }
832 +
833 + hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
834 + if (IS_ERR(hpriv->target_pwr)) {
835 + rc = PTR_ERR(hpriv->target_pwr);
836 + if (rc == -EPROBE_DEFER)
837 + goto err_out;
838 + hpriv->target_pwr = NULL;
839 + }
840 +
841 + for (i = 0; i < AHCI_MAX_CLKS; i++) {
842 + /*
843 + * For now we must use clk_get(dev, NULL) for the first clock,
844 + * because some platforms (da850, spear13xx) are not yet
845 + * converted to use devicetree for clocks. For new platforms
846 + * this is equivalent to of_clk_get(dev->of_node, 0).
847 + */
848 + if (i == 0)
849 + clk = clk_get(dev, NULL);
850 + else
851 + clk = of_clk_get(dev->of_node, i);
852 +
853 + if (IS_ERR(clk)) {
854 + rc = PTR_ERR(clk);
855 + if (rc == -EPROBE_DEFER)
856 + goto err_out;
857 + break;
858 + }
859 + hpriv->clks[i] = clk;
860 + }
861 +
862 + hpriv->phy = devm_phy_get(dev, "sata-phy");
863 + if (IS_ERR(hpriv->phy)) {
864 + rc = PTR_ERR(hpriv->phy);
865 + switch (rc) {
866 + case -ENODEV:
867 + case -ENOSYS:
868 + /* continue normally */
869 + hpriv->phy = NULL;
870 + break;
871 +
872 + case -EPROBE_DEFER:
873 + goto err_out;
874 +
875 + default:
876 + dev_err(dev, "couldn't get sata-phy\n");
877 + goto err_out;
878 + }
879 + }
880 +
881 + pm_runtime_enable(dev);
882 + pm_runtime_get_sync(dev);
883 + hpriv->got_runtime_pm = true;
884 +
885 + devres_remove_group(dev, NULL);
886 + return hpriv;
887 +
888 +err_out:
889 + devres_release_group(dev, NULL);
890 + return ERR_PTR(rc);
891 +}
892 +EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
893 +
894 +/**
895 + * ahci_platform_init_host - Bring up an ahci-platform host
896 + * @pdev: platform device pointer for the host
897 + * @hpriv: ahci-host private data for the host
898 + * @pi_template: template for the ata_port_info to use
899 + * @force_port_map: param passed to ahci_save_initial_config
900 + * @mask_port_map: param passed to ahci_save_initial_config
901 + *
902 + * This function does all the usual steps needed to bring up an
903 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
904 + * must be initialized / enabled before calling this.
905 + *
906 + * RETURNS:
907 + * 0 on success otherwise a negative error code
908 + */
909 +int ahci_platform_init_host(struct platform_device *pdev,
910 + struct ahci_host_priv *hpriv,
911 + const struct ata_port_info *pi_template,
912 + unsigned int force_port_map,
913 + unsigned int mask_port_map)
914 +{
915 + struct device *dev = &pdev->dev;
916 + struct ata_port_info pi = *pi_template;
917 + const struct ata_port_info *ppi[] = { &pi, NULL };
918 + struct ata_host *host;
919 + int i, irq, n_ports, rc;
920 +
921 + irq = platform_get_irq(pdev, 0);
922 + if (irq <= 0) {
923 + dev_err(dev, "no irq\n");
924 + return -EINVAL;
925 + }
926 +
927 + /* prepare host */
928 + hpriv->flags |= (unsigned long)pi.private_data;
929 +
930 + ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
931 +
932 + if (hpriv->cap & HOST_CAP_NCQ)
933 + pi.flags |= ATA_FLAG_NCQ;
934 +
935 + if (hpriv->cap & HOST_CAP_PMP)
936 + pi.flags |= ATA_FLAG_PMP;
937 +
938 + ahci_set_em_messages(hpriv, &pi);
939 +
940 + /* CAP.NP sometimes indicate the index of the last enabled
941 + * port, at other times, that of the last possible port, so
942 + * determining the maximum port number requires looking at
943 + * both CAP.NP and port_map.
944 + */
945 + n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
946 +
947 + host = ata_host_alloc_pinfo(dev, ppi, n_ports);
948 + if (!host)
949 + return -ENOMEM;
950 +
951 + host->private_data = hpriv;
952 +
953 + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
954 + host->flags |= ATA_HOST_PARALLEL_SCAN;
955 + else
956 + dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
957 +
958 + if (pi.flags & ATA_FLAG_EM)
959 + ahci_reset_em(host);
960 +
961 + for (i = 0; i < host->n_ports; i++) {
962 + struct ata_port *ap = host->ports[i];
963 +
964 + ata_port_desc(ap, "mmio %pR",
965 + platform_get_resource(pdev, IORESOURCE_MEM, 0));
966 + ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
967 +
968 + /* set enclosure management message type */
969 + if (ap->flags & ATA_FLAG_EM)
970 + ap->em_message_type = hpriv->em_msg_type;
971 +
972 + /* disabled/not-implemented port */
973 + if (!(hpriv->port_map & (1 << i)))
974 + ap->ops = &ata_dummy_port_ops;
975 + }
976 +
977 + rc = ahci_reset_controller(host);
978 + if (rc)
979 + return rc;
980 +
981 + ahci_init_controller(host);
982 + ahci_print_info(host, "platform");
983 +
984 + return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
985 + &ahci_platform_sht);
986 +}
987 +EXPORT_SYMBOL_GPL(ahci_platform_init_host);
988 +
989 +static void ahci_host_stop(struct ata_host *host)
990 +{
991 + struct device *dev = host->dev;
992 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
993 + struct ahci_host_priv *hpriv = host->private_data;
994 +
995 + if (pdata && pdata->exit)
996 + pdata->exit(dev);
997 +
998 + ahci_platform_disable_resources(hpriv);
999 +}
1000 +
1001 +#ifdef CONFIG_PM_SLEEP
1002 +/**
1003 + * ahci_platform_suspend_host - Suspend an ahci-platform host
1004 + * @dev: device pointer for the host
1005 + *
1006 + * This function does all the usual steps needed to suspend an
1007 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
1008 + * must be disabled after calling this.
1009 + *
1010 + * RETURNS:
1011 + * 0 on success otherwise a negative error code
1012 + */
1013 +int ahci_platform_suspend_host(struct device *dev)
1014 +{
1015 + struct ata_host *host = dev_get_drvdata(dev);
1016 + struct ahci_host_priv *hpriv = host->private_data;
1017 + void __iomem *mmio = hpriv->mmio;
1018 + u32 ctl;
1019 +
1020 + if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
1021 + dev_err(dev, "firmware update required for suspend/resume\n");
1022 + return -EIO;
1023 + }
1024 +
1025 + /*
1026 + * AHCI spec rev1.1 section 8.3.3:
1027 + * Software must disable interrupts prior to requesting a
1028 + * transition of the HBA to D3 state.
1029 + */
1030 + ctl = readl(mmio + HOST_CTL);
1031 + ctl &= ~HOST_IRQ_EN;
1032 + writel(ctl, mmio + HOST_CTL);
1033 + readl(mmio + HOST_CTL); /* flush */
1034 +
1035 + return ata_host_suspend(host, PMSG_SUSPEND);
1036 +}
1037 +EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
1038 +
1039 +/**
1040 + * ahci_platform_resume_host - Resume an ahci-platform host
1041 + * @dev: device pointer for the host
1042 + *
1043 + * This function does all the usual steps needed to resume an ahci-platform
1044 + * host, note any necessary resources (ie clks, phy, etc.) must be
1045 + * initialized / enabled before calling this.
1046 + *
1047 + * RETURNS:
1048 + * 0 on success otherwise a negative error code
1049 + */
1050 +int ahci_platform_resume_host(struct device *dev)
1051 +{
1052 + struct ata_host *host = dev_get_drvdata(dev);
1053 + int rc;
1054 +
1055 + if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
1056 + rc = ahci_reset_controller(host);
1057 + if (rc)
1058 + return rc;
1059 +
1060 + ahci_init_controller(host);
1061 + }
1062 +
1063 + ata_host_resume(host);
1064 +
1065 + return 0;
1066 +}
1067 +EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
1068 +
1069 +/**
1070 + * ahci_platform_suspend - Suspend an ahci-platform device
1071 + * @dev: the platform device to suspend
1072 + *
1073 + * This function suspends the host associated with the device, followed by
1074 + * disabling all the resources of the device.
1075 + *
1076 + * RETURNS:
1077 + * 0 on success otherwise a negative error code
1078 + */
1079 +int ahci_platform_suspend(struct device *dev)
1080 +{
1081 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
1082 + struct ata_host *host = dev_get_drvdata(dev);
1083 + struct ahci_host_priv *hpriv = host->private_data;
1084 + int rc;
1085 +
1086 + rc = ahci_platform_suspend_host(dev);
1087 + if (rc)
1088 + return rc;
1089 +
1090 + if (pdata && pdata->suspend) {
1091 + rc = pdata->suspend(dev);
1092 + if (rc)
1093 + goto resume_host;
1094 + }
1095 +
1096 + ahci_platform_disable_resources(hpriv);
1097 +
1098 + return 0;
1099 +
1100 +resume_host:
1101 + ahci_platform_resume_host(dev);
1102 + return rc;
1103 +}
1104 +EXPORT_SYMBOL_GPL(ahci_platform_suspend);
1105 +
1106 +/**
1107 + * ahci_platform_resume - Resume an ahci-platform device
1108 + * @dev: the platform device to resume
1109 + *
1110 + * This function enables all the resources of the device followed by
1111 + * resuming the host associated with the device.
1112 + *
1113 + * RETURNS:
1114 + * 0 on success otherwise a negative error code
1115 + */
1116 +int ahci_platform_resume(struct device *dev)
1117 +{
1118 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
1119 + struct ata_host *host = dev_get_drvdata(dev);
1120 + struct ahci_host_priv *hpriv = host->private_data;
1121 + int rc;
1122 +
1123 + rc = ahci_platform_enable_resources(hpriv);
1124 + if (rc)
1125 + return rc;
1126 +
1127 + if (pdata && pdata->resume) {
1128 + rc = pdata->resume(dev);
1129 + if (rc)
1130 + goto disable_resources;
1131 + }
1132 +
1133 + rc = ahci_platform_resume_host(dev);
1134 + if (rc)
1135 + goto disable_resources;
1136 +
1137 + /* We resumed so update PM runtime state */
1138 + pm_runtime_disable(dev);
1139 + pm_runtime_set_active(dev);
1140 + pm_runtime_enable(dev);
1141 +
1142 + return 0;
1143 +
1144 +disable_resources:
1145 + ahci_platform_disable_resources(hpriv);
1146 +
1147 + return rc;
1148 +}
1149 +EXPORT_SYMBOL_GPL(ahci_platform_resume);
1150 +#endif
1151 +
1152 +MODULE_DESCRIPTION("AHCI SATA platform library");
1153 +MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
1154 +MODULE_LICENSE("GPL");
1155 --
1156 1.7.10.4
1157