intel_pmic_chtwc.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Intel CHT Whiskey Cove PMIC operation region driver
  4. * Copyright (C) 2017 Hans de Goede <[email protected]>
  5. *
  6. * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
  7. * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
  8. */
  9. #include <linux/acpi.h>
  10. #include <linux/init.h>
  11. #include <linux/mfd/intel_soc_pmic.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/regmap.h>
  14. #include "intel_pmic.h"
  15. #define CHT_WC_V1P05A_CTRL 0x6e3b
  16. #define CHT_WC_V1P15_CTRL 0x6e3c
  17. #define CHT_WC_V1P05A_VSEL 0x6e3d
  18. #define CHT_WC_V1P15_VSEL 0x6e3e
  19. #define CHT_WC_V1P8A_CTRL 0x6e56
  20. #define CHT_WC_V1P8SX_CTRL 0x6e57
  21. #define CHT_WC_VDDQ_CTRL 0x6e58
  22. #define CHT_WC_V1P2A_CTRL 0x6e59
  23. #define CHT_WC_V1P2SX_CTRL 0x6e5a
  24. #define CHT_WC_V1P8A_VSEL 0x6e5b
  25. #define CHT_WC_VDDQ_VSEL 0x6e5c
  26. #define CHT_WC_V2P8SX_CTRL 0x6e5d
  27. #define CHT_WC_V3P3A_CTRL 0x6e5e
  28. #define CHT_WC_V3P3SD_CTRL 0x6e5f
  29. #define CHT_WC_VSDIO_CTRL 0x6e67
  30. #define CHT_WC_V3P3A_VSEL 0x6e68
  31. #define CHT_WC_VPROG1A_CTRL 0x6e90
  32. #define CHT_WC_VPROG1B_CTRL 0x6e91
  33. #define CHT_WC_VPROG1F_CTRL 0x6e95
  34. #define CHT_WC_VPROG2D_CTRL 0x6e99
  35. #define CHT_WC_VPROG3A_CTRL 0x6e9a
  36. #define CHT_WC_VPROG3B_CTRL 0x6e9b
  37. #define CHT_WC_VPROG4A_CTRL 0x6e9c
  38. #define CHT_WC_VPROG4B_CTRL 0x6e9d
  39. #define CHT_WC_VPROG4C_CTRL 0x6e9e
  40. #define CHT_WC_VPROG4D_CTRL 0x6e9f
  41. #define CHT_WC_VPROG5A_CTRL 0x6ea0
  42. #define CHT_WC_VPROG5B_CTRL 0x6ea1
  43. #define CHT_WC_VPROG6A_CTRL 0x6ea2
  44. #define CHT_WC_VPROG6B_CTRL 0x6ea3
  45. #define CHT_WC_VPROG1A_VSEL 0x6ec0
  46. #define CHT_WC_VPROG1B_VSEL 0x6ec1
  47. #define CHT_WC_V1P8SX_VSEL 0x6ec2
  48. #define CHT_WC_V1P2SX_VSEL 0x6ec3
  49. #define CHT_WC_V1P2A_VSEL 0x6ec4
  50. #define CHT_WC_VPROG1F_VSEL 0x6ec5
  51. #define CHT_WC_VSDIO_VSEL 0x6ec6
  52. #define CHT_WC_V2P8SX_VSEL 0x6ec7
  53. #define CHT_WC_V3P3SD_VSEL 0x6ec8
  54. #define CHT_WC_VPROG2D_VSEL 0x6ec9
  55. #define CHT_WC_VPROG3A_VSEL 0x6eca
  56. #define CHT_WC_VPROG3B_VSEL 0x6ecb
  57. #define CHT_WC_VPROG4A_VSEL 0x6ecc
  58. #define CHT_WC_VPROG4B_VSEL 0x6ecd
  59. #define CHT_WC_VPROG4C_VSEL 0x6ece
  60. #define CHT_WC_VPROG4D_VSEL 0x6ecf
  61. #define CHT_WC_VPROG5A_VSEL 0x6ed0
  62. #define CHT_WC_VPROG5B_VSEL 0x6ed1
  63. #define CHT_WC_VPROG6A_VSEL 0x6ed2
  64. #define CHT_WC_VPROG6B_VSEL 0x6ed3
  65. /*
  66. * Regulator support is based on the non upstream patch:
  67. * "regulator: whiskey_cove: implements Whiskey Cove pmic VRF support"
  68. * https://github.com/intel-aero/meta-intel-aero/blob/master/recipes-kernel/linux/linux-yocto/0019-regulator-whiskey_cove-implements-WhiskeyCove-pmic-V.patch
  69. */
  70. static struct pmic_table power_table[] = {
  71. {
  72. .address = 0x0,
  73. .reg = CHT_WC_V1P8A_CTRL,
  74. .bit = 0x01,
  75. }, /* V18A */
  76. {
  77. .address = 0x04,
  78. .reg = CHT_WC_V1P8SX_CTRL,
  79. .bit = 0x07,
  80. }, /* V18X */
  81. {
  82. .address = 0x08,
  83. .reg = CHT_WC_VDDQ_CTRL,
  84. .bit = 0x01,
  85. }, /* VDDQ */
  86. {
  87. .address = 0x0c,
  88. .reg = CHT_WC_V1P2A_CTRL,
  89. .bit = 0x07,
  90. }, /* V12A */
  91. {
  92. .address = 0x10,
  93. .reg = CHT_WC_V1P2SX_CTRL,
  94. .bit = 0x07,
  95. }, /* V12X */
  96. {
  97. .address = 0x14,
  98. .reg = CHT_WC_V2P8SX_CTRL,
  99. .bit = 0x07,
  100. }, /* V28X */
  101. {
  102. .address = 0x18,
  103. .reg = CHT_WC_V3P3A_CTRL,
  104. .bit = 0x01,
  105. }, /* V33A */
  106. {
  107. .address = 0x1c,
  108. .reg = CHT_WC_V3P3SD_CTRL,
  109. .bit = 0x07,
  110. }, /* V3SD */
  111. {
  112. .address = 0x20,
  113. .reg = CHT_WC_VSDIO_CTRL,
  114. .bit = 0x07,
  115. }, /* VSD */
  116. /* {
  117. .address = 0x24,
  118. .reg = ??,
  119. .bit = ??,
  120. }, ** VSW2 */
  121. /* {
  122. .address = 0x28,
  123. .reg = ??,
  124. .bit = ??,
  125. }, ** VSW1 */
  126. /* {
  127. .address = 0x2c,
  128. .reg = ??,
  129. .bit = ??,
  130. }, ** VUPY */
  131. /* {
  132. .address = 0x30,
  133. .reg = ??,
  134. .bit = ??,
  135. }, ** VRSO */
  136. {
  137. .address = 0x34,
  138. .reg = CHT_WC_VPROG1A_CTRL,
  139. .bit = 0x07,
  140. }, /* VP1A */
  141. {
  142. .address = 0x38,
  143. .reg = CHT_WC_VPROG1B_CTRL,
  144. .bit = 0x07,
  145. }, /* VP1B */
  146. {
  147. .address = 0x3c,
  148. .reg = CHT_WC_VPROG1F_CTRL,
  149. .bit = 0x07,
  150. }, /* VP1F */
  151. {
  152. .address = 0x40,
  153. .reg = CHT_WC_VPROG2D_CTRL,
  154. .bit = 0x07,
  155. }, /* VP2D */
  156. {
  157. .address = 0x44,
  158. .reg = CHT_WC_VPROG3A_CTRL,
  159. .bit = 0x07,
  160. }, /* VP3A */
  161. {
  162. .address = 0x48,
  163. .reg = CHT_WC_VPROG3B_CTRL,
  164. .bit = 0x07,
  165. }, /* VP3B */
  166. {
  167. .address = 0x4c,
  168. .reg = CHT_WC_VPROG4A_CTRL,
  169. .bit = 0x07,
  170. }, /* VP4A */
  171. {
  172. .address = 0x50,
  173. .reg = CHT_WC_VPROG4B_CTRL,
  174. .bit = 0x07,
  175. }, /* VP4B */
  176. {
  177. .address = 0x54,
  178. .reg = CHT_WC_VPROG4C_CTRL,
  179. .bit = 0x07,
  180. }, /* VP4C */
  181. {
  182. .address = 0x58,
  183. .reg = CHT_WC_VPROG4D_CTRL,
  184. .bit = 0x07,
  185. }, /* VP4D */
  186. {
  187. .address = 0x5c,
  188. .reg = CHT_WC_VPROG5A_CTRL,
  189. .bit = 0x07,
  190. }, /* VP5A */
  191. {
  192. .address = 0x60,
  193. .reg = CHT_WC_VPROG5B_CTRL,
  194. .bit = 0x07,
  195. }, /* VP5B */
  196. {
  197. .address = 0x64,
  198. .reg = CHT_WC_VPROG6A_CTRL,
  199. .bit = 0x07,
  200. }, /* VP6A */
  201. {
  202. .address = 0x68,
  203. .reg = CHT_WC_VPROG6B_CTRL,
  204. .bit = 0x07,
  205. }, /* VP6B */
  206. /* {
  207. .address = 0x6c,
  208. .reg = ??,
  209. .bit = ??,
  210. } ** VP7A */
  211. };
  212. static int intel_cht_wc_pmic_get_power(struct regmap *regmap, int reg,
  213. int bit, u64 *value)
  214. {
  215. int data;
  216. if (regmap_read(regmap, reg, &data))
  217. return -EIO;
  218. *value = (data & bit) ? 1 : 0;
  219. return 0;
  220. }
  221. static int intel_cht_wc_pmic_update_power(struct regmap *regmap, int reg,
  222. int bitmask, bool on)
  223. {
  224. return regmap_update_bits(regmap, reg, bitmask, on ? 1 : 0);
  225. }
  226. static int intel_cht_wc_exec_mipi_pmic_seq_element(struct regmap *regmap,
  227. u16 i2c_client_address,
  228. u32 reg_address,
  229. u32 value, u32 mask)
  230. {
  231. u32 address;
  232. if (i2c_client_address > 0xff || reg_address > 0xff) {
  233. pr_warn("%s warning addresses too big client 0x%x reg 0x%x\n",
  234. __func__, i2c_client_address, reg_address);
  235. return -ERANGE;
  236. }
  237. address = (i2c_client_address << 8) | reg_address;
  238. return regmap_update_bits(regmap, address, mask, value);
  239. }
  240. /*
  241. * The thermal table and ops are empty, we do not support the Thermal opregion
  242. * (DPTF) due to lacking documentation.
  243. */
  244. static const struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
  245. .get_power = intel_cht_wc_pmic_get_power,
  246. .update_power = intel_cht_wc_pmic_update_power,
  247. .exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element,
  248. .lpat_raw_to_temp = acpi_lpat_raw_to_temp,
  249. .power_table = power_table,
  250. .power_table_count = ARRAY_SIZE(power_table),
  251. };
  252. static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev)
  253. {
  254. struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
  255. return intel_pmic_install_opregion_handler(&pdev->dev,
  256. ACPI_HANDLE(pdev->dev.parent),
  257. pmic->regmap,
  258. &intel_cht_wc_pmic_opregion_data);
  259. }
  260. static const struct platform_device_id cht_wc_opregion_id_table[] = {
  261. { .name = "cht_wcove_region" },
  262. {},
  263. };
  264. static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
  265. .probe = intel_cht_wc_pmic_opregion_probe,
  266. .driver = {
  267. .name = "cht_whiskey_cove_pmic",
  268. },
  269. .id_table = cht_wc_opregion_id_table,
  270. };
  271. builtin_platform_driver(intel_cht_wc_pmic_opregion_driver);