tps65911-comparator.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * tps65910.c -- TI TPS6591x
  4. *
  5. * Copyright 2010 Texas Instruments Inc.
  6. *
  7. * Author: Jorge Eduardo Candelaria <[email protected]>
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/init.h>
  12. #include <linux/slab.h>
  13. #include <linux/err.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/debugfs.h>
  16. #include <linux/gpio.h>
  17. #include <linux/mfd/tps65910.h>
  18. #define COMP1 0
  19. #define COMP2 1
  20. /* Comparator 1 voltage selection table in millivolts */
  21. static const u16 COMP_VSEL_TABLE[] = {
  22. 0, 2500, 2500, 2500, 2500, 2550, 2600, 2650,
  23. 2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050,
  24. 3100, 3150, 3200, 3250, 3300, 3350, 3400, 3450,
  25. 3500,
  26. };
  27. struct comparator {
  28. const char *name;
  29. int reg;
  30. int uV_max;
  31. const u16 *vsel_table;
  32. };
  33. static struct comparator tps_comparators[] = {
  34. {
  35. .name = "COMP1",
  36. .reg = TPS65911_VMBCH,
  37. .uV_max = 3500,
  38. .vsel_table = COMP_VSEL_TABLE,
  39. },
  40. {
  41. .name = "COMP2",
  42. .reg = TPS65911_VMBCH2,
  43. .uV_max = 3500,
  44. .vsel_table = COMP_VSEL_TABLE,
  45. },
  46. };
  47. static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
  48. {
  49. struct comparator tps_comp = tps_comparators[id];
  50. int curr_voltage = 0;
  51. int ret;
  52. u8 index = 0, val;
  53. while (curr_voltage < tps_comp.uV_max) {
  54. curr_voltage = tps_comp.vsel_table[index];
  55. if (curr_voltage >= voltage)
  56. break;
  57. else if (curr_voltage < voltage)
  58. index ++;
  59. }
  60. if (curr_voltage > tps_comp.uV_max)
  61. return -EINVAL;
  62. val = index << 1;
  63. ret = regmap_write(tps65910->regmap, tps_comp.reg, val);
  64. return ret;
  65. }
  66. static int comp_threshold_get(struct tps65910 *tps65910, int id)
  67. {
  68. struct comparator tps_comp = tps_comparators[id];
  69. unsigned int val;
  70. int ret;
  71. ret = regmap_read(tps65910->regmap, tps_comp.reg, &val);
  72. if (ret < 0)
  73. return ret;
  74. val >>= 1;
  75. return tps_comp.vsel_table[val];
  76. }
  77. static ssize_t comp_threshold_show(struct device *dev,
  78. struct device_attribute *attr, char *buf)
  79. {
  80. struct tps65910 *tps65910 = dev_get_drvdata(dev->parent);
  81. struct attribute comp_attr = attr->attr;
  82. int id, uVolt;
  83. if (!strcmp(comp_attr.name, "comp1_threshold"))
  84. id = COMP1;
  85. else if (!strcmp(comp_attr.name, "comp2_threshold"))
  86. id = COMP2;
  87. else
  88. return -EINVAL;
  89. uVolt = comp_threshold_get(tps65910, id);
  90. return sprintf(buf, "%d\n", uVolt);
  91. }
  92. static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL);
  93. static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
  94. static int tps65911_comparator_probe(struct platform_device *pdev)
  95. {
  96. struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
  97. struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
  98. int ret;
  99. ret = comp_threshold_set(tps65910, COMP1, pdata->vmbch_threshold);
  100. if (ret < 0) {
  101. dev_err(&pdev->dev, "cannot set COMP1 threshold\n");
  102. return ret;
  103. }
  104. ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold);
  105. if (ret < 0) {
  106. dev_err(&pdev->dev, "cannot set COMP2 threshold\n");
  107. return ret;
  108. }
  109. /* Create sysfs entry */
  110. ret = device_create_file(&pdev->dev, &dev_attr_comp1_threshold);
  111. if (ret < 0)
  112. dev_err(&pdev->dev, "failed to add COMP1 sysfs file\n");
  113. ret = device_create_file(&pdev->dev, &dev_attr_comp2_threshold);
  114. if (ret < 0)
  115. dev_err(&pdev->dev, "failed to add COMP2 sysfs file\n");
  116. return ret;
  117. }
  118. static int tps65911_comparator_remove(struct platform_device *pdev)
  119. {
  120. struct tps65910 *tps65910;
  121. tps65910 = dev_get_drvdata(pdev->dev.parent);
  122. device_remove_file(&pdev->dev, &dev_attr_comp2_threshold);
  123. device_remove_file(&pdev->dev, &dev_attr_comp1_threshold);
  124. return 0;
  125. }
  126. static struct platform_driver tps65911_comparator_driver = {
  127. .driver = {
  128. .name = "tps65911-comparator",
  129. },
  130. .probe = tps65911_comparator_probe,
  131. .remove = tps65911_comparator_remove,
  132. };
  133. static int __init tps65911_comparator_init(void)
  134. {
  135. return platform_driver_register(&tps65911_comparator_driver);
  136. }
  137. subsys_initcall(tps65911_comparator_init);
  138. static void __exit tps65911_comparator_exit(void)
  139. {
  140. platform_driver_unregister(&tps65911_comparator_driver);
  141. }
  142. module_exit(tps65911_comparator_exit);
  143. MODULE_AUTHOR("Jorge Eduardo Candelaria <[email protected]>");
  144. MODULE_DESCRIPTION("TPS65911 comparator driver");
  145. MODULE_LICENSE("GPL v2");
  146. MODULE_ALIAS("platform:tps65911-comparator");