vqmmc-ipq4019-regulator.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // Copyright (c) 2019 Mantas Pucka <[email protected]>
  4. // Copyright (c) 2019 Robert Marko <[email protected]>
  5. //
  6. // Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator
  7. #include <linux/io.h>
  8. #include <linux/module.h>
  9. #include <linux/of.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/regmap.h>
  12. #include <linux/regulator/driver.h>
  13. #include <linux/regulator/machine.h>
  14. #include <linux/regulator/of_regulator.h>
  15. static const unsigned int ipq4019_vmmc_voltages[] = {
  16. 1500000, 1800000, 2500000, 3000000,
  17. };
  18. static const struct regulator_ops ipq4019_regulator_voltage_ops = {
  19. .list_voltage = regulator_list_voltage_table,
  20. .map_voltage = regulator_map_voltage_ascend,
  21. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  22. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  23. };
  24. static const struct regulator_desc vmmc_regulator = {
  25. .name = "vmmcq",
  26. .ops = &ipq4019_regulator_voltage_ops,
  27. .type = REGULATOR_VOLTAGE,
  28. .owner = THIS_MODULE,
  29. .volt_table = ipq4019_vmmc_voltages,
  30. .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages),
  31. .vsel_reg = 0,
  32. .vsel_mask = 0x3,
  33. };
  34. static const struct regmap_config ipq4019_vmmcq_regmap_config = {
  35. .reg_bits = 32,
  36. .reg_stride = 4,
  37. .val_bits = 32,
  38. };
  39. static int ipq4019_regulator_probe(struct platform_device *pdev)
  40. {
  41. struct device *dev = &pdev->dev;
  42. struct regulator_init_data *init_data;
  43. struct regulator_config cfg = {};
  44. struct regulator_dev *rdev;
  45. struct regmap *rmap;
  46. void __iomem *base;
  47. init_data = of_get_regulator_init_data(dev, dev->of_node,
  48. &vmmc_regulator);
  49. if (!init_data)
  50. return -EINVAL;
  51. base = devm_platform_ioremap_resource(pdev, 0);
  52. if (IS_ERR(base))
  53. return PTR_ERR(base);
  54. rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config);
  55. if (IS_ERR(rmap))
  56. return PTR_ERR(rmap);
  57. cfg.dev = dev;
  58. cfg.init_data = init_data;
  59. cfg.of_node = dev->of_node;
  60. cfg.regmap = rmap;
  61. rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg);
  62. if (IS_ERR(rdev)) {
  63. dev_err(dev, "Failed to register regulator: %ld\n",
  64. PTR_ERR(rdev));
  65. return PTR_ERR(rdev);
  66. }
  67. platform_set_drvdata(pdev, rdev);
  68. return 0;
  69. }
  70. static const struct of_device_id regulator_ipq4019_of_match[] = {
  71. { .compatible = "qcom,vqmmc-ipq4019-regulator", },
  72. {},
  73. };
  74. static struct platform_driver ipq4019_regulator_driver = {
  75. .probe = ipq4019_regulator_probe,
  76. .driver = {
  77. .name = "vqmmc-ipq4019-regulator",
  78. .of_match_table = of_match_ptr(regulator_ipq4019_of_match),
  79. },
  80. };
  81. module_platform_driver(ipq4019_regulator_driver);
  82. MODULE_LICENSE("GPL");
  83. MODULE_AUTHOR("Mantas Pucka <[email protected]>");
  84. MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator");