mt6577_auxadc.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016 MediaTek Inc.
  4. * Author: Zhiyong Tao <[email protected]>
  5. */
  6. #include <linux/clk.h>
  7. #include <linux/delay.h>
  8. #include <linux/err.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/mod_devicetable.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/property.h>
  14. #include <linux/iopoll.h>
  15. #include <linux/io.h>
  16. #include <linux/iio/iio.h>
  17. /* Register definitions */
  18. #define MT6577_AUXADC_CON0 0x00
  19. #define MT6577_AUXADC_CON1 0x04
  20. #define MT6577_AUXADC_CON2 0x10
  21. #define MT6577_AUXADC_STA BIT(0)
  22. #define MT6577_AUXADC_DAT0 0x14
  23. #define MT6577_AUXADC_RDY0 BIT(12)
  24. #define MT6577_AUXADC_MISC 0x94
  25. #define MT6577_AUXADC_PDN_EN BIT(14)
  26. #define MT6577_AUXADC_DAT_MASK 0xfff
  27. #define MT6577_AUXADC_SLEEP_US 1000
  28. #define MT6577_AUXADC_TIMEOUT_US 10000
  29. #define MT6577_AUXADC_POWER_READY_MS 1
  30. #define MT6577_AUXADC_SAMPLE_READY_US 25
  31. struct mtk_auxadc_compatible {
  32. bool sample_data_cali;
  33. bool check_global_idle;
  34. };
  35. struct mt6577_auxadc_device {
  36. void __iomem *reg_base;
  37. struct clk *adc_clk;
  38. struct mutex lock;
  39. const struct mtk_auxadc_compatible *dev_comp;
  40. };
  41. static const struct mtk_auxadc_compatible mt8186_compat = {
  42. .sample_data_cali = false,
  43. .check_global_idle = false,
  44. };
  45. static const struct mtk_auxadc_compatible mt8173_compat = {
  46. .sample_data_cali = false,
  47. .check_global_idle = true,
  48. };
  49. static const struct mtk_auxadc_compatible mt6765_compat = {
  50. .sample_data_cali = true,
  51. .check_global_idle = false,
  52. };
  53. #define MT6577_AUXADC_CHANNEL(idx) { \
  54. .type = IIO_VOLTAGE, \
  55. .indexed = 1, \
  56. .channel = (idx), \
  57. .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
  58. }
  59. static const struct iio_chan_spec mt6577_auxadc_iio_channels[] = {
  60. MT6577_AUXADC_CHANNEL(0),
  61. MT6577_AUXADC_CHANNEL(1),
  62. MT6577_AUXADC_CHANNEL(2),
  63. MT6577_AUXADC_CHANNEL(3),
  64. MT6577_AUXADC_CHANNEL(4),
  65. MT6577_AUXADC_CHANNEL(5),
  66. MT6577_AUXADC_CHANNEL(6),
  67. MT6577_AUXADC_CHANNEL(7),
  68. MT6577_AUXADC_CHANNEL(8),
  69. MT6577_AUXADC_CHANNEL(9),
  70. MT6577_AUXADC_CHANNEL(10),
  71. MT6577_AUXADC_CHANNEL(11),
  72. MT6577_AUXADC_CHANNEL(12),
  73. MT6577_AUXADC_CHANNEL(13),
  74. MT6577_AUXADC_CHANNEL(14),
  75. MT6577_AUXADC_CHANNEL(15),
  76. };
  77. /* For Voltage calculation */
  78. #define VOLTAGE_FULL_RANGE 1500 /* VA voltage */
  79. #define AUXADC_PRECISE 4096 /* 12 bits */
  80. static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali)
  81. {
  82. return rawdata;
  83. }
  84. static inline void mt6577_auxadc_mod_reg(void __iomem *reg,
  85. u32 or_mask, u32 and_mask)
  86. {
  87. u32 val;
  88. val = readl(reg);
  89. val |= or_mask;
  90. val &= ~and_mask;
  91. writel(val, reg);
  92. }
  93. static int mt6577_auxadc_read(struct iio_dev *indio_dev,
  94. struct iio_chan_spec const *chan)
  95. {
  96. u32 val;
  97. void __iomem *reg_channel;
  98. int ret;
  99. struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
  100. reg_channel = adc_dev->reg_base + MT6577_AUXADC_DAT0 +
  101. chan->channel * 0x04;
  102. mutex_lock(&adc_dev->lock);
  103. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1,
  104. 0, 1 << chan->channel);
  105. /* read channel and make sure old ready bit == 0 */
  106. ret = readl_poll_timeout(reg_channel, val,
  107. ((val & MT6577_AUXADC_RDY0) == 0),
  108. MT6577_AUXADC_SLEEP_US,
  109. MT6577_AUXADC_TIMEOUT_US);
  110. if (ret < 0) {
  111. dev_err(indio_dev->dev.parent,
  112. "wait for channel[%d] ready bit clear time out\n",
  113. chan->channel);
  114. goto err_timeout;
  115. }
  116. /* set bit to trigger sample */
  117. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1,
  118. 1 << chan->channel, 0);
  119. /* we must delay here for hardware sample channel data */
  120. udelay(MT6577_AUXADC_SAMPLE_READY_US);
  121. if (adc_dev->dev_comp->check_global_idle) {
  122. /* check MTK_AUXADC_CON2 if auxadc is idle */
  123. ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2,
  124. val, ((val & MT6577_AUXADC_STA) == 0),
  125. MT6577_AUXADC_SLEEP_US,
  126. MT6577_AUXADC_TIMEOUT_US);
  127. if (ret < 0) {
  128. dev_err(indio_dev->dev.parent,
  129. "wait for auxadc idle time out\n");
  130. goto err_timeout;
  131. }
  132. }
  133. /* read channel and make sure ready bit == 1 */
  134. ret = readl_poll_timeout(reg_channel, val,
  135. ((val & MT6577_AUXADC_RDY0) != 0),
  136. MT6577_AUXADC_SLEEP_US,
  137. MT6577_AUXADC_TIMEOUT_US);
  138. if (ret < 0) {
  139. dev_err(indio_dev->dev.parent,
  140. "wait for channel[%d] data ready time out\n",
  141. chan->channel);
  142. goto err_timeout;
  143. }
  144. /* read data */
  145. val = readl(reg_channel) & MT6577_AUXADC_DAT_MASK;
  146. mutex_unlock(&adc_dev->lock);
  147. return val;
  148. err_timeout:
  149. mutex_unlock(&adc_dev->lock);
  150. return -ETIMEDOUT;
  151. }
  152. static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev,
  153. struct iio_chan_spec const *chan,
  154. int *val,
  155. int *val2,
  156. long info)
  157. {
  158. struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
  159. switch (info) {
  160. case IIO_CHAN_INFO_PROCESSED:
  161. *val = mt6577_auxadc_read(indio_dev, chan);
  162. if (*val < 0) {
  163. dev_err(indio_dev->dev.parent,
  164. "failed to sample data on channel[%d]\n",
  165. chan->channel);
  166. return *val;
  167. }
  168. if (adc_dev->dev_comp->sample_data_cali)
  169. *val = mt_auxadc_get_cali_data(*val, true);
  170. /* Convert adc raw data to voltage: 0 - 1500 mV */
  171. *val = *val * VOLTAGE_FULL_RANGE / AUXADC_PRECISE;
  172. return IIO_VAL_INT;
  173. default:
  174. return -EINVAL;
  175. }
  176. }
  177. static const struct iio_info mt6577_auxadc_info = {
  178. .read_raw = &mt6577_auxadc_read_raw,
  179. };
  180. static int mt6577_auxadc_resume(struct device *dev)
  181. {
  182. struct iio_dev *indio_dev = dev_get_drvdata(dev);
  183. struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
  184. int ret;
  185. ret = clk_prepare_enable(adc_dev->adc_clk);
  186. if (ret) {
  187. pr_err("failed to enable auxadc clock\n");
  188. return ret;
  189. }
  190. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  191. MT6577_AUXADC_PDN_EN, 0);
  192. mdelay(MT6577_AUXADC_POWER_READY_MS);
  193. return 0;
  194. }
  195. static int mt6577_auxadc_suspend(struct device *dev)
  196. {
  197. struct iio_dev *indio_dev = dev_get_drvdata(dev);
  198. struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
  199. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  200. 0, MT6577_AUXADC_PDN_EN);
  201. clk_disable_unprepare(adc_dev->adc_clk);
  202. return 0;
  203. }
  204. static int mt6577_auxadc_probe(struct platform_device *pdev)
  205. {
  206. struct mt6577_auxadc_device *adc_dev;
  207. unsigned long adc_clk_rate;
  208. struct iio_dev *indio_dev;
  209. int ret;
  210. indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
  211. if (!indio_dev)
  212. return -ENOMEM;
  213. adc_dev = iio_priv(indio_dev);
  214. indio_dev->name = dev_name(&pdev->dev);
  215. indio_dev->info = &mt6577_auxadc_info;
  216. indio_dev->modes = INDIO_DIRECT_MODE;
  217. indio_dev->channels = mt6577_auxadc_iio_channels;
  218. indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels);
  219. adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
  220. if (IS_ERR(adc_dev->reg_base)) {
  221. dev_err(&pdev->dev, "failed to get auxadc base address\n");
  222. return PTR_ERR(adc_dev->reg_base);
  223. }
  224. adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main");
  225. if (IS_ERR(adc_dev->adc_clk)) {
  226. dev_err(&pdev->dev, "failed to get auxadc clock\n");
  227. return PTR_ERR(adc_dev->adc_clk);
  228. }
  229. ret = clk_prepare_enable(adc_dev->adc_clk);
  230. if (ret) {
  231. dev_err(&pdev->dev, "failed to enable auxadc clock\n");
  232. return ret;
  233. }
  234. adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
  235. if (!adc_clk_rate) {
  236. ret = -EINVAL;
  237. dev_err(&pdev->dev, "null clock rate\n");
  238. goto err_disable_clk;
  239. }
  240. adc_dev->dev_comp = device_get_match_data(&pdev->dev);
  241. mutex_init(&adc_dev->lock);
  242. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  243. MT6577_AUXADC_PDN_EN, 0);
  244. mdelay(MT6577_AUXADC_POWER_READY_MS);
  245. platform_set_drvdata(pdev, indio_dev);
  246. ret = iio_device_register(indio_dev);
  247. if (ret < 0) {
  248. dev_err(&pdev->dev, "failed to register iio device\n");
  249. goto err_power_off;
  250. }
  251. return 0;
  252. err_power_off:
  253. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  254. 0, MT6577_AUXADC_PDN_EN);
  255. err_disable_clk:
  256. clk_disable_unprepare(adc_dev->adc_clk);
  257. return ret;
  258. }
  259. static int mt6577_auxadc_remove(struct platform_device *pdev)
  260. {
  261. struct iio_dev *indio_dev = platform_get_drvdata(pdev);
  262. struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
  263. iio_device_unregister(indio_dev);
  264. mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
  265. 0, MT6577_AUXADC_PDN_EN);
  266. clk_disable_unprepare(adc_dev->adc_clk);
  267. return 0;
  268. }
  269. static DEFINE_SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops,
  270. mt6577_auxadc_suspend,
  271. mt6577_auxadc_resume);
  272. static const struct of_device_id mt6577_auxadc_of_match[] = {
  273. { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat },
  274. { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat },
  275. { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat },
  276. { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat },
  277. { .compatible = "mediatek,mt8186-auxadc", .data = &mt8186_compat },
  278. { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat },
  279. { }
  280. };
  281. MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match);
  282. static struct platform_driver mt6577_auxadc_driver = {
  283. .driver = {
  284. .name = "mt6577-auxadc",
  285. .of_match_table = mt6577_auxadc_of_match,
  286. .pm = pm_sleep_ptr(&mt6577_auxadc_pm_ops),
  287. },
  288. .probe = mt6577_auxadc_probe,
  289. .remove = mt6577_auxadc_remove,
  290. };
  291. module_platform_driver(mt6577_auxadc_driver);
  292. MODULE_AUTHOR("Zhiyong Tao <[email protected]>");
  293. MODULE_DESCRIPTION("MTK AUXADC Device Driver");
  294. MODULE_LICENSE("GPL v2");