hi6421-pmic-core.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Device driver for Hi6421 PMIC
  4. *
  5. * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
  6. * http://www.hisilicon.com
  7. * Copyright (c) <2013-2017> Linaro Ltd.
  8. * https://www.linaro.org
  9. *
  10. * Author: Guodong Xu <[email protected]>
  11. */
  12. #include <linux/device.h>
  13. #include <linux/err.h>
  14. #include <linux/mfd/core.h>
  15. #include <linux/mfd/hi6421-pmic.h>
  16. #include <linux/module.h>
  17. #include <linux/of_device.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/regmap.h>
  20. static const struct mfd_cell hi6421_devs[] = {
  21. { .name = "hi6421-regulator", },
  22. };
  23. static const struct mfd_cell hi6421v530_devs[] = {
  24. { .name = "hi6421v530-regulator", },
  25. };
  26. static const struct regmap_config hi6421_regmap_config = {
  27. .reg_bits = 32,
  28. .reg_stride = 4,
  29. .val_bits = 8,
  30. .max_register = HI6421_REG_TO_BUS_ADDR(HI6421_REG_MAX),
  31. };
  32. static const struct of_device_id of_hi6421_pmic_match[] = {
  33. {
  34. .compatible = "hisilicon,hi6421-pmic",
  35. .data = (void *)HI6421
  36. },
  37. {
  38. .compatible = "hisilicon,hi6421v530-pmic",
  39. .data = (void *)HI6421_V530
  40. },
  41. { },
  42. };
  43. MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match);
  44. static int hi6421_pmic_probe(struct platform_device *pdev)
  45. {
  46. struct hi6421_pmic *pmic;
  47. struct resource *res;
  48. const struct of_device_id *id;
  49. const struct mfd_cell *subdevs;
  50. enum hi6421_type type;
  51. void __iomem *base;
  52. int n_subdevs, ret;
  53. id = of_match_device(of_hi6421_pmic_match, &pdev->dev);
  54. if (!id)
  55. return -EINVAL;
  56. type = (enum hi6421_type)id->data;
  57. pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
  58. if (!pmic)
  59. return -ENOMEM;
  60. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  61. base = devm_ioremap_resource(&pdev->dev, res);
  62. if (IS_ERR(base))
  63. return PTR_ERR(base);
  64. pmic->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
  65. &hi6421_regmap_config);
  66. if (IS_ERR(pmic->regmap)) {
  67. dev_err(&pdev->dev, "Failed to initialise Regmap: %ld\n",
  68. PTR_ERR(pmic->regmap));
  69. return PTR_ERR(pmic->regmap);
  70. }
  71. platform_set_drvdata(pdev, pmic);
  72. switch (type) {
  73. case HI6421:
  74. /* set over-current protection debounce 8ms */
  75. regmap_update_bits(pmic->regmap, HI6421_OCP_DEB_CTRL_REG,
  76. (HI6421_OCP_DEB_SEL_MASK
  77. | HI6421_OCP_EN_DEBOUNCE_MASK
  78. | HI6421_OCP_AUTO_STOP_MASK),
  79. (HI6421_OCP_DEB_SEL_8MS
  80. | HI6421_OCP_EN_DEBOUNCE_ENABLE));
  81. subdevs = hi6421_devs;
  82. n_subdevs = ARRAY_SIZE(hi6421_devs);
  83. break;
  84. case HI6421_V530:
  85. subdevs = hi6421v530_devs;
  86. n_subdevs = ARRAY_SIZE(hi6421v530_devs);
  87. break;
  88. default:
  89. dev_err(&pdev->dev, "Unknown device type %d\n",
  90. (unsigned int)type);
  91. return -EINVAL;
  92. }
  93. ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
  94. subdevs, n_subdevs, NULL, 0, NULL);
  95. if (ret) {
  96. dev_err(&pdev->dev, "Failed to add child devices: %d\n", ret);
  97. return ret;
  98. }
  99. return 0;
  100. }
  101. static struct platform_driver hi6421_pmic_driver = {
  102. .driver = {
  103. .name = "hi6421_pmic",
  104. .of_match_table = of_hi6421_pmic_match,
  105. },
  106. .probe = hi6421_pmic_probe,
  107. };
  108. module_platform_driver(hi6421_pmic_driver);
  109. MODULE_AUTHOR("Guodong Xu <[email protected]>");
  110. MODULE_DESCRIPTION("Hi6421 PMIC driver");
  111. MODULE_LICENSE("GPL v2");