root/drivers/ata/libahci_platform.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ahci_platform_enable_phys
  2. ahci_platform_disable_phys
  3. ahci_platform_enable_clks
  4. ahci_platform_disable_clks
  5. ahci_platform_enable_regulators
  6. ahci_platform_disable_regulators
  7. ahci_platform_enable_resources
  8. ahci_platform_disable_resources
  9. ahci_platform_put_resources
  10. ahci_platform_get_phy
  11. ahci_platform_get_regulator
  12. ahci_platform_get_resources
  13. ahci_platform_init_host
  14. ahci_host_stop
  15. ahci_platform_shutdown
  16. ahci_platform_suspend_host
  17. ahci_platform_resume_host
  18. ahci_platform_suspend
  19. ahci_platform_resume

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

/* [<][>][^][v][top][bottom][index][help] */