stk6d2x_cal_gpio.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <stk6d2x.h>
  17. #include <linux/pwm.h>
  18. #define OSC_CAL_FREQ (40)
  19. static u16 cal_period = 0xffff;
  20. u16 ams_pwm_gpio_period(struct stk6d2x_data *alps_data);
  21. int stk6d2x_setup_pwm(struct stk6d2x_data *alps_data, long pwm_freq)
  22. {
  23. int ret = 0;
  24. stk6d2x_wrapper *stk_wrapper = container_of(alps_data, stk6d2x_wrapper, alps_data);
  25. struct device *dev = stk_wrapper->dev;
  26. struct clk *pclk = NULL;
  27. ALS_dbg("setup gpio pwm %d Hz\n", pwm_freq);
  28. pclk = devm_clk_get(dev, "gpio_pwm_default-clk");
  29. if (NULL == pclk) {
  30. ALS_err("get pclk (gpio_pwm_default-clk) error. \n");
  31. return -ENODEV;
  32. }
  33. if (pwm_freq > 0) {
  34. #if 0
  35. if (__clk_is_enabled(pclk)) {
  36. ALS_dbg("clk_disable_unprepare (pclk) start! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
  37. clk_disable_unprepare(pclk);
  38. }
  39. msleep_interruptible(10);
  40. #endif
  41. ret = clk_set_rate(pclk, pwm_freq);
  42. if (ret) {
  43. ALS_err("clk_set_rate (pclk) fail! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
  44. return ret;
  45. } else {
  46. ALS_dbg("clk_set_rate (pclk) success! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
  47. }
  48. if (!__clk_is_enabled(pclk)) {
  49. ret = clk_prepare_enable(pclk);
  50. if (ret) {
  51. ALS_err("clk_prepare_enable (pclk) fail! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
  52. return ret;
  53. } else {
  54. ALS_dbg("clk_prepare_enable (pclk) success! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
  55. }
  56. }
  57. } else {
  58. if (__clk_is_enabled(pclk)) {
  59. clk_disable_unprepare(pclk);
  60. ALS_dbg("clk_disable_unprepare (pclk) start! (clk_is_enabled: %d, clk_get_rate: %lld)", __clk_is_enabled(pclk), clk_get_rate(pclk));
  61. }
  62. }
  63. return ret;
  64. }
  65. ssize_t stk6d2x_osc_cal_store(struct device *dev,
  66. struct device_attribute *attr, const char *buf, size_t size)
  67. {
  68. stk6d2x_wrapper *stk_wrapper = dev_get_drvdata(dev);
  69. stk6d2x_data *alps_data = &stk_wrapper->alps_data;
  70. int pwm_Hz = 0;
  71. int err = 0;
  72. if (!data->osc_cal) {
  73. ALS_err("no osc calibration mode\n");
  74. return size;
  75. }
  76. err = kstrtoint(buf, 10, &pwm_Hz);
  77. if (err < 0) {
  78. ALS_err("kstrtoint failed.(%d)\n", err);
  79. return size;
  80. }
  81. if (pwm_Hz == 0) {
  82. ALS_dbg("pwm output stop! (%d Hz)\n", pwm_Hz);
  83. stk6d2x_setup_pwm(alps_data, 0);
  84. } else if ((pwm_Hz > 0) && (pwm_Hz <= 120)) {
  85. stk6d2x_pin_control(alps_data, true);
  86. if (pwm_Hz == 1) {
  87. ALS_dbg("pwm output start! (%d Hz)\n", OSC_CAL_FREQ);
  88. stk6d2x_osc_cal(alps_data);
  89. } else {
  90. ALS_dbg("pwm output start! (%d Hz)\n", pwm_Hz);
  91. stk6d2x_setup_pwm(alps_data, pwm_Hz);
  92. }
  93. } else {
  94. ALS_err("pwm out of range error! (%d Hz)\n", pwm_Hz);
  95. }
  96. return size;
  97. }
  98. void stk6d2x_osc_cal(struct stk6d2x_data *alps_data)
  99. {
  100. u16 ret;
  101. stk6d2x_setup_pwm(alps_data, OSC_CAL_FREQ);
  102. ret = ams_pwm_gpio_period(alps_data);
  103. if (ret != 0) {
  104. cal_period = ret;
  105. }
  106. ALS_dbg("cal_period = %d", ret);
  107. stk6d2x_setup_pwm(alps_data, 0);
  108. }
  109. u16 stk6d2x_get_pwm_calibration(void)
  110. {
  111. if (cal_period == 0)
  112. return 0xffff;
  113. return cal_period;
  114. }