tps6594-esm.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * ESM (Error Signal Monitor) driver for TI TPS6594/TPS6593/LP8764 PMICs
  4. *
  5. * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
  6. */
  7. #include <linux/interrupt.h>
  8. #include <linux/module.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/pm_runtime.h>
  11. #include <linux/regmap.h>
  12. #include <linux/mfd/tps6594.h>
  13. #define TPS6594_DEV_REV_1 0x08
  14. static irqreturn_t tps6594_esm_isr(int irq, void *dev_id)
  15. {
  16. struct platform_device *pdev = dev_id;
  17. int i;
  18. for (i = 0 ; i < pdev->num_resources ; i++) {
  19. if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
  20. dev_err(pdev->dev.parent, "%s error detected\n", pdev->resource[i].name);
  21. return IRQ_HANDLED;
  22. }
  23. }
  24. return IRQ_NONE;
  25. }
  26. static int tps6594_esm_probe(struct platform_device *pdev)
  27. {
  28. struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
  29. struct device *dev = &pdev->dev;
  30. unsigned int rev;
  31. int irq;
  32. int ret;
  33. int i;
  34. /*
  35. * Due to a bug in revision 1 of the PMIC, the GPIO3 used for the
  36. * SoC ESM function is used to power the load switch instead.
  37. * As a consequence, ESM can not be used on those PMIC.
  38. * Check the version and return an error in case of revision 1.
  39. */
  40. ret = regmap_read(tps->regmap, TPS6594_REG_DEV_REV, &rev);
  41. if (ret)
  42. return dev_err_probe(dev, ret,
  43. "Failed to read PMIC revision\n");
  44. if (rev == TPS6594_DEV_REV_1)
  45. return dev_err_probe(dev, -ENODEV,
  46. "ESM not supported for revision 1 PMIC\n");
  47. for (i = 0; i < pdev->num_resources; i++) {
  48. irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
  49. if (irq < 0)
  50. return irq;
  51. ret = devm_request_threaded_irq(dev, irq, NULL,
  52. tps6594_esm_isr, IRQF_ONESHOT,
  53. pdev->resource[i].name, pdev);
  54. if (ret)
  55. return dev_err_probe(dev, ret, "Failed to request irq\n");
  56. }
  57. ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
  58. TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
  59. if (ret)
  60. return dev_err_probe(dev, ret, "Failed to configure ESM\n");
  61. ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
  62. TPS6594_BIT_ESM_SOC_START);
  63. if (ret)
  64. return dev_err_probe(dev, ret, "Failed to start ESM\n");
  65. pm_runtime_enable(dev);
  66. pm_runtime_get_sync(dev);
  67. return 0;
  68. }
  69. static void tps6594_esm_remove(struct platform_device *pdev)
  70. {
  71. struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
  72. struct device *dev = &pdev->dev;
  73. int ret;
  74. ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
  75. TPS6594_BIT_ESM_SOC_START);
  76. if (ret) {
  77. dev_err(dev, "Failed to stop ESM\n");
  78. goto out;
  79. }
  80. ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
  81. TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
  82. if (ret)
  83. dev_err(dev, "Failed to unconfigure ESM\n");
  84. out:
  85. pm_runtime_put_sync(dev);
  86. pm_runtime_disable(dev);
  87. }
  88. static int tps6594_esm_suspend(struct device *dev)
  89. {
  90. struct tps6594 *tps = dev_get_drvdata(dev->parent);
  91. int ret;
  92. ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
  93. TPS6594_BIT_ESM_SOC_START);
  94. pm_runtime_put_sync(dev);
  95. return ret;
  96. }
  97. static int tps6594_esm_resume(struct device *dev)
  98. {
  99. struct tps6594 *tps = dev_get_drvdata(dev->parent);
  100. pm_runtime_get_sync(dev);
  101. return regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
  102. TPS6594_BIT_ESM_SOC_START);
  103. }
  104. static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_esm_pm_ops, tps6594_esm_suspend, tps6594_esm_resume);
  105. static struct platform_driver tps6594_esm_driver = {
  106. .driver = {
  107. .name = "tps6594-esm",
  108. .pm = pm_sleep_ptr(&tps6594_esm_pm_ops),
  109. },
  110. .probe = tps6594_esm_probe,
  111. .remove_new = tps6594_esm_remove,
  112. };
  113. module_platform_driver(tps6594_esm_driver);
  114. MODULE_ALIAS("platform:tps6594-esm");
  115. MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
  116. MODULE_DESCRIPTION("TPS6594 Error Signal Monitor Driver");
  117. MODULE_LICENSE("GPL");