hid-mcp2200.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * MCP2200 - Microchip USB to GPIO bridge
  4. *
  5. * Copyright (c) 2023, Johannes Roith <johannes@gnu-linux.rocks>
  6. *
  7. * Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/22228A.pdf
  8. * App Note for HID: https://ww1.microchip.com/downloads/en/DeviceDoc/93066A.pdf
  9. */
  10. #include <linux/completion.h>
  11. #include <linux/delay.h>
  12. #include <linux/err.h>
  13. #include <linux/gpio/driver.h>
  14. #include <linux/hid.h>
  15. #include <linux/hidraw.h>
  16. #include <linux/module.h>
  17. #include <linux/mutex.h>
  18. #include "hid-ids.h"
  19. /* Commands codes in a raw output report */
  20. #define SET_CLEAR_OUTPUTS 0x08
  21. #define CONFIGURE 0x10
  22. #define READ_EE 0x20
  23. #define WRITE_EE 0x40
  24. #define READ_ALL 0x80
  25. /* MCP GPIO direction encoding */
  26. enum MCP_IO_DIR {
  27. MCP2200_DIR_OUT = 0x00,
  28. MCP2200_DIR_IN = 0x01,
  29. };
  30. /* Altternative pin assignments */
  31. #define TXLED 2
  32. #define RXLED 3
  33. #define USBCFG 6
  34. #define SSPND 7
  35. #define MCP_NGPIO 8
  36. /* CMD to set or clear a GPIO output */
  37. struct mcp_set_clear_outputs {
  38. u8 cmd;
  39. u8 dummys1[10];
  40. u8 set_bmap;
  41. u8 clear_bmap;
  42. u8 dummys2[3];
  43. } __packed;
  44. /* CMD to configure the IOs */
  45. struct mcp_configure {
  46. u8 cmd;
  47. u8 dummys1[3];
  48. u8 io_bmap;
  49. u8 config_alt_pins;
  50. u8 io_default_val_bmap;
  51. u8 config_alt_options;
  52. u8 baud_h;
  53. u8 baud_l;
  54. u8 dummys2[6];
  55. } __packed;
  56. /* CMD to read all parameters */
  57. struct mcp_read_all {
  58. u8 cmd;
  59. u8 dummys[15];
  60. } __packed;
  61. /* Response to the read all cmd */
  62. struct mcp_read_all_resp {
  63. u8 cmd;
  64. u8 eep_addr;
  65. u8 dummy;
  66. u8 eep_val;
  67. u8 io_bmap;
  68. u8 config_alt_pins;
  69. u8 io_default_val_bmap;
  70. u8 config_alt_options;
  71. u8 baud_h;
  72. u8 baud_l;
  73. u8 io_port_val_bmap;
  74. u8 dummys[5];
  75. } __packed;
  76. struct mcp2200 {
  77. struct hid_device *hdev;
  78. struct mutex lock;
  79. struct completion wait_in_report;
  80. u8 gpio_dir;
  81. u8 gpio_val;
  82. u8 gpio_inval;
  83. u8 baud_h;
  84. u8 baud_l;
  85. u8 config_alt_pins;
  86. u8 gpio_reset_val;
  87. u8 config_alt_options;
  88. int status;
  89. struct gpio_chip gc;
  90. u8 hid_report[16];
  91. };
  92. /* this executes the READ_ALL cmd */
  93. static int mcp_cmd_read_all(struct mcp2200 *mcp)
  94. {
  95. struct mcp_read_all *read_all;
  96. int len, t;
  97. reinit_completion(&mcp->wait_in_report);
  98. mutex_lock(&mcp->lock);
  99. read_all = (struct mcp_read_all *) mcp->hid_report;
  100. read_all->cmd = READ_ALL;
  101. len = hid_hw_output_report(mcp->hdev, (u8 *) read_all,
  102. sizeof(struct mcp_read_all));
  103. mutex_unlock(&mcp->lock);
  104. if (len != sizeof(struct mcp_read_all))
  105. return -EINVAL;
  106. t = wait_for_completion_timeout(&mcp->wait_in_report,
  107. msecs_to_jiffies(4000));
  108. if (!t)
  109. return -ETIMEDOUT;
  110. /* return status, negative value if wrong response was received */
  111. return mcp->status;
  112. }
  113. static void mcp_set_multiple(struct gpio_chip *gc, unsigned long *mask,
  114. unsigned long *bits)
  115. {
  116. struct mcp2200 *mcp = gpiochip_get_data(gc);
  117. u8 value;
  118. int status;
  119. struct mcp_set_clear_outputs *cmd;
  120. mutex_lock(&mcp->lock);
  121. cmd = (struct mcp_set_clear_outputs *) mcp->hid_report;
  122. value = mcp->gpio_val & ~*mask;
  123. value |= (*mask & *bits);
  124. cmd->cmd = SET_CLEAR_OUTPUTS;
  125. cmd->set_bmap = value;
  126. cmd->clear_bmap = ~(value);
  127. status = hid_hw_output_report(mcp->hdev, (u8 *) cmd,
  128. sizeof(struct mcp_set_clear_outputs));
  129. if (status == sizeof(struct mcp_set_clear_outputs))
  130. mcp->gpio_val = value;
  131. mutex_unlock(&mcp->lock);
  132. }
  133. static void mcp_set(struct gpio_chip *gc, unsigned int gpio_nr, int value)
  134. {
  135. unsigned long mask = 1 << gpio_nr;
  136. unsigned long bmap_value = value << gpio_nr;
  137. mcp_set_multiple(gc, &mask, &bmap_value);
  138. }
  139. static int mcp_get_multiple(struct gpio_chip *gc, unsigned long *mask,
  140. unsigned long *bits)
  141. {
  142. u32 val;
  143. struct mcp2200 *mcp = gpiochip_get_data(gc);
  144. int status;
  145. status = mcp_cmd_read_all(mcp);
  146. if (status)
  147. return status;
  148. val = mcp->gpio_inval;
  149. *bits = (val & *mask);
  150. return 0;
  151. }
  152. static int mcp_get(struct gpio_chip *gc, unsigned int gpio_nr)
  153. {
  154. unsigned long mask = 0, bits = 0;
  155. mask = (1 << gpio_nr);
  156. mcp_get_multiple(gc, &mask, &bits);
  157. return bits > 0;
  158. }
  159. static int mcp_get_direction(struct gpio_chip *gc, unsigned int gpio_nr)
  160. {
  161. struct mcp2200 *mcp = gpiochip_get_data(gc);
  162. return (mcp->gpio_dir & (MCP2200_DIR_IN << gpio_nr))
  163. ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
  164. }
  165. static int mcp_set_direction(struct gpio_chip *gc, unsigned int gpio_nr,
  166. enum MCP_IO_DIR io_direction)
  167. {
  168. struct mcp2200 *mcp = gpiochip_get_data(gc);
  169. struct mcp_configure *conf;
  170. int status;
  171. /* after the configure cmd we will need to set the outputs again */
  172. unsigned long mask = ~(mcp->gpio_dir); /* only set outputs */
  173. unsigned long bits = mcp->gpio_val;
  174. /* Offsets of alternative pins in config_alt_pins, 0 is not used */
  175. u8 alt_pin_conf[8] = {SSPND, USBCFG, 0, 0, 0, 0, RXLED, TXLED};
  176. u8 config_alt_pins = mcp->config_alt_pins;
  177. /* Read in the reset baudrate first, we need it later */
  178. status = mcp_cmd_read_all(mcp);
  179. if (status != 0)
  180. return status;
  181. mutex_lock(&mcp->lock);
  182. conf = (struct mcp_configure *) mcp->hid_report;
  183. /* configure will reset the chip! */
  184. conf->cmd = CONFIGURE;
  185. conf->io_bmap = (mcp->gpio_dir & ~(1 << gpio_nr))
  186. | (io_direction << gpio_nr);
  187. /* Don't overwrite the reset parameters */
  188. conf->baud_h = mcp->baud_h;
  189. conf->baud_l = mcp->baud_l;
  190. conf->config_alt_options = mcp->config_alt_options;
  191. conf->io_default_val_bmap = mcp->gpio_reset_val;
  192. /* Adjust alt. func if necessary */
  193. if (alt_pin_conf[gpio_nr])
  194. config_alt_pins &= ~(1 << alt_pin_conf[gpio_nr]);
  195. conf->config_alt_pins = config_alt_pins;
  196. status = hid_hw_output_report(mcp->hdev, (u8 *) conf,
  197. sizeof(struct mcp_set_clear_outputs));
  198. if (status == sizeof(struct mcp_set_clear_outputs)) {
  199. mcp->gpio_dir = conf->io_bmap;
  200. mcp->config_alt_pins = config_alt_pins;
  201. } else {
  202. mutex_unlock(&mcp->lock);
  203. return -EIO;
  204. }
  205. mutex_unlock(&mcp->lock);
  206. /* Configure CMD will clear all IOs -> rewrite them */
  207. mcp_set_multiple(gc, &mask, &bits);
  208. return 0;
  209. }
  210. static int mcp_direction_input(struct gpio_chip *gc, unsigned int gpio_nr)
  211. {
  212. return mcp_set_direction(gc, gpio_nr, MCP2200_DIR_IN);
  213. }
  214. static int mcp_direction_output(struct gpio_chip *gc, unsigned int gpio_nr,
  215. int value)
  216. {
  217. int ret;
  218. unsigned long mask, bmap_value;
  219. mask = 1 << gpio_nr;
  220. bmap_value = value << gpio_nr;
  221. ret = mcp_set_direction(gc, gpio_nr, MCP2200_DIR_OUT);
  222. if (!ret)
  223. mcp_set_multiple(gc, &mask, &bmap_value);
  224. return ret;
  225. }
  226. static const struct gpio_chip template_chip = {
  227. .label = "mcp2200",
  228. .owner = THIS_MODULE,
  229. .get_direction = mcp_get_direction,
  230. .direction_input = mcp_direction_input,
  231. .direction_output = mcp_direction_output,
  232. .set = mcp_set,
  233. .set_multiple = mcp_set_multiple,
  234. .get = mcp_get,
  235. .get_multiple = mcp_get_multiple,
  236. .base = -1,
  237. .ngpio = MCP_NGPIO,
  238. .can_sleep = true,
  239. };
  240. /*
  241. * MCP2200 uses interrupt endpoint for input reports. This function
  242. * is called by HID layer when it receives i/p report from mcp2200,
  243. * which is actually a response to the previously sent command.
  244. */
  245. static int mcp2200_raw_event(struct hid_device *hdev, struct hid_report *report,
  246. u8 *data, int size)
  247. {
  248. struct mcp2200 *mcp = hid_get_drvdata(hdev);
  249. struct mcp_read_all_resp *all_resp;
  250. switch (data[0]) {
  251. case READ_ALL:
  252. all_resp = (struct mcp_read_all_resp *) data;
  253. mcp->status = 0;
  254. mcp->gpio_inval = all_resp->io_port_val_bmap;
  255. mcp->baud_h = all_resp->baud_h;
  256. mcp->baud_l = all_resp->baud_l;
  257. mcp->gpio_reset_val = all_resp->io_default_val_bmap;
  258. mcp->config_alt_pins = all_resp->config_alt_pins;
  259. mcp->config_alt_options = all_resp->config_alt_options;
  260. break;
  261. default:
  262. mcp->status = -EIO;
  263. break;
  264. }
  265. complete(&mcp->wait_in_report);
  266. return 0;
  267. }
  268. static int mcp2200_probe(struct hid_device *hdev, const struct hid_device_id *id)
  269. {
  270. int ret;
  271. struct mcp2200 *mcp;
  272. mcp = devm_kzalloc(&hdev->dev, sizeof(*mcp), GFP_KERNEL);
  273. if (!mcp)
  274. return -ENOMEM;
  275. ret = hid_parse(hdev);
  276. if (ret) {
  277. hid_err(hdev, "can't parse reports\n");
  278. return ret;
  279. }
  280. ret = hid_hw_start(hdev, 0);
  281. if (ret) {
  282. hid_err(hdev, "can't start hardware\n");
  283. return ret;
  284. }
  285. hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n", hdev->version >> 8,
  286. hdev->version & 0xff, hdev->name, hdev->phys);
  287. ret = hid_hw_open(hdev);
  288. if (ret) {
  289. hid_err(hdev, "can't open device\n");
  290. hid_hw_stop(hdev);
  291. return ret;
  292. }
  293. mutex_init(&mcp->lock);
  294. init_completion(&mcp->wait_in_report);
  295. hid_set_drvdata(hdev, mcp);
  296. mcp->hdev = hdev;
  297. mcp->gc = template_chip;
  298. mcp->gc.parent = &hdev->dev;
  299. ret = devm_gpiochip_add_data(&hdev->dev, &mcp->gc, mcp);
  300. if (ret < 0) {
  301. hid_err(hdev, "Unable to register gpiochip\n");
  302. hid_hw_close(hdev);
  303. hid_hw_stop(hdev);
  304. return ret;
  305. }
  306. return 0;
  307. }
  308. static void mcp2200_remove(struct hid_device *hdev)
  309. {
  310. hid_hw_close(hdev);
  311. hid_hw_stop(hdev);
  312. }
  313. static const struct hid_device_id mcp2200_devices[] = {
  314. { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_MCP2200) },
  315. { }
  316. };
  317. MODULE_DEVICE_TABLE(hid, mcp2200_devices);
  318. static struct hid_driver mcp2200_driver = {
  319. .name = "mcp2200",
  320. .id_table = mcp2200_devices,
  321. .probe = mcp2200_probe,
  322. .remove = mcp2200_remove,
  323. .raw_event = mcp2200_raw_event,
  324. };
  325. /* Register with HID core */
  326. module_hid_driver(mcp2200_driver);
  327. MODULE_AUTHOR("Johannes Roith <johannes@gnu-linux.rocks>");
  328. MODULE_DESCRIPTION("MCP2200 Microchip HID USB to GPIO bridge");
  329. MODULE_LICENSE("GPL");