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