hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/ata/ahci_brcm.c
....@@ -1,17 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Broadcom SATA3 AHCI Controller Driver
34 *
45 * Copyright © 2009-2015 Broadcom Corporation
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2, or (at your option)
9
- * any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
156 */
167
178 #include <linux/ahci_platform.h>
....@@ -82,6 +73,7 @@
8273 BRCM_SATA_BCM7425 = 1,
8374 BRCM_SATA_BCM7445,
8475 BRCM_SATA_NSP,
76
+ BRCM_SATA_BCM7216,
8577 };
8678
8779 enum brcm_ahci_quirks {
....@@ -346,24 +338,39 @@
346338 .port_ops = &ahci_brcm_platform_ops,
347339 };
348340
349
-#ifdef CONFIG_PM_SLEEP
350341 static int brcm_ahci_suspend(struct device *dev)
351342 {
352343 struct ata_host *host = dev_get_drvdata(dev);
353344 struct ahci_host_priv *hpriv = host->private_data;
354345 struct brcm_ahci_priv *priv = hpriv->plat_data;
346
+ int ret;
355347
356348 brcm_sata_phys_disable(priv);
357349
358
- return ahci_platform_suspend(dev);
350
+ if (IS_ENABLED(CONFIG_PM_SLEEP))
351
+ ret = ahci_platform_suspend(dev);
352
+ else
353
+ ret = 0;
354
+
355
+ if (priv->version != BRCM_SATA_BCM7216)
356
+ reset_control_assert(priv->rcdev);
357
+
358
+ return ret;
359359 }
360360
361
-static int brcm_ahci_resume(struct device *dev)
361
+static int __maybe_unused brcm_ahci_resume(struct device *dev)
362362 {
363363 struct ata_host *host = dev_get_drvdata(dev);
364364 struct ahci_host_priv *hpriv = host->private_data;
365365 struct brcm_ahci_priv *priv = hpriv->plat_data;
366
- int ret;
366
+ int ret = 0;
367
+
368
+ if (priv->version == BRCM_SATA_BCM7216)
369
+ ret = reset_control_reset(priv->rcdev);
370
+ else
371
+ ret = reset_control_deassert(priv->rcdev);
372
+ if (ret)
373
+ return ret;
367374
368375 /* Make sure clocks are turned on before re-configuration */
369376 ret = ahci_platform_enable_clks(hpriv);
....@@ -408,7 +415,6 @@
408415 ahci_platform_disable_clks(hpriv);
409416 return ret;
410417 }
411
-#endif
412418
413419 static struct scsi_host_template ahci_platform_sht = {
414420 AHCI_SHT(DRV_NAME),
....@@ -417,7 +423,9 @@
417423 static const struct of_device_id ahci_of_match[] = {
418424 {.compatible = "brcm,bcm7425-ahci", .data = (void *)BRCM_SATA_BCM7425},
419425 {.compatible = "brcm,bcm7445-ahci", .data = (void *)BRCM_SATA_BCM7445},
426
+ {.compatible = "brcm,bcm63138-ahci", .data = (void *)BRCM_SATA_BCM7445},
420427 {.compatible = "brcm,bcm-nsp-ahci", .data = (void *)BRCM_SATA_NSP},
428
+ {.compatible = "brcm,bcm7216-ahci", .data = (void *)BRCM_SATA_BCM7216},
421429 {},
422430 };
423431 MODULE_DEVICE_TABLE(of, ahci_of_match);
....@@ -426,6 +434,7 @@
426434 {
427435 const struct of_device_id *of_id;
428436 struct device *dev = &pdev->dev;
437
+ const char *reset_name = NULL;
429438 struct brcm_ahci_priv *priv;
430439 struct ahci_host_priv *hpriv;
431440 struct resource *res;
....@@ -447,16 +456,19 @@
447456 if (IS_ERR(priv->top_ctrl))
448457 return PTR_ERR(priv->top_ctrl);
449458
450
- /* Reset is optional depending on platform */
451
- priv->rcdev = devm_reset_control_get(&pdev->dev, "ahci");
452
- if (!IS_ERR_OR_NULL(priv->rcdev))
453
- reset_control_deassert(priv->rcdev);
459
+ /* Reset is optional depending on platform and named differently */
460
+ if (priv->version == BRCM_SATA_BCM7216)
461
+ reset_name = "rescal";
462
+ else
463
+ reset_name = "ahci";
464
+
465
+ priv->rcdev = devm_reset_control_get_optional(&pdev->dev, reset_name);
466
+ if (IS_ERR(priv->rcdev))
467
+ return PTR_ERR(priv->rcdev);
454468
455469 hpriv = ahci_platform_get_resources(pdev, 0);
456
- if (IS_ERR(hpriv)) {
457
- ret = PTR_ERR(hpriv);
458
- goto out_reset;
459
- }
470
+ if (IS_ERR(hpriv))
471
+ return PTR_ERR(hpriv);
460472
461473 hpriv->plat_data = priv;
462474 hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
....@@ -464,7 +476,7 @@
464476 switch (priv->version) {
465477 case BRCM_SATA_BCM7425:
466478 hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
467
- /* fall through */
479
+ fallthrough;
468480 case BRCM_SATA_NSP:
469481 hpriv->flags |= AHCI_HFLAG_NO_NCQ;
470482 priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
....@@ -472,6 +484,13 @@
472484 default:
473485 break;
474486 }
487
+
488
+ if (priv->version == BRCM_SATA_BCM7216)
489
+ ret = reset_control_reset(priv->rcdev);
490
+ else
491
+ ret = reset_control_deassert(priv->rcdev);
492
+ if (ret)
493
+ return ret;
475494
476495 ret = ahci_platform_enable_clks(hpriv);
477496 if (ret)
....@@ -520,7 +539,7 @@
520539 out_disable_clks:
521540 ahci_platform_disable_clks(hpriv);
522541 out_reset:
523
- if (!IS_ERR_OR_NULL(priv->rcdev))
542
+ if (priv->version != BRCM_SATA_BCM7216)
524543 reset_control_assert(priv->rcdev);
525544 return ret;
526545 }
....@@ -541,11 +560,26 @@
541560 return 0;
542561 }
543562
563
+static void brcm_ahci_shutdown(struct platform_device *pdev)
564
+{
565
+ int ret;
566
+
567
+ /* All resources releasing happens via devres, but our device, unlike a
568
+ * proper remove is not disappearing, therefore using
569
+ * brcm_ahci_suspend() here which does explicit power management is
570
+ * appropriate.
571
+ */
572
+ ret = brcm_ahci_suspend(&pdev->dev);
573
+ if (ret)
574
+ dev_err(&pdev->dev, "failed to shutdown\n");
575
+}
576
+
544577 static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
545578
546579 static struct platform_driver brcm_ahci_driver = {
547580 .probe = brcm_ahci_probe,
548581 .remove = brcm_ahci_remove,
582
+ .shutdown = brcm_ahci_shutdown,
549583 .driver = {
550584 .name = DRV_NAME,
551585 .of_match_table = ahci_of_match,