mt6370.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2022 Richtek Technology Corp.
  4. *
  5. * Author: ChiYuan Huang <[email protected]>
  6. */
  7. #include <linux/bits.h>
  8. #include <linux/bitfield.h>
  9. #include <linux/i2c.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/kernel.h>
  12. #include <linux/mfd/core.h>
  13. #include <linux/module.h>
  14. #include <linux/regmap.h>
  15. #include "mt6370.h"
  16. #define MT6370_REG_DEV_INFO 0x100
  17. #define MT6370_REG_CHG_IRQ1 0x1C0
  18. #define MT6370_REG_CHG_MASK1 0x1E0
  19. #define MT6370_REG_MAXADDR 0x1FF
  20. #define MT6370_VENID_MASK GENMASK(7, 4)
  21. #define MT6370_NUM_IRQREGS 16
  22. #define MT6370_USBC_I2CADDR 0x4E
  23. #define MT6370_MAX_ADDRLEN 2
  24. #define MT6370_VENID_RT5081 0x8
  25. #define MT6370_VENID_RT5081A 0xA
  26. #define MT6370_VENID_MT6370 0xE
  27. #define MT6370_VENID_MT6371 0xF
  28. #define MT6370_VENID_MT6372P 0x9
  29. #define MT6370_VENID_MT6372CP 0xB
  30. static const struct regmap_irq mt6370_irqs[] = {
  31. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHGON, 8),
  32. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TREG, 8),
  33. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_AICR, 8),
  34. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_MIVR, 8),
  35. REGMAP_IRQ_REG_LINE(MT6370_IRQ_PWR_RDY, 8),
  36. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FL_CHG_VINOVP, 8),
  37. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSUV, 8),
  38. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSOV, 8),
  39. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VBATOV, 8),
  40. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VINOVPCHG, 8),
  41. REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COLD, 8),
  42. REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COOL, 8),
  43. REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_WARM, 8),
  44. REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_HOT, 8),
  45. REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_STATC, 8),
  46. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_FAULT, 8),
  47. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_STATC, 8),
  48. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TMR, 8),
  49. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_BATABS, 8),
  50. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ADPBAD, 8),
  51. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RVP, 8),
  52. REGMAP_IRQ_REG_LINE(MT6370_IRQ_TSHUTDOWN, 8),
  53. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IINMEAS, 8),
  54. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ICCMEAS, 8),
  55. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET_DONE, 8),
  56. REGMAP_IRQ_REG_LINE(MT6370_IRQ_WDTMR, 8),
  57. REGMAP_IRQ_REG_LINE(MT6370_IRQ_SSFINISH, 8),
  58. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RECHG, 8),
  59. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TERM, 8),
  60. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IEOC, 8),
  61. REGMAP_IRQ_REG_LINE(MT6370_IRQ_ADC_DONE, 8),
  62. REGMAP_IRQ_REG_LINE(MT6370_IRQ_PUMPX_DONE, 8),
  63. REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_BATUV, 8),
  64. REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_MIDOV, 8),
  65. REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_OLP, 8),
  66. REGMAP_IRQ_REG_LINE(MT6370_IRQ_ATTACH, 8),
  67. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DETACH, 8),
  68. REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_STPDONE, 8),
  69. REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_VBUSDET_DONE, 8),
  70. REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_DET, 8),
  71. REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET, 8),
  72. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DCDT, 8),
  73. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_VGOK, 8),
  74. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_WDTMR, 8),
  75. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_UC, 8),
  76. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OC, 8),
  77. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OV, 8),
  78. REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_SWON, 8),
  79. REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP_D, 8),
  80. REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP, 8),
  81. REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP_D, 8),
  82. REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP, 8),
  83. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_STRBPIN, 8),
  84. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TORPIN, 8),
  85. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TX, 8),
  86. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_LVF, 8),
  87. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_SHORT, 8),
  88. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_SHORT, 8),
  89. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_STRB, 8),
  90. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB, 8),
  91. REGMAP_IRQ_REG_LINE(mT6370_IRQ_FLED2_STRB_TO, 8),
  92. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB_TO, 8),
  93. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_TOR, 8),
  94. REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_TOR, 8),
  95. REGMAP_IRQ_REG_LINE(MT6370_IRQ_OTP, 8),
  96. REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_OVP, 8),
  97. REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_UV, 8),
  98. REGMAP_IRQ_REG_LINE(MT6370_IRQ_LDO_OC, 8),
  99. REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OCP, 8),
  100. REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OVP, 8),
  101. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_OCP, 8),
  102. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_OCP, 8),
  103. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_BST_OCP, 8),
  104. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_SCP, 8),
  105. REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_SCP, 8),
  106. };
  107. static const struct regmap_irq_chip mt6370_irq_chip = {
  108. .name = "mt6370-irqs",
  109. .status_base = MT6370_REG_CHG_IRQ1,
  110. .mask_base = MT6370_REG_CHG_MASK1,
  111. .num_regs = MT6370_NUM_IRQREGS,
  112. .irqs = mt6370_irqs,
  113. .num_irqs = ARRAY_SIZE(mt6370_irqs),
  114. };
  115. static const struct resource mt6370_regulator_irqs[] = {
  116. DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_SCP, "db_vpos_scp"),
  117. DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_SCP, "db_vneg_scp"),
  118. DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_BST_OCP, "db_vbst_ocp"),
  119. DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_OCP, "db_vpos_ocp"),
  120. DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_OCP, "db_vneg_ocp"),
  121. DEFINE_RES_IRQ_NAMED(MT6370_IRQ_LDO_OC, "ldo_oc"),
  122. };
  123. static const struct mfd_cell mt6370_devices[] = {
  124. MFD_CELL_OF("mt6370-adc",
  125. NULL, NULL, 0, 0, "mediatek,mt6370-adc"),
  126. MFD_CELL_OF("mt6370-charger",
  127. NULL, NULL, 0, 0, "mediatek,mt6370-charger"),
  128. MFD_CELL_OF("mt6370-flashlight",
  129. NULL, NULL, 0, 0, "mediatek,mt6370-flashlight"),
  130. MFD_CELL_OF("mt6370-indicator",
  131. NULL, NULL, 0, 0, "mediatek,mt6370-indicator"),
  132. MFD_CELL_OF("mt6370-tcpc",
  133. NULL, NULL, 0, 0, "mediatek,mt6370-tcpc"),
  134. MFD_CELL_RES("mt6370-regulator", mt6370_regulator_irqs),
  135. };
  136. static const struct mfd_cell mt6370_exclusive_devices[] = {
  137. MFD_CELL_OF("mt6370-backlight",
  138. NULL, NULL, 0, 0, "mediatek,mt6370-backlight"),
  139. };
  140. static const struct mfd_cell mt6372_exclusive_devices[] = {
  141. MFD_CELL_OF("mt6370-backlight",
  142. NULL, NULL, 0, 0, "mediatek,mt6372-backlight"),
  143. };
  144. static int mt6370_check_vendor_info(struct device *dev, struct regmap *rmap,
  145. int *vid)
  146. {
  147. unsigned int devinfo;
  148. int ret;
  149. ret = regmap_read(rmap, MT6370_REG_DEV_INFO, &devinfo);
  150. if (ret)
  151. return ret;
  152. *vid = FIELD_GET(MT6370_VENID_MASK, devinfo);
  153. switch (*vid) {
  154. case MT6370_VENID_RT5081:
  155. case MT6370_VENID_RT5081A:
  156. case MT6370_VENID_MT6370:
  157. case MT6370_VENID_MT6371:
  158. case MT6370_VENID_MT6372P:
  159. case MT6370_VENID_MT6372CP:
  160. return 0;
  161. default:
  162. dev_err(dev, "Unknown Vendor ID 0x%02x\n", devinfo);
  163. return -ENODEV;
  164. }
  165. }
  166. static int mt6370_regmap_read(void *context, const void *reg_buf,
  167. size_t reg_size, void *val_buf, size_t val_size)
  168. {
  169. struct mt6370_info *info = context;
  170. const u8 *u8_buf = reg_buf;
  171. u8 bank_idx, bank_addr;
  172. int ret;
  173. bank_idx = u8_buf[0];
  174. bank_addr = u8_buf[1];
  175. ret = i2c_smbus_read_i2c_block_data(info->i2c[bank_idx], bank_addr,
  176. val_size, val_buf);
  177. if (ret < 0)
  178. return ret;
  179. if (ret != val_size)
  180. return -EIO;
  181. return 0;
  182. }
  183. static int mt6370_regmap_write(void *context, const void *data, size_t count)
  184. {
  185. struct mt6370_info *info = context;
  186. const u8 *u8_buf = data;
  187. u8 bank_idx, bank_addr;
  188. int len = count - MT6370_MAX_ADDRLEN;
  189. bank_idx = u8_buf[0];
  190. bank_addr = u8_buf[1];
  191. return i2c_smbus_write_i2c_block_data(info->i2c[bank_idx], bank_addr,
  192. len, data + MT6370_MAX_ADDRLEN);
  193. }
  194. static const struct regmap_bus mt6370_regmap_bus = {
  195. .read = mt6370_regmap_read,
  196. .write = mt6370_regmap_write,
  197. };
  198. static const struct regmap_config mt6370_regmap_config = {
  199. .reg_bits = 16,
  200. .val_bits = 8,
  201. .reg_format_endian = REGMAP_ENDIAN_BIG,
  202. .max_register = MT6370_REG_MAXADDR,
  203. };
  204. static int mt6370_probe(struct i2c_client *i2c)
  205. {
  206. struct mt6370_info *info;
  207. struct i2c_client *usbc_i2c;
  208. struct regmap *regmap;
  209. struct device *dev = &i2c->dev;
  210. int ret, vid;
  211. info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
  212. if (!info)
  213. return -ENOMEM;
  214. usbc_i2c = devm_i2c_new_dummy_device(dev, i2c->adapter,
  215. MT6370_USBC_I2CADDR);
  216. if (IS_ERR(usbc_i2c))
  217. return dev_err_probe(dev, PTR_ERR(usbc_i2c),
  218. "Failed to register USBC I2C client\n");
  219. /* Assign I2C client for PMU and TypeC */
  220. info->i2c[MT6370_PMU_I2C] = i2c;
  221. info->i2c[MT6370_USBC_I2C] = usbc_i2c;
  222. regmap = devm_regmap_init(dev, &mt6370_regmap_bus,
  223. info, &mt6370_regmap_config);
  224. if (IS_ERR(regmap))
  225. return dev_err_probe(dev, PTR_ERR(regmap),
  226. "Failed to init regmap\n");
  227. ret = mt6370_check_vendor_info(dev, regmap, &vid);
  228. if (ret)
  229. return dev_err_probe(dev, ret, "Failed to check vendor info\n");
  230. ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq,
  231. IRQF_ONESHOT, -1, &mt6370_irq_chip,
  232. &info->irq_data);
  233. if (ret)
  234. return dev_err_probe(dev, ret, "Failed to add irq chip\n");
  235. switch (vid) {
  236. case MT6370_VENID_MT6372P:
  237. case MT6370_VENID_MT6372CP:
  238. ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
  239. mt6372_exclusive_devices,
  240. ARRAY_SIZE(mt6372_exclusive_devices),
  241. NULL, 0,
  242. regmap_irq_get_domain(info->irq_data));
  243. break;
  244. default:
  245. ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
  246. mt6370_exclusive_devices,
  247. ARRAY_SIZE(mt6370_exclusive_devices),
  248. NULL, 0,
  249. regmap_irq_get_domain(info->irq_data));
  250. break;
  251. }
  252. if (ret)
  253. return dev_err_probe(dev, ret, "Failed to add the exclusive devices\n");
  254. return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
  255. mt6370_devices, ARRAY_SIZE(mt6370_devices),
  256. NULL, 0,
  257. regmap_irq_get_domain(info->irq_data));
  258. }
  259. static const struct of_device_id mt6370_match_table[] = {
  260. { .compatible = "mediatek,mt6370" },
  261. {}
  262. };
  263. MODULE_DEVICE_TABLE(of, mt6370_match_table);
  264. static struct i2c_driver mt6370_driver = {
  265. .driver = {
  266. .name = "mt6370",
  267. .of_match_table = mt6370_match_table,
  268. },
  269. .probe_new = mt6370_probe,
  270. };
  271. module_i2c_driver(mt6370_driver);
  272. MODULE_AUTHOR("ChiYuan Huang <[email protected]>");
  273. MODULE_DESCRIPTION("MediaTek MT6370 SubPMIC Driver");
  274. MODULE_LICENSE("GPL v2");