mt6311-regulator.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (c) 2015 MediaTek Inc.
  4. // Author: Henry Chen <henryc.chen@mediatek.com>
  5. #include <linux/err.h>
  6. #include <linux/i2c.h>
  7. #include <linux/init.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/module.h>
  10. #include <linux/regmap.h>
  11. #include <linux/regulator/driver.h>
  12. #include <linux/regulator/machine.h>
  13. #include <linux/regulator/of_regulator.h>
  14. #include <linux/regulator/mt6311.h>
  15. #include <linux/slab.h>
  16. #include "mt6311-regulator.h"
  17. static const struct regmap_config mt6311_regmap_config = {
  18. .reg_bits = 8,
  19. .val_bits = 8,
  20. .max_register = MT6311_FQMTR_CON4,
  21. .cache_type = REGCACHE_MAPLE,
  22. };
  23. /* Default limits measured in millivolts and milliamps */
  24. #define MT6311_MIN_UV 600000
  25. #define MT6311_MAX_UV 1393750
  26. #define MT6311_STEP_UV 6250
  27. static const struct regulator_ops mt6311_buck_ops = {
  28. .list_voltage = regulator_list_voltage_linear,
  29. .map_voltage = regulator_map_voltage_linear,
  30. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  31. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  32. .set_voltage_time_sel = regulator_set_voltage_time_sel,
  33. .enable = regulator_enable_regmap,
  34. .disable = regulator_disable_regmap,
  35. .is_enabled = regulator_is_enabled_regmap,
  36. };
  37. static const struct regulator_ops mt6311_ldo_ops = {
  38. .enable = regulator_enable_regmap,
  39. .disable = regulator_disable_regmap,
  40. .is_enabled = regulator_is_enabled_regmap,
  41. };
  42. #define MT6311_BUCK(_id) \
  43. {\
  44. .name = #_id,\
  45. .ops = &mt6311_buck_ops,\
  46. .of_match = of_match_ptr(#_id),\
  47. .regulators_node = of_match_ptr("regulators"),\
  48. .type = REGULATOR_VOLTAGE,\
  49. .id = MT6311_ID_##_id,\
  50. .n_voltages = (MT6311_MAX_UV - MT6311_MIN_UV) / MT6311_STEP_UV + 1,\
  51. .min_uV = MT6311_MIN_UV,\
  52. .uV_step = MT6311_STEP_UV,\
  53. .owner = THIS_MODULE,\
  54. .enable_reg = MT6311_VDVFS11_CON9,\
  55. .enable_mask = MT6311_PMIC_VDVFS11_EN_MASK,\
  56. .vsel_reg = MT6311_VDVFS11_CON12,\
  57. .vsel_mask = MT6311_PMIC_VDVFS11_VOSEL_MASK,\
  58. }
  59. #define MT6311_LDO(_id) \
  60. {\
  61. .name = #_id,\
  62. .ops = &mt6311_ldo_ops,\
  63. .of_match = of_match_ptr(#_id),\
  64. .regulators_node = of_match_ptr("regulators"),\
  65. .type = REGULATOR_VOLTAGE,\
  66. .id = MT6311_ID_##_id,\
  67. .owner = THIS_MODULE,\
  68. .enable_reg = MT6311_LDO_CON3,\
  69. .enable_mask = MT6311_PMIC_RG_VBIASN_EN_MASK,\
  70. }
  71. static const struct regulator_desc mt6311_regulators[] = {
  72. MT6311_BUCK(VDVFS),
  73. MT6311_LDO(VBIASN),
  74. };
  75. /*
  76. * I2C driver interface functions
  77. */
  78. static int mt6311_i2c_probe(struct i2c_client *i2c)
  79. {
  80. struct regulator_config config = { };
  81. struct regulator_dev *rdev;
  82. struct regmap *regmap;
  83. int i, ret;
  84. unsigned int data;
  85. regmap = devm_regmap_init_i2c(i2c, &mt6311_regmap_config);
  86. if (IS_ERR(regmap)) {
  87. ret = PTR_ERR(regmap);
  88. dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
  89. ret);
  90. return ret;
  91. }
  92. ret = regmap_read(regmap, MT6311_SWCID, &data);
  93. if (ret < 0) {
  94. dev_err(&i2c->dev, "Failed to read DEVICE_ID reg: %d\n", ret);
  95. return ret;
  96. }
  97. switch (data) {
  98. case MT6311_E1_CID_CODE:
  99. case MT6311_E2_CID_CODE:
  100. case MT6311_E3_CID_CODE:
  101. break;
  102. default:
  103. dev_err(&i2c->dev, "Unsupported device id = 0x%x.\n", data);
  104. return -ENODEV;
  105. }
  106. for (i = 0; i < MT6311_MAX_REGULATORS; i++) {
  107. config.dev = &i2c->dev;
  108. config.regmap = regmap;
  109. rdev = devm_regulator_register(&i2c->dev,
  110. &mt6311_regulators[i], &config);
  111. if (IS_ERR(rdev)) {
  112. dev_err(&i2c->dev,
  113. "Failed to register MT6311 regulator\n");
  114. return PTR_ERR(rdev);
  115. }
  116. }
  117. return 0;
  118. }
  119. static const struct i2c_device_id mt6311_i2c_id[] = {
  120. { "mt6311" },
  121. {}
  122. };
  123. MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id);
  124. #ifdef CONFIG_OF
  125. static const struct of_device_id mt6311_dt_ids[] = {
  126. { .compatible = "mediatek,mt6311-regulator",
  127. .data = &mt6311_i2c_id[0] },
  128. {},
  129. };
  130. MODULE_DEVICE_TABLE(of, mt6311_dt_ids);
  131. #endif
  132. static struct i2c_driver mt6311_regulator_driver = {
  133. .driver = {
  134. .name = "mt6311",
  135. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  136. .of_match_table = of_match_ptr(mt6311_dt_ids),
  137. },
  138. .probe = mt6311_i2c_probe,
  139. .id_table = mt6311_i2c_id,
  140. };
  141. module_i2c_driver(mt6311_regulator_driver);
  142. MODULE_AUTHOR("Henry Chen <henryc.chen@mediatek.com>");
  143. MODULE_DESCRIPTION("Regulator device driver for Mediatek MT6311");
  144. MODULE_LICENSE("GPL v2");