0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/kernel.h>
0013 #include <linux/gfp.h>
0014 #include <linux/module.h>
0015 #include <linux/pm.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/device.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/libata.h>
0020 #include <linux/ahci_platform.h>
0021 #include <linux/phy/phy.h>
0022 #include <linux/pm_runtime.h>
0023 #include <linux/of_platform.h>
0024 #include <linux/reset.h>
0025 #include "ahci.h"
0026
0027 static void ahci_host_stop(struct ata_host *host);
0028
0029 struct ata_port_operations ahci_platform_ops = {
0030 .inherits = &ahci_ops,
0031 .host_stop = ahci_host_stop,
0032 };
0033 EXPORT_SYMBOL_GPL(ahci_platform_ops);
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
0047 {
0048 int rc, i;
0049
0050 for (i = 0; i < hpriv->nports; i++) {
0051 rc = phy_init(hpriv->phys[i]);
0052 if (rc)
0053 goto disable_phys;
0054
0055 rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
0056 if (rc) {
0057 phy_exit(hpriv->phys[i]);
0058 goto disable_phys;
0059 }
0060
0061 rc = phy_power_on(hpriv->phys[i]);
0062 if (rc) {
0063 phy_exit(hpriv->phys[i]);
0064 goto disable_phys;
0065 }
0066 }
0067
0068 return 0;
0069
0070 disable_phys:
0071 while (--i >= 0) {
0072 phy_power_off(hpriv->phys[i]);
0073 phy_exit(hpriv->phys[i]);
0074 }
0075 return rc;
0076 }
0077 EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
0078
0079
0080
0081
0082
0083
0084
0085 void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
0086 {
0087 int i;
0088
0089 for (i = 0; i < hpriv->nports; i++) {
0090 phy_power_off(hpriv->phys[i]);
0091 phy_exit(hpriv->phys[i]);
0092 }
0093 }
0094 EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
0108 {
0109 int c, rc;
0110
0111 for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
0112 rc = clk_prepare_enable(hpriv->clks[c]);
0113 if (rc)
0114 goto disable_unprepare_clk;
0115 }
0116 return 0;
0117
0118 disable_unprepare_clk:
0119 while (--c >= 0)
0120 clk_disable_unprepare(hpriv->clks[c]);
0121 return rc;
0122 }
0123 EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
0124
0125
0126
0127
0128
0129
0130
0131
0132 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
0133 {
0134 int c;
0135
0136 for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
0137 if (hpriv->clks[c])
0138 clk_disable_unprepare(hpriv->clks[c]);
0139 }
0140 EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
0155 {
0156 int rc, i;
0157
0158 rc = regulator_enable(hpriv->ahci_regulator);
0159 if (rc)
0160 return rc;
0161
0162 rc = regulator_enable(hpriv->phy_regulator);
0163 if (rc)
0164 goto disable_ahci_pwrs;
0165
0166 for (i = 0; i < hpriv->nports; i++) {
0167 if (!hpriv->target_pwrs[i])
0168 continue;
0169
0170 rc = regulator_enable(hpriv->target_pwrs[i]);
0171 if (rc)
0172 goto disable_target_pwrs;
0173 }
0174
0175 return 0;
0176
0177 disable_target_pwrs:
0178 while (--i >= 0)
0179 if (hpriv->target_pwrs[i])
0180 regulator_disable(hpriv->target_pwrs[i]);
0181
0182 regulator_disable(hpriv->phy_regulator);
0183 disable_ahci_pwrs:
0184 regulator_disable(hpriv->ahci_regulator);
0185 return rc;
0186 }
0187 EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators);
0188
0189
0190
0191
0192
0193
0194
0195
0196 void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv)
0197 {
0198 int i;
0199
0200 for (i = 0; i < hpriv->nports; i++) {
0201 if (!hpriv->target_pwrs[i])
0202 continue;
0203 regulator_disable(hpriv->target_pwrs[i]);
0204 }
0205
0206 regulator_disable(hpriv->ahci_regulator);
0207 regulator_disable(hpriv->phy_regulator);
0208 }
0209 EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
0228 {
0229 int rc;
0230
0231 rc = ahci_platform_enable_regulators(hpriv);
0232 if (rc)
0233 return rc;
0234
0235 rc = ahci_platform_enable_clks(hpriv);
0236 if (rc)
0237 goto disable_regulator;
0238
0239 rc = reset_control_deassert(hpriv->rsts);
0240 if (rc)
0241 goto disable_clks;
0242
0243 rc = ahci_platform_enable_phys(hpriv);
0244 if (rc)
0245 goto disable_resets;
0246
0247 return 0;
0248
0249 disable_resets:
0250 reset_control_assert(hpriv->rsts);
0251
0252 disable_clks:
0253 ahci_platform_disable_clks(hpriv);
0254
0255 disable_regulator:
0256 ahci_platform_disable_regulators(hpriv);
0257
0258 return rc;
0259 }
0260 EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
0274 {
0275 ahci_platform_disable_phys(hpriv);
0276
0277 reset_control_assert(hpriv->rsts);
0278
0279 ahci_platform_disable_clks(hpriv);
0280
0281 ahci_platform_disable_regulators(hpriv);
0282 }
0283 EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
0284
0285 static void ahci_platform_put_resources(struct device *dev, void *res)
0286 {
0287 struct ahci_host_priv *hpriv = res;
0288 int c;
0289
0290 if (hpriv->got_runtime_pm) {
0291 pm_runtime_put_sync(dev);
0292 pm_runtime_disable(dev);
0293 }
0294
0295 for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
0296 clk_put(hpriv->clks[c]);
0297
0298
0299
0300
0301
0302 for (c = 0; c < hpriv->nports; c++)
0303 if (hpriv->target_pwrs && hpriv->target_pwrs[c])
0304 regulator_put(hpriv->target_pwrs[c]);
0305
0306 kfree(hpriv->target_pwrs);
0307 }
0308
0309 static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,
0310 struct device *dev, struct device_node *node)
0311 {
0312 int rc;
0313
0314 hpriv->phys[port] = devm_of_phy_get(dev, node, NULL);
0315
0316 if (!IS_ERR(hpriv->phys[port]))
0317 return 0;
0318
0319 rc = PTR_ERR(hpriv->phys[port]);
0320 switch (rc) {
0321 case -ENOSYS:
0322
0323 if (of_find_property(node, "phys", NULL)) {
0324 dev_err(dev,
0325 "couldn't get PHY in node %pOFn: ENOSYS\n",
0326 node);
0327 break;
0328 }
0329 fallthrough;
0330 case -ENODEV:
0331
0332 hpriv->phys[port] = NULL;
0333 rc = 0;
0334 break;
0335 case -EPROBE_DEFER:
0336
0337 break;
0338
0339 default:
0340 dev_err(dev,
0341 "couldn't get PHY in node %pOFn: %d\n",
0342 node, rc);
0343
0344 break;
0345 }
0346
0347 return rc;
0348 }
0349
0350 static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
0351 struct device *dev)
0352 {
0353 struct regulator *target_pwr;
0354 int rc = 0;
0355
0356 target_pwr = regulator_get(dev, "target");
0357
0358 if (!IS_ERR(target_pwr))
0359 hpriv->target_pwrs[port] = target_pwr;
0360 else
0361 rc = PTR_ERR(target_pwr);
0362
0363 return rc;
0364 }
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
0386 unsigned int flags)
0387 {
0388 struct device *dev = &pdev->dev;
0389 struct ahci_host_priv *hpriv;
0390 struct clk *clk;
0391 struct device_node *child;
0392 int i, enabled_ports = 0, rc = -ENOMEM, child_nodes;
0393 u32 mask_port_map = 0;
0394
0395 if (!devres_open_group(dev, NULL, GFP_KERNEL))
0396 return ERR_PTR(-ENOMEM);
0397
0398 hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
0399 GFP_KERNEL);
0400 if (!hpriv)
0401 goto err_out;
0402
0403 devres_add(dev, hpriv);
0404
0405 hpriv->mmio = devm_ioremap_resource(dev,
0406 platform_get_resource(pdev, IORESOURCE_MEM, 0));
0407 if (IS_ERR(hpriv->mmio)) {
0408 rc = PTR_ERR(hpriv->mmio);
0409 goto err_out;
0410 }
0411
0412 for (i = 0; i < AHCI_MAX_CLKS; i++) {
0413
0414
0415
0416
0417
0418
0419 if (i == 0)
0420 clk = clk_get(dev, NULL);
0421 else
0422 clk = of_clk_get(dev->of_node, i);
0423
0424 if (IS_ERR(clk)) {
0425 rc = PTR_ERR(clk);
0426 if (rc == -EPROBE_DEFER)
0427 goto err_out;
0428 break;
0429 }
0430 hpriv->clks[i] = clk;
0431 }
0432
0433 hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
0434 if (IS_ERR(hpriv->ahci_regulator)) {
0435 rc = PTR_ERR(hpriv->ahci_regulator);
0436 if (rc != 0)
0437 goto err_out;
0438 }
0439
0440 hpriv->phy_regulator = devm_regulator_get(dev, "phy");
0441 if (IS_ERR(hpriv->phy_regulator)) {
0442 rc = PTR_ERR(hpriv->phy_regulator);
0443 goto err_out;
0444 }
0445
0446 if (flags & AHCI_PLATFORM_GET_RESETS) {
0447 hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
0448 if (IS_ERR(hpriv->rsts)) {
0449 rc = PTR_ERR(hpriv->rsts);
0450 goto err_out;
0451 }
0452 }
0453
0454 hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
0455
0456
0457
0458
0459
0460
0461 if (!child_nodes)
0462 hpriv->nports = 1;
0463
0464 hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
0465 if (!hpriv->phys) {
0466 rc = -ENOMEM;
0467 goto err_out;
0468 }
0469
0470
0471
0472
0473 hpriv->target_pwrs = kcalloc(hpriv->nports, sizeof(*hpriv->target_pwrs), GFP_KERNEL);
0474 if (!hpriv->target_pwrs) {
0475 rc = -ENOMEM;
0476 goto err_out;
0477 }
0478
0479 if (child_nodes) {
0480 for_each_child_of_node(dev->of_node, child) {
0481 u32 port;
0482 struct platform_device *port_dev __maybe_unused;
0483
0484 if (!of_device_is_available(child))
0485 continue;
0486
0487 if (of_property_read_u32(child, "reg", &port)) {
0488 rc = -EINVAL;
0489 of_node_put(child);
0490 goto err_out;
0491 }
0492
0493 if (port >= hpriv->nports) {
0494 dev_warn(dev, "invalid port number %d\n", port);
0495 continue;
0496 }
0497 mask_port_map |= BIT(port);
0498
0499 #ifdef CONFIG_OF_ADDRESS
0500 of_platform_device_create(child, NULL, NULL);
0501
0502 port_dev = of_find_device_by_node(child);
0503
0504 if (port_dev) {
0505 rc = ahci_platform_get_regulator(hpriv, port,
0506 &port_dev->dev);
0507 if (rc == -EPROBE_DEFER) {
0508 of_node_put(child);
0509 goto err_out;
0510 }
0511 }
0512 #endif
0513
0514 rc = ahci_platform_get_phy(hpriv, port, dev, child);
0515 if (rc) {
0516 of_node_put(child);
0517 goto err_out;
0518 }
0519
0520 enabled_ports++;
0521 }
0522 if (!enabled_ports) {
0523 dev_warn(dev, "No port enabled\n");
0524 rc = -ENODEV;
0525 goto err_out;
0526 }
0527
0528 if (!hpriv->mask_port_map)
0529 hpriv->mask_port_map = mask_port_map;
0530 } else {
0531
0532
0533
0534
0535 rc = ahci_platform_get_phy(hpriv, 0, dev, dev->of_node);
0536 if (rc)
0537 goto err_out;
0538
0539 rc = ahci_platform_get_regulator(hpriv, 0, dev);
0540 if (rc == -EPROBE_DEFER)
0541 goto err_out;
0542 }
0543 pm_runtime_enable(dev);
0544 pm_runtime_get_sync(dev);
0545 hpriv->got_runtime_pm = true;
0546
0547 devres_remove_group(dev, NULL);
0548 return hpriv;
0549
0550 err_out:
0551 devres_release_group(dev, NULL);
0552 return ERR_PTR(rc);
0553 }
0554 EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 int ahci_platform_init_host(struct platform_device *pdev,
0571 struct ahci_host_priv *hpriv,
0572 const struct ata_port_info *pi_template,
0573 struct scsi_host_template *sht)
0574 {
0575 struct device *dev = &pdev->dev;
0576 struct ata_port_info pi = *pi_template;
0577 const struct ata_port_info *ppi[] = { &pi, NULL };
0578 struct ata_host *host;
0579 int i, irq, n_ports, rc;
0580
0581 irq = platform_get_irq(pdev, 0);
0582 if (irq < 0)
0583 return irq;
0584 if (!irq)
0585 return -EINVAL;
0586
0587 hpriv->irq = irq;
0588
0589
0590 pi.private_data = (void *)(unsigned long)hpriv->flags;
0591
0592 ahci_save_initial_config(dev, hpriv);
0593
0594 if (hpriv->cap & HOST_CAP_NCQ)
0595 pi.flags |= ATA_FLAG_NCQ;
0596
0597 if (hpriv->cap & HOST_CAP_PMP)
0598 pi.flags |= ATA_FLAG_PMP;
0599
0600 ahci_set_em_messages(hpriv, &pi);
0601
0602
0603
0604
0605
0606
0607 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
0608
0609 host = ata_host_alloc_pinfo(dev, ppi, n_ports);
0610 if (!host)
0611 return -ENOMEM;
0612
0613 host->private_data = hpriv;
0614
0615 if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
0616 host->flags |= ATA_HOST_PARALLEL_SCAN;
0617 else
0618 dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
0619
0620 if (pi.flags & ATA_FLAG_EM)
0621 ahci_reset_em(host);
0622
0623 for (i = 0; i < host->n_ports; i++) {
0624 struct ata_port *ap = host->ports[i];
0625
0626 ata_port_desc(ap, "mmio %pR",
0627 platform_get_resource(pdev, IORESOURCE_MEM, 0));
0628 ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
0629
0630
0631 if (ap->flags & ATA_FLAG_EM)
0632 ap->em_message_type = hpriv->em_msg_type;
0633
0634
0635 if (!(hpriv->port_map & (1 << i)))
0636 ap->ops = &ata_dummy_port_ops;
0637 }
0638
0639 if (hpriv->cap & HOST_CAP_64) {
0640 rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
0641 if (rc) {
0642 dev_err(dev, "Failed to enable 64-bit DMA.\n");
0643 return rc;
0644 }
0645 }
0646
0647 rc = ahci_reset_controller(host);
0648 if (rc)
0649 return rc;
0650
0651 ahci_init_controller(host);
0652 ahci_print_info(host, "platform");
0653
0654 return ahci_host_activate(host, sht);
0655 }
0656 EXPORT_SYMBOL_GPL(ahci_platform_init_host);
0657
0658 static void ahci_host_stop(struct ata_host *host)
0659 {
0660 struct ahci_host_priv *hpriv = host->private_data;
0661
0662 ahci_platform_disable_resources(hpriv);
0663 }
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673 void ahci_platform_shutdown(struct platform_device *pdev)
0674 {
0675 struct ata_host *host = platform_get_drvdata(pdev);
0676 struct ahci_host_priv *hpriv = host->private_data;
0677 void __iomem *mmio = hpriv->mmio;
0678 int i;
0679
0680 for (i = 0; i < host->n_ports; i++) {
0681 struct ata_port *ap = host->ports[i];
0682
0683
0684 if (ap->ops->freeze)
0685 ap->ops->freeze(ap);
0686
0687
0688 if (ap->ops->port_stop)
0689 ap->ops->port_stop(ap);
0690 }
0691
0692
0693 writel(readl(mmio + HOST_CTL) & ~HOST_IRQ_EN, mmio + HOST_CTL);
0694 readl(mmio + HOST_CTL);
0695 writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT);
0696 }
0697 EXPORT_SYMBOL_GPL(ahci_platform_shutdown);
0698
0699 #ifdef CONFIG_PM_SLEEP
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711 int ahci_platform_suspend_host(struct device *dev)
0712 {
0713 struct ata_host *host = dev_get_drvdata(dev);
0714 struct ahci_host_priv *hpriv = host->private_data;
0715 void __iomem *mmio = hpriv->mmio;
0716 u32 ctl;
0717
0718 if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
0719 dev_err(dev, "firmware update required for suspend/resume\n");
0720 return -EIO;
0721 }
0722
0723
0724
0725
0726
0727
0728 ctl = readl(mmio + HOST_CTL);
0729 ctl &= ~HOST_IRQ_EN;
0730 writel(ctl, mmio + HOST_CTL);
0731 readl(mmio + HOST_CTL);
0732
0733 if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
0734 ahci_platform_disable_phys(hpriv);
0735
0736 ata_host_suspend(host, PMSG_SUSPEND);
0737 return 0;
0738 }
0739 EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752 int ahci_platform_resume_host(struct device *dev)
0753 {
0754 struct ata_host *host = dev_get_drvdata(dev);
0755 struct ahci_host_priv *hpriv = host->private_data;
0756 int rc;
0757
0758 if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
0759 rc = ahci_reset_controller(host);
0760 if (rc)
0761 return rc;
0762
0763 ahci_init_controller(host);
0764 }
0765
0766 if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
0767 ahci_platform_enable_phys(hpriv);
0768
0769 ata_host_resume(host);
0770
0771 return 0;
0772 }
0773 EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785 int ahci_platform_suspend(struct device *dev)
0786 {
0787 struct ata_host *host = dev_get_drvdata(dev);
0788 struct ahci_host_priv *hpriv = host->private_data;
0789 int rc;
0790
0791 rc = ahci_platform_suspend_host(dev);
0792 if (rc)
0793 return rc;
0794
0795 ahci_platform_disable_resources(hpriv);
0796
0797 return 0;
0798 }
0799 EXPORT_SYMBOL_GPL(ahci_platform_suspend);
0800
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811 int ahci_platform_resume(struct device *dev)
0812 {
0813 struct ata_host *host = dev_get_drvdata(dev);
0814 struct ahci_host_priv *hpriv = host->private_data;
0815 int rc;
0816
0817 rc = ahci_platform_enable_resources(hpriv);
0818 if (rc)
0819 return rc;
0820
0821 rc = ahci_platform_resume_host(dev);
0822 if (rc)
0823 goto disable_resources;
0824
0825
0826 pm_runtime_disable(dev);
0827 pm_runtime_set_active(dev);
0828 pm_runtime_enable(dev);
0829
0830 return 0;
0831
0832 disable_resources:
0833 ahci_platform_disable_resources(hpriv);
0834
0835 return rc;
0836 }
0837 EXPORT_SYMBOL_GPL(ahci_platform_resume);
0838 #endif
0839
0840 MODULE_DESCRIPTION("AHCI SATA platform library");
0841 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
0842 MODULE_LICENSE("GPL");