Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * AHCI SATA platform library
4 *
5 * Copyright 2004-2005 Red Hat, Inc.
6 * Jeff Garzik <jgarzik@pobox.com>
7 * Copyright 2010 MontaVista Software, LLC.
8 * Anton Vorontsov <avorontsov@ru.mvista.com>
9 */
10
11#include <linux/clk.h>
12#include <linux/kernel.h>
13#include <linux/gfp.h>
14#include <linux/module.h>
15#include <linux/pm.h>
16#include <linux/interrupt.h>
17#include <linux/device.h>
18#include <linux/platform_device.h>
19#include <linux/libata.h>
20#include <linux/ahci_platform.h>
21#include <linux/phy/phy.h>
22#include <linux/pm_runtime.h>
23#include <linux/of.h>
24#include <linux/of_platform.h>
25#include <linux/reset.h>
26#include "ahci.h"
27
28static void ahci_host_stop(struct ata_host *host);
29
30struct ata_port_operations ahci_platform_ops = {
31 .inherits = &ahci_ops,
32 .host_stop = ahci_host_stop,
33};
34EXPORT_SYMBOL_GPL(ahci_platform_ops);
35
36/**
37 * ahci_platform_enable_phys - Enable PHYs
38 * @hpriv: host private area to store config values
39 *
40 * This function enables all the PHYs found in hpriv->phys, if any.
41 * If a PHY fails to be enabled, it disables all the PHYs already
42 * enabled in reverse order and returns an error.
43 *
44 * RETURNS:
45 * 0 on success otherwise a negative error code
46 */
47int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
48{
49 int rc, i;
50
51 for (i = 0; i < hpriv->nports; i++) {
52 if (ahci_ignore_port(hpriv, i))
53 continue;
54
55 rc = phy_init(hpriv->phys[i]);
56 if (rc)
57 goto disable_phys;
58
59 rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
60 if (rc) {
61 phy_exit(hpriv->phys[i]);
62 goto disable_phys;
63 }
64
65 rc = phy_power_on(hpriv->phys[i]);
66 if (rc) {
67 phy_exit(hpriv->phys[i]);
68 goto disable_phys;
69 }
70 }
71
72 return 0;
73
74disable_phys:
75 while (--i >= 0) {
76 if (ahci_ignore_port(hpriv, i))
77 continue;
78
79 phy_power_off(hpriv->phys[i]);
80 phy_exit(hpriv->phys[i]);
81 }
82 return rc;
83}
84EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
85
86/**
87 * ahci_platform_disable_phys - Disable PHYs
88 * @hpriv: host private area to store config values
89 *
90 * This function disables all PHYs found in hpriv->phys.
91 */
92void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
93{
94 int i;
95
96 for (i = 0; i < hpriv->nports; i++) {
97 if (ahci_ignore_port(hpriv, i))
98 continue;
99
100 phy_power_off(hpriv->phys[i]);
101 phy_exit(hpriv->phys[i]);
102 }
103}
104EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
105
106/**
107 * ahci_platform_find_clk - Find platform clock
108 * @hpriv: host private area to store config values
109 * @con_id: clock connection ID
110 *
111 * This function returns a pointer to the clock descriptor of the clock with
112 * the passed ID.
113 *
114 * RETURNS:
115 * Pointer to the clock descriptor on success otherwise NULL
116 */
117struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id)
118{
119 int i;
120
121 for (i = 0; i < hpriv->n_clks; i++) {
122 if (hpriv->clks[i].id && !strcmp(hpriv->clks[i].id, con_id))
123 return hpriv->clks[i].clk;
124 }
125
126 return NULL;
127}
128EXPORT_SYMBOL_GPL(ahci_platform_find_clk);
129
130/**
131 * ahci_platform_enable_clks - Enable platform clocks
132 * @hpriv: host private area to store config values
133 *
134 * This function enables all the clks found for the AHCI device.
135 *
136 * RETURNS:
137 * 0 on success otherwise a negative error code
138 */
139int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
140{
141 return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks);
142}
143EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
144
145/**
146 * ahci_platform_disable_clks - Disable platform clocks
147 * @hpriv: host private area to store config values
148 *
149 * This function disables all the clocks enabled before
150 * (bulk-clocks-disable function is supposed to do that in reverse
151 * from the enabling procedure order).
152 */
153void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
154{
155 clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks);
156}
157EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
158
159/**
160 * ahci_platform_deassert_rsts - Deassert/trigger platform resets
161 * @hpriv: host private area to store config values
162 *
163 * This function deasserts or triggers all the reset lines found for
164 * the AHCI device.
165 *
166 * RETURNS:
167 * 0 on success otherwise a negative error code
168 */
169int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv)
170{
171 if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER)
172 return reset_control_reset(hpriv->rsts);
173
174 return reset_control_deassert(hpriv->rsts);
175}
176EXPORT_SYMBOL_GPL(ahci_platform_deassert_rsts);
177
178/**
179 * ahci_platform_assert_rsts - Assert/rearm platform resets
180 * @hpriv: host private area to store config values
181 *
182 * This function asserts or rearms (for self-deasserting resets) all
183 * the reset controls found for the AHCI device.
184 *
185 * RETURNS:
186 * 0 on success otherwise a negative error code
187 */
188int ahci_platform_assert_rsts(struct ahci_host_priv *hpriv)
189{
190 if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER)
191 return reset_control_rearm(hpriv->rsts);
192
193 return reset_control_assert(hpriv->rsts);
194}
195EXPORT_SYMBOL_GPL(ahci_platform_assert_rsts);
196
197/**
198 * ahci_platform_enable_regulators - Enable regulators
199 * @hpriv: host private area to store config values
200 *
201 * This function enables all the regulators found in controller and
202 * hpriv->target_pwrs, if any. If a regulator fails to be enabled, it
203 * disables all the regulators already enabled in reverse order and
204 * returns an error.
205 *
206 * RETURNS:
207 * 0 on success otherwise a negative error code
208 */
209int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
210{
211 int rc, i;
212
213 rc = regulator_enable(hpriv->ahci_regulator);
214 if (rc)
215 return rc;
216
217 rc = regulator_enable(hpriv->phy_regulator);
218 if (rc)
219 goto disable_ahci_pwrs;
220
221 for (i = 0; i < hpriv->nports; i++) {
222 if (!hpriv->target_pwrs[i])
223 continue;
224
225 rc = regulator_enable(hpriv->target_pwrs[i]);
226 if (rc)
227 goto disable_target_pwrs;
228 }
229
230 return 0;
231
232disable_target_pwrs:
233 while (--i >= 0)
234 if (hpriv->target_pwrs[i])
235 regulator_disable(hpriv->target_pwrs[i]);
236
237 regulator_disable(hpriv->phy_regulator);
238disable_ahci_pwrs:
239 regulator_disable(hpriv->ahci_regulator);
240 return rc;
241}
242EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators);
243
244/**
245 * ahci_platform_disable_regulators - Disable regulators
246 * @hpriv: host private area to store config values
247 *
248 * This function disables all regulators found in hpriv->target_pwrs and
249 * AHCI controller.
250 */
251void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv)
252{
253 int i;
254
255 for (i = 0; i < hpriv->nports; i++) {
256 if (!hpriv->target_pwrs[i])
257 continue;
258 regulator_disable(hpriv->target_pwrs[i]);
259 }
260
261 regulator_disable(hpriv->ahci_regulator);
262 regulator_disable(hpriv->phy_regulator);
263}
264EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
265/**
266 * ahci_platform_enable_resources - Enable platform resources
267 * @hpriv: host private area to store config values
268 *
269 * This function enables all ahci_platform managed resources in the
270 * following order:
271 * 1) Regulator
272 * 2) Clocks (through ahci_platform_enable_clks)
273 * 3) Resets
274 * 4) Phys
275 *
276 * If resource enabling fails at any point the previous enabled resources
277 * are disabled in reverse order.
278 *
279 * RETURNS:
280 * 0 on success otherwise a negative error code
281 */
282int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
283{
284 int rc;
285
286 rc = ahci_platform_enable_regulators(hpriv);
287 if (rc)
288 return rc;
289
290 rc = ahci_platform_enable_clks(hpriv);
291 if (rc)
292 goto disable_regulator;
293
294 rc = ahci_platform_deassert_rsts(hpriv);
295 if (rc)
296 goto disable_clks;
297
298 rc = ahci_platform_enable_phys(hpriv);
299 if (rc)
300 goto disable_rsts;
301
302 return 0;
303
304disable_rsts:
305 ahci_platform_assert_rsts(hpriv);
306
307disable_clks:
308 ahci_platform_disable_clks(hpriv);
309
310disable_regulator:
311 ahci_platform_disable_regulators(hpriv);
312
313 return rc;
314}
315EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
316
317/**
318 * ahci_platform_disable_resources - Disable platform resources
319 * @hpriv: host private area to store config values
320 *
321 * This function disables all ahci_platform managed resources in the
322 * following order:
323 * 1) Phys
324 * 2) Resets
325 * 3) Clocks (through ahci_platform_disable_clks)
326 * 4) Regulator
327 */
328void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
329{
330 ahci_platform_disable_phys(hpriv);
331
332 ahci_platform_assert_rsts(hpriv);
333
334 ahci_platform_disable_clks(hpriv);
335
336 ahci_platform_disable_regulators(hpriv);
337}
338EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
339
340static void ahci_platform_put_resources(struct device *dev, void *res)
341{
342 struct ahci_host_priv *hpriv = res;
343 int c;
344
345 if (hpriv->got_runtime_pm) {
346 pm_runtime_put_sync(dev);
347 pm_runtime_disable(dev);
348 }
349
350 /*
351 * The regulators are tied to child node device and not to the
352 * SATA device itself. So we can't use devm for automatically
353 * releasing them. We have to do it manually here.
354 */
355 for (c = 0; c < hpriv->nports; c++)
356 if (hpriv->target_pwrs && hpriv->target_pwrs[c])
357 regulator_put(hpriv->target_pwrs[c]);
358
359 kfree(hpriv->target_pwrs);
360}
361
362static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,
363 struct device *dev, struct device_node *node)
364{
365 int rc;
366
367 hpriv->phys[port] = devm_of_phy_get(dev, node, NULL);
368
369 if (!IS_ERR(hpriv->phys[port]))
370 return 0;
371
372 rc = PTR_ERR(hpriv->phys[port]);
373 switch (rc) {
374 case -ENOSYS:
375 /* No PHY support. Check if PHY is required. */
376 if (of_property_present(node, "phys")) {
377 dev_err(dev,
378 "couldn't get PHY in node %pOFn: ENOSYS\n",
379 node);
380 break;
381 }
382 fallthrough;
383 case -ENODEV:
384 /* continue normally */
385 hpriv->phys[port] = NULL;
386 rc = 0;
387 break;
388 case -EPROBE_DEFER:
389 /* Do not complain yet */
390 break;
391
392 default:
393 dev_err(dev,
394 "couldn't get PHY in node %pOFn: %d\n",
395 node, rc);
396
397 break;
398 }
399
400 return rc;
401}
402
403static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
404 struct device *dev)
405{
406 struct regulator *target_pwr;
407 int rc = 0;
408
409 target_pwr = regulator_get(dev, "target");
410
411 if (!IS_ERR(target_pwr))
412 hpriv->target_pwrs[port] = target_pwr;
413 else
414 rc = PTR_ERR(target_pwr);
415
416 return rc;
417}
418
419static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
420 struct device *dev)
421{
422 u32 port;
423
424 if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
425 hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
426
427 of_property_read_u32(dev->of_node,
428 "ports-implemented", &hpriv->saved_port_map);
429
430 for_each_child_of_node_scoped(dev->of_node, child) {
431 if (!of_device_is_available(child))
432 continue;
433
434 if (of_property_read_u32(child, "reg", &port))
435 return -EINVAL;
436
437 if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
438 hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
439 }
440
441 return 0;
442}
443
444static u32 ahci_platform_find_max_port_id(struct device *dev)
445{
446 u32 max_port = 0;
447
448 for_each_child_of_node_scoped(dev->of_node, child) {
449 u32 port;
450
451 if (!of_property_read_u32(child, "reg", &port))
452 max_port = max(max_port, port);
453 }
454
455 return max_port;
456}
457
458/**
459 * ahci_platform_get_resources - Get platform resources
460 * @pdev: platform device to get resources for
461 * @flags: bitmap representing the resource to get
462 *
463 * This function allocates an ahci_host_priv struct, and gets the following
464 * resources, storing a reference to them inside the returned struct:
465 *
466 * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
467 * 2) regulator for controlling the targets power (optional)
468 * regulator for controlling the AHCI controller (optional)
469 * 3) all clocks specified in the devicetree node, or a single
470 * clock for non-OF platforms (optional)
471 * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
472 * 5) phys (optional)
473 *
474 * RETURNS:
475 * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
476 */
477struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
478 unsigned int flags)
479{
480 int child_nodes, rc = -ENOMEM, enabled_ports = 0;
481 struct device *dev = &pdev->dev;
482 struct ahci_host_priv *hpriv;
483 u32 mask_port_map = 0;
484 u32 max_port;
485
486 if (!devres_open_group(dev, NULL, GFP_KERNEL))
487 return ERR_PTR(-ENOMEM);
488
489 hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
490 GFP_KERNEL);
491 if (!hpriv)
492 goto err_out;
493
494 devres_add(dev, hpriv);
495
496 /*
497 * If the DT provided an "ahci" named resource, use it. Otherwise,
498 * fallback to using the default first resource for the device node.
499 */
500 if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"))
501 hpriv->mmio = devm_platform_ioremap_resource_byname(pdev, "ahci");
502 else
503 hpriv->mmio = devm_platform_ioremap_resource(pdev, 0);
504 if (IS_ERR(hpriv->mmio)) {
505 rc = PTR_ERR(hpriv->mmio);
506 goto err_out;
507 }
508
509 /*
510 * Bulk clocks getting procedure can fail to find any clock due to
511 * running on a non-OF platform or due to the clocks being defined in
512 * bypass of the DT firmware (like da850, spear13xx). In that case we
513 * fallback to getting a single clock source right from the dev clocks
514 * list.
515 */
516 rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
517 if (rc < 0)
518 goto err_out;
519
520 if (rc > 0) {
521 /* Got clocks in bulk */
522 hpriv->n_clks = rc;
523 } else {
524 /*
525 * No clock bulk found: fallback to manually getting
526 * the optional clock.
527 */
528 hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
529 if (!hpriv->clks) {
530 rc = -ENOMEM;
531 goto err_out;
532 }
533 hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
534 if (IS_ERR(hpriv->clks->clk)) {
535 rc = PTR_ERR(hpriv->clks->clk);
536 goto err_out;
537 } else if (hpriv->clks->clk) {
538 hpriv->clks->id = "ahci";
539 hpriv->n_clks = 1;
540 }
541 }
542
543 hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
544 if (IS_ERR(hpriv->ahci_regulator)) {
545 rc = PTR_ERR(hpriv->ahci_regulator);
546 if (rc != 0)
547 goto err_out;
548 }
549
550 hpriv->phy_regulator = devm_regulator_get(dev, "phy");
551 if (IS_ERR(hpriv->phy_regulator)) {
552 rc = PTR_ERR(hpriv->phy_regulator);
553 goto err_out;
554 }
555
556 if (flags & AHCI_PLATFORM_GET_RESETS) {
557 hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
558 if (IS_ERR(hpriv->rsts)) {
559 rc = PTR_ERR(hpriv->rsts);
560 goto err_out;
561 }
562
563 hpriv->f_rsts = flags & AHCI_PLATFORM_RST_TRIGGER;
564 }
565
566 /*
567 * Too many sub-nodes most likely means having something wrong with
568 * the firmware.
569 */
570 child_nodes = of_get_child_count(dev->of_node);
571 if (child_nodes > AHCI_MAX_PORTS) {
572 rc = -EINVAL;
573 goto err_out;
574 }
575
576 /* find maximum port id for allocating structures */
577 max_port = ahci_platform_find_max_port_id(dev);
578 /*
579 * Set nports according to maximum port id. Clamp at
580 * AHCI_MAX_PORTS, warning message for invalid port id
581 * is generated later.
582 * When DT has no sub-nodes max_port is 0, nports is 1,
583 * in order to be able to use the
584 * ahci_platform_[en|dis]able_[phys|regulators] functions.
585 */
586 hpriv->nports = min(AHCI_MAX_PORTS, max_port + 1);
587
588 hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
589 if (!hpriv->phys) {
590 rc = -ENOMEM;
591 goto err_out;
592 }
593 /*
594 * We cannot use devm_ here, since ahci_platform_put_resources() uses
595 * target_pwrs after devm_ have freed memory
596 */
597 hpriv->target_pwrs = kcalloc(hpriv->nports, sizeof(*hpriv->target_pwrs), GFP_KERNEL);
598 if (!hpriv->target_pwrs) {
599 rc = -ENOMEM;
600 goto err_out;
601 }
602
603 if (child_nodes) {
604 for_each_child_of_node_scoped(dev->of_node, child) {
605 u32 port;
606 struct platform_device *port_dev __maybe_unused;
607
608 if (!of_device_is_available(child))
609 continue;
610
611 if (of_property_read_u32(child, "reg", &port)) {
612 rc = -EINVAL;
613 goto err_out;
614 }
615
616 if (port >= hpriv->nports) {
617 dev_warn(dev, "invalid port number %d\n", port);
618 continue;
619 }
620 mask_port_map |= BIT(port);
621
622#ifdef CONFIG_OF_ADDRESS
623 of_platform_device_create(child, NULL, NULL);
624
625 port_dev = of_find_device_by_node(child);
626
627 if (port_dev) {
628 rc = ahci_platform_get_regulator(hpriv, port,
629 &port_dev->dev);
630 if (rc == -EPROBE_DEFER)
631 goto err_out;
632 }
633#endif
634
635 rc = ahci_platform_get_phy(hpriv, port, dev, child);
636 if (rc)
637 goto err_out;
638
639 enabled_ports++;
640 }
641 if (!enabled_ports) {
642 dev_warn(dev, "No port enabled\n");
643 rc = -ENODEV;
644 goto err_out;
645 }
646
647 if (!hpriv->mask_port_map)
648 hpriv->mask_port_map = mask_port_map;
649 } else {
650 /*
651 * If no sub-node was found, keep this for device tree
652 * compatibility
653 */
654 hpriv->mask_port_map |= BIT(0);
655
656 rc = ahci_platform_get_phy(hpriv, 0, dev, dev->of_node);
657 if (rc)
658 goto err_out;
659
660 rc = ahci_platform_get_regulator(hpriv, 0, dev);
661 if (rc == -EPROBE_DEFER)
662 goto err_out;
663 }
664
665 /*
666 * Retrieve firmware-specific flags which then will be used to set
667 * the HW-init fields of HBA and its ports
668 */
669 rc = ahci_platform_get_firmware(hpriv, dev);
670 if (rc)
671 goto err_out;
672
673 pm_runtime_enable(dev);
674 pm_runtime_get_sync(dev);
675 hpriv->got_runtime_pm = true;
676
677 devres_remove_group(dev, NULL);
678 return hpriv;
679
680err_out:
681 devres_release_group(dev, NULL);
682 return ERR_PTR(rc);
683}
684EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
685
686/**
687 * ahci_platform_init_host - Bring up an ahci-platform host
688 * @pdev: platform device pointer for the host
689 * @hpriv: ahci-host private data for the host
690 * @pi_template: template for the ata_port_info to use
691 * @sht: scsi_host_template to use when registering
692 *
693 * This function does all the usual steps needed to bring up an
694 * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
695 * must be initialized / enabled before calling this.
696 *
697 * RETURNS:
698 * 0 on success otherwise a negative error code
699 */
700int ahci_platform_init_host(struct platform_device *pdev,
701 struct ahci_host_priv *hpriv,
702 const struct ata_port_info *pi_template,
703 const struct scsi_host_template *sht)
704{
705 struct device *dev = &pdev->dev;
706 struct ata_port_info pi = *pi_template;
707 const struct ata_port_info *ppi[] = { &pi, NULL };
708 struct ata_host *host;
709 int i, irq, n_ports, rc;
710
711 irq = platform_get_irq(pdev, 0);
712 if (irq < 0)
713 return irq;
714 if (!irq)
715 return -EINVAL;
716
717 hpriv->irq = irq;
718
719 /* prepare host */
720 pi.private_data = (void *)(unsigned long)hpriv->flags;
721
722 ahci_save_initial_config(dev, hpriv);
723
724 if (hpriv->cap & HOST_CAP_NCQ)
725 pi.flags |= ATA_FLAG_NCQ;
726
727 if (hpriv->cap & HOST_CAP_PMP)
728 pi.flags |= ATA_FLAG_PMP;
729
730 ahci_set_em_messages(hpriv, &pi);
731
732 /* CAP.NP sometimes indicate the index of the last enabled
733 * port, at other times, that of the last possible port, so
734 * determining the maximum port number requires looking at
735 * both CAP.NP and port_map.
736 */
737 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
738
739 host = ata_host_alloc_pinfo(dev, ppi, n_ports);
740 if (!host)
741 return -ENOMEM;
742
743 host->private_data = hpriv;
744
745 if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
746 host->flags |= ATA_HOST_PARALLEL_SCAN;
747 else
748 dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
749
750 if (pi.flags & ATA_FLAG_EM)
751 ahci_reset_em(host);
752
753 for (i = 0; i < host->n_ports; i++) {
754 struct ata_port *ap = host->ports[i];
755
756 ata_port_desc(ap, "mmio %pR",
757 platform_get_resource(pdev, IORESOURCE_MEM, 0));
758 ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
759
760 /* set enclosure management message type */
761 if (ap->flags & ATA_FLAG_EM)
762 ap->em_message_type = hpriv->em_msg_type;
763
764 /* disabled/not-implemented port */
765 if (!(hpriv->port_map & (1 << i)))
766 ap->ops = &ata_dummy_port_ops;
767 }
768
769 if (hpriv->cap & HOST_CAP_64) {
770 rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
771 if (rc) {
772 dev_err(dev, "Failed to enable 64-bit DMA.\n");
773 return rc;
774 }
775 }
776
777 rc = ahci_reset_controller(host);
778 if (rc)
779 return rc;
780
781 ahci_init_controller(host);
782 ahci_print_info(host, "platform");
783
784 return ahci_host_activate(host, sht);
785}
786EXPORT_SYMBOL_GPL(ahci_platform_init_host);
787
788static void ahci_host_stop(struct ata_host *host)
789{
790 struct ahci_host_priv *hpriv = host->private_data;
791
792 ahci_platform_disable_resources(hpriv);
793}
794
795/**
796 * ahci_platform_shutdown - Disable interrupts and stop DMA for host ports
797 * @pdev: platform device pointer for the host
798 *
799 * This function is called during system shutdown and performs the minimal
800 * deconfiguration required to ensure that an ahci_platform host cannot
801 * corrupt or otherwise interfere with a new kernel being started with kexec.
802 */
803void ahci_platform_shutdown(struct platform_device *pdev)
804{
805 struct ata_host *host = platform_get_drvdata(pdev);
806 struct ahci_host_priv *hpriv = host->private_data;
807 void __iomem *mmio = hpriv->mmio;
808 int i;
809
810 for (i = 0; i < host->n_ports; i++) {
811 struct ata_port *ap = host->ports[i];
812
813 /* Disable port interrupts */
814 if (ap->ops->freeze)
815 ap->ops->freeze(ap);
816
817 /* Stop the port DMA engines */
818 if (ap->ops->port_stop)
819 ap->ops->port_stop(ap);
820 }
821
822 /* Disable and clear host interrupts */
823 writel(readl(mmio + HOST_CTL) & ~HOST_IRQ_EN, mmio + HOST_CTL);
824 readl(mmio + HOST_CTL); /* flush */
825 writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT);
826}
827EXPORT_SYMBOL_GPL(ahci_platform_shutdown);
828
829#ifdef CONFIG_PM_SLEEP
830/**
831 * ahci_platform_suspend_host - Suspend an ahci-platform host
832 * @dev: device pointer for the host
833 *
834 * This function does all the usual steps needed to suspend an
835 * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
836 * must be disabled after calling this.
837 *
838 * RETURNS:
839 * 0 on success otherwise a negative error code
840 */
841int ahci_platform_suspend_host(struct device *dev)
842{
843 struct ata_host *host = dev_get_drvdata(dev);
844 struct ahci_host_priv *hpriv = host->private_data;
845 void __iomem *mmio = hpriv->mmio;
846 u32 ctl;
847
848 if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
849 dev_err(dev, "firmware update required for suspend/resume\n");
850 return -EIO;
851 }
852
853 /*
854 * AHCI spec rev1.1 section 8.3.3:
855 * Software must disable interrupts prior to requesting a
856 * transition of the HBA to D3 state.
857 */
858 ctl = readl(mmio + HOST_CTL);
859 ctl &= ~HOST_IRQ_EN;
860 writel(ctl, mmio + HOST_CTL);
861 readl(mmio + HOST_CTL); /* flush */
862
863 if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
864 ahci_platform_disable_phys(hpriv);
865
866 ata_host_suspend(host, PMSG_SUSPEND);
867 return 0;
868}
869EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
870
871/**
872 * ahci_platform_resume_host - Resume an ahci-platform host
873 * @dev: device pointer for the host
874 *
875 * This function does all the usual steps needed to resume an ahci-platform
876 * host, note any necessary resources (ie clks, phys, etc.) must be
877 * initialized / enabled before calling this.
878 *
879 * RETURNS:
880 * 0 on success otherwise a negative error code
881 */
882int ahci_platform_resume_host(struct device *dev)
883{
884 struct ata_host *host = dev_get_drvdata(dev);
885 struct ahci_host_priv *hpriv = host->private_data;
886 int rc;
887
888 if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
889 rc = ahci_reset_controller(host);
890 if (rc)
891 return rc;
892
893 ahci_init_controller(host);
894 }
895
896 if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
897 ahci_platform_enable_phys(hpriv);
898
899 ata_host_resume(host);
900
901 return 0;
902}
903EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
904
905/**
906 * ahci_platform_suspend - Suspend an ahci-platform device
907 * @dev: the platform device to suspend
908 *
909 * This function suspends the host associated with the device, followed by
910 * disabling all the resources of the device.
911 *
912 * RETURNS:
913 * 0 on success otherwise a negative error code
914 */
915int ahci_platform_suspend(struct device *dev)
916{
917 struct ata_host *host = dev_get_drvdata(dev);
918 struct ahci_host_priv *hpriv = host->private_data;
919 int rc;
920
921 rc = ahci_platform_suspend_host(dev);
922 if (rc)
923 return rc;
924
925 ahci_platform_disable_resources(hpriv);
926
927 return 0;
928}
929EXPORT_SYMBOL_GPL(ahci_platform_suspend);
930
931/**
932 * ahci_platform_resume - Resume an ahci-platform device
933 * @dev: the platform device to resume
934 *
935 * This function enables all the resources of the device followed by
936 * resuming the host associated with the device.
937 *
938 * RETURNS:
939 * 0 on success otherwise a negative error code
940 */
941int ahci_platform_resume(struct device *dev)
942{
943 struct ata_host *host = dev_get_drvdata(dev);
944 struct ahci_host_priv *hpriv = host->private_data;
945 int rc;
946
947 rc = ahci_platform_enable_resources(hpriv);
948 if (rc)
949 return rc;
950
951 rc = ahci_platform_resume_host(dev);
952 if (rc)
953 goto disable_resources;
954
955 /* We resumed so update PM runtime state */
956 pm_runtime_disable(dev);
957 pm_runtime_set_active(dev);
958 pm_runtime_enable(dev);
959
960 return 0;
961
962disable_resources:
963 ahci_platform_disable_resources(hpriv);
964
965 return rc;
966}
967EXPORT_SYMBOL_GPL(ahci_platform_resume);
968#endif
969
970MODULE_DESCRIPTION("AHCI SATA platform library");
971MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
972MODULE_LICENSE("GPL");