extcon-fsa9480.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * extcon-fsa9480.c - Fairchild Semiconductor FSA9480 extcon driver
  4. *
  5. * Copyright (c) 2019 Tomasz Figa <tomasz.figa@gmail.com>
  6. *
  7. * Loosely based on old fsa9480 misc-device driver.
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/types.h>
  12. #include <linux/i2c.h>
  13. #include <linux/slab.h>
  14. #include <linux/bitops.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/err.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/kobject.h>
  19. #include <linux/extcon-provider.h>
  20. #include <linux/irqdomain.h>
  21. #include <linux/regmap.h>
  22. /* FSA9480 I2C registers */
  23. #define FSA9480_REG_DEVID 0x01
  24. #define FSA9480_REG_CTRL 0x02
  25. #define FSA9480_REG_INT1 0x03
  26. #define FSA9480_REG_INT2 0x04
  27. #define FSA9480_REG_INT1_MASK 0x05
  28. #define FSA9480_REG_INT2_MASK 0x06
  29. #define FSA9480_REG_ADC 0x07
  30. #define FSA9480_REG_TIMING1 0x08
  31. #define FSA9480_REG_TIMING2 0x09
  32. #define FSA9480_REG_DEV_T1 0x0a
  33. #define FSA9480_REG_DEV_T2 0x0b
  34. #define FSA9480_REG_BTN1 0x0c
  35. #define FSA9480_REG_BTN2 0x0d
  36. #define FSA9480_REG_CK 0x0e
  37. #define FSA9480_REG_CK_INT1 0x0f
  38. #define FSA9480_REG_CK_INT2 0x10
  39. #define FSA9480_REG_CK_INTMASK1 0x11
  40. #define FSA9480_REG_CK_INTMASK2 0x12
  41. #define FSA9480_REG_MANSW1 0x13
  42. #define FSA9480_REG_MANSW2 0x14
  43. #define FSA9480_REG_END 0x15
  44. /* Control */
  45. #define CON_SWITCH_OPEN (1 << 4)
  46. #define CON_RAW_DATA (1 << 3)
  47. #define CON_MANUAL_SW (1 << 2)
  48. #define CON_WAIT (1 << 1)
  49. #define CON_INT_MASK (1 << 0)
  50. #define CON_MASK (CON_SWITCH_OPEN | CON_RAW_DATA | \
  51. CON_MANUAL_SW | CON_WAIT)
  52. /* Device Type 1 */
  53. #define DEV_USB_OTG 7
  54. #define DEV_DEDICATED_CHG 6
  55. #define DEV_USB_CHG 5
  56. #define DEV_CAR_KIT 4
  57. #define DEV_UART 3
  58. #define DEV_USB 2
  59. #define DEV_AUDIO_2 1
  60. #define DEV_AUDIO_1 0
  61. #define DEV_T1_USB_MASK (DEV_USB_OTG | DEV_USB)
  62. #define DEV_T1_UART_MASK (DEV_UART)
  63. #define DEV_T1_CHARGER_MASK (DEV_DEDICATED_CHG | DEV_USB_CHG)
  64. /* Device Type 2 */
  65. #define DEV_AV 14
  66. #define DEV_TTY 13
  67. #define DEV_PPD 12
  68. #define DEV_JIG_UART_OFF 11
  69. #define DEV_JIG_UART_ON 10
  70. #define DEV_JIG_USB_OFF 9
  71. #define DEV_JIG_USB_ON 8
  72. #define DEV_T2_USB_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON)
  73. #define DEV_T2_UART_MASK (DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
  74. #define DEV_T2_JIG_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \
  75. DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
  76. /*
  77. * Manual Switch
  78. * D- [7:5] / D+ [4:2]
  79. * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO
  80. */
  81. #define SW_VAUDIO ((4 << 5) | (4 << 2))
  82. #define SW_UART ((3 << 5) | (3 << 2))
  83. #define SW_AUDIO ((2 << 5) | (2 << 2))
  84. #define SW_DHOST ((1 << 5) | (1 << 2))
  85. #define SW_AUTO ((0 << 5) | (0 << 2))
  86. /* Interrupt 1 */
  87. #define INT1_MASK (0xff << 0)
  88. #define INT_DETACH (1 << 1)
  89. #define INT_ATTACH (1 << 0)
  90. /* Interrupt 2 mask */
  91. #define INT2_MASK (0x1f << 0)
  92. /* Timing Set 1 */
  93. #define TIMING1_ADC_500MS (0x6 << 0)
  94. struct fsa9480_usbsw {
  95. struct device *dev;
  96. struct regmap *regmap;
  97. struct extcon_dev *edev;
  98. u16 cable;
  99. };
  100. static const unsigned int fsa9480_extcon_cable[] = {
  101. EXTCON_USB_HOST,
  102. EXTCON_USB,
  103. EXTCON_CHG_USB_DCP,
  104. EXTCON_CHG_USB_SDP,
  105. EXTCON_CHG_USB_ACA,
  106. EXTCON_JACK_LINE_OUT,
  107. EXTCON_JACK_VIDEO_OUT,
  108. EXTCON_JIG,
  109. EXTCON_NONE,
  110. };
  111. static const u64 cable_types[] = {
  112. [DEV_USB_OTG] = BIT_ULL(EXTCON_USB_HOST),
  113. [DEV_DEDICATED_CHG] = BIT_ULL(EXTCON_USB) | BIT_ULL(EXTCON_CHG_USB_DCP),
  114. [DEV_USB_CHG] = BIT_ULL(EXTCON_USB) | BIT_ULL(EXTCON_CHG_USB_SDP),
  115. [DEV_CAR_KIT] = BIT_ULL(EXTCON_USB) | BIT_ULL(EXTCON_CHG_USB_SDP)
  116. | BIT_ULL(EXTCON_JACK_LINE_OUT),
  117. [DEV_UART] = BIT_ULL(EXTCON_JIG),
  118. [DEV_USB] = BIT_ULL(EXTCON_USB) | BIT_ULL(EXTCON_CHG_USB_SDP),
  119. [DEV_AUDIO_2] = BIT_ULL(EXTCON_JACK_LINE_OUT),
  120. [DEV_AUDIO_1] = BIT_ULL(EXTCON_JACK_LINE_OUT),
  121. [DEV_AV] = BIT_ULL(EXTCON_JACK_LINE_OUT)
  122. | BIT_ULL(EXTCON_JACK_VIDEO_OUT),
  123. [DEV_TTY] = BIT_ULL(EXTCON_JIG),
  124. [DEV_PPD] = BIT_ULL(EXTCON_JACK_LINE_OUT) | BIT_ULL(EXTCON_CHG_USB_ACA),
  125. [DEV_JIG_UART_OFF] = BIT_ULL(EXTCON_JIG),
  126. [DEV_JIG_UART_ON] = BIT_ULL(EXTCON_JIG),
  127. [DEV_JIG_USB_OFF] = BIT_ULL(EXTCON_USB) | BIT_ULL(EXTCON_JIG),
  128. [DEV_JIG_USB_ON] = BIT_ULL(EXTCON_USB) | BIT_ULL(EXTCON_JIG),
  129. };
  130. /* Define regmap configuration of FSA9480 for I2C communication */
  131. static bool fsa9480_volatile_reg(struct device *dev, unsigned int reg)
  132. {
  133. switch (reg) {
  134. case FSA9480_REG_INT1_MASK:
  135. return true;
  136. default:
  137. break;
  138. }
  139. return false;
  140. }
  141. static const struct regmap_config fsa9480_regmap_config = {
  142. .reg_bits = 8,
  143. .val_bits = 8,
  144. .volatile_reg = fsa9480_volatile_reg,
  145. .max_register = FSA9480_REG_END,
  146. };
  147. static int fsa9480_write_reg(struct fsa9480_usbsw *usbsw, int reg, int value)
  148. {
  149. int ret;
  150. ret = regmap_write(usbsw->regmap, reg, value);
  151. if (ret < 0)
  152. dev_err(usbsw->dev, "%s: err %d\n", __func__, ret);
  153. return ret;
  154. }
  155. static int fsa9480_read_reg(struct fsa9480_usbsw *usbsw, int reg)
  156. {
  157. int ret, val;
  158. ret = regmap_read(usbsw->regmap, reg, &val);
  159. if (ret < 0) {
  160. dev_err(usbsw->dev, "%s: err %d\n", __func__, ret);
  161. return ret;
  162. }
  163. return val;
  164. }
  165. static int fsa9480_read_irq(struct fsa9480_usbsw *usbsw, int *value)
  166. {
  167. u8 regs[2];
  168. int ret;
  169. ret = regmap_bulk_read(usbsw->regmap, FSA9480_REG_INT1, regs, 2);
  170. if (ret < 0)
  171. dev_err(usbsw->dev, "%s: err %d\n", __func__, ret);
  172. *value = regs[1] << 8 | regs[0];
  173. return ret;
  174. }
  175. static void fsa9480_handle_change(struct fsa9480_usbsw *usbsw,
  176. u16 mask, bool attached)
  177. {
  178. while (mask) {
  179. int dev = fls64(mask) - 1;
  180. u64 cables = cable_types[dev];
  181. while (cables) {
  182. int cable = fls64(cables) - 1;
  183. extcon_set_state_sync(usbsw->edev, cable, attached);
  184. cables &= ~BIT_ULL(cable);
  185. }
  186. mask &= ~BIT_ULL(dev);
  187. }
  188. }
  189. static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw)
  190. {
  191. int val1, val2;
  192. u16 val;
  193. val1 = fsa9480_read_reg(usbsw, FSA9480_REG_DEV_T1);
  194. val2 = fsa9480_read_reg(usbsw, FSA9480_REG_DEV_T2);
  195. if (val1 < 0 || val2 < 0) {
  196. dev_err(usbsw->dev, "%s: failed to read registers", __func__);
  197. return;
  198. }
  199. val = val2 << 8 | val1;
  200. dev_info(usbsw->dev, "dev1: 0x%x, dev2: 0x%x\n", val1, val2);
  201. /* handle detached cables first */
  202. fsa9480_handle_change(usbsw, usbsw->cable & ~val, false);
  203. /* then handle attached ones */
  204. fsa9480_handle_change(usbsw, val & ~usbsw->cable, true);
  205. usbsw->cable = val;
  206. }
  207. static irqreturn_t fsa9480_irq_handler(int irq, void *data)
  208. {
  209. struct fsa9480_usbsw *usbsw = data;
  210. int intr = 0;
  211. /* clear interrupt */
  212. fsa9480_read_irq(usbsw, &intr);
  213. if (!intr)
  214. return IRQ_NONE;
  215. /* device detection */
  216. fsa9480_detect_dev(usbsw);
  217. return IRQ_HANDLED;
  218. }
  219. static int fsa9480_probe(struct i2c_client *client,
  220. const struct i2c_device_id *id)
  221. {
  222. struct fsa9480_usbsw *info;
  223. int ret;
  224. if (!client->irq) {
  225. dev_err(&client->dev, "no interrupt provided\n");
  226. return -EINVAL;
  227. }
  228. info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
  229. if (!info)
  230. return -ENOMEM;
  231. info->dev = &client->dev;
  232. i2c_set_clientdata(client, info);
  233. /* External connector */
  234. info->edev = devm_extcon_dev_allocate(info->dev,
  235. fsa9480_extcon_cable);
  236. if (IS_ERR(info->edev)) {
  237. dev_err(info->dev, "failed to allocate memory for extcon\n");
  238. ret = -ENOMEM;
  239. return ret;
  240. }
  241. ret = devm_extcon_dev_register(info->dev, info->edev);
  242. if (ret) {
  243. dev_err(info->dev, "failed to register extcon device\n");
  244. return ret;
  245. }
  246. info->regmap = devm_regmap_init_i2c(client, &fsa9480_regmap_config);
  247. if (IS_ERR(info->regmap)) {
  248. ret = PTR_ERR(info->regmap);
  249. dev_err(info->dev, "failed to allocate register map: %d\n",
  250. ret);
  251. return ret;
  252. }
  253. /* ADC Detect Time: 500ms */
  254. fsa9480_write_reg(info, FSA9480_REG_TIMING1, TIMING1_ADC_500MS);
  255. /* configure automatic switching */
  256. fsa9480_write_reg(info, FSA9480_REG_CTRL, CON_MASK);
  257. /* unmask interrupt (attach/detach only) */
  258. fsa9480_write_reg(info, FSA9480_REG_INT1_MASK,
  259. INT1_MASK & ~(INT_ATTACH | INT_DETACH));
  260. fsa9480_write_reg(info, FSA9480_REG_INT2_MASK, INT2_MASK);
  261. ret = devm_request_threaded_irq(info->dev, client->irq, NULL,
  262. fsa9480_irq_handler,
  263. IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  264. "fsa9480", info);
  265. if (ret) {
  266. dev_err(info->dev, "failed to request IRQ\n");
  267. return ret;
  268. }
  269. device_init_wakeup(info->dev, true);
  270. fsa9480_detect_dev(info);
  271. return 0;
  272. }
  273. static int fsa9480_remove(struct i2c_client *client)
  274. {
  275. return 0;
  276. }
  277. #ifdef CONFIG_PM_SLEEP
  278. static int fsa9480_suspend(struct device *dev)
  279. {
  280. struct i2c_client *client = to_i2c_client(dev);
  281. if (device_may_wakeup(&client->dev) && client->irq)
  282. enable_irq_wake(client->irq);
  283. return 0;
  284. }
  285. static int fsa9480_resume(struct device *dev)
  286. {
  287. struct i2c_client *client = to_i2c_client(dev);
  288. if (device_may_wakeup(&client->dev) && client->irq)
  289. disable_irq_wake(client->irq);
  290. return 0;
  291. }
  292. #endif
  293. static const struct dev_pm_ops fsa9480_pm_ops = {
  294. SET_SYSTEM_SLEEP_PM_OPS(fsa9480_suspend, fsa9480_resume)
  295. };
  296. static const struct i2c_device_id fsa9480_id[] = {
  297. { "fsa9480", 0 },
  298. {}
  299. };
  300. MODULE_DEVICE_TABLE(i2c, fsa9480_id);
  301. static const struct of_device_id fsa9480_of_match[] = {
  302. { .compatible = "fcs,fsa9480", },
  303. { .compatible = "fcs,fsa880", },
  304. { },
  305. };
  306. MODULE_DEVICE_TABLE(of, fsa9480_of_match);
  307. static struct i2c_driver fsa9480_i2c_driver = {
  308. .driver = {
  309. .name = "fsa9480",
  310. .pm = &fsa9480_pm_ops,
  311. .of_match_table = fsa9480_of_match,
  312. },
  313. .probe = fsa9480_probe,
  314. .remove = fsa9480_remove,
  315. .id_table = fsa9480_id,
  316. };
  317. static int __init fsa9480_module_init(void)
  318. {
  319. return i2c_add_driver(&fsa9480_i2c_driver);
  320. }
  321. subsys_initcall(fsa9480_module_init);
  322. static void __exit fsa9480_module_exit(void)
  323. {
  324. i2c_del_driver(&fsa9480_i2c_driver);
  325. }
  326. module_exit(fsa9480_module_exit);
  327. MODULE_DESCRIPTION("Fairchild Semiconductor FSA9480 extcon driver");
  328. MODULE_AUTHOR("Tomasz Figa <tomasz.figa@gmail.com>");
  329. MODULE_LICENSE("GPL");