1 // SPDX-License-Identifier: GPL-2.0-only
3 * MCP2200 - Microchip USB to GPIO bridge
5 * Copyright (c) 2023, Johannes Roith <johannes@gnu-linux.rocks>
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
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>
20 /* Commands codes in a raw output report */
21 #define SET_CLEAR_OUTPUTS 0x08
22 #define CONFIGURE 0x10
27 /* MCP GPIO direction encoding */
29 MCP2200_DIR_OUT
= 0x00,
30 MCP2200_DIR_IN
= 0x01,
33 /* Altternative pin assignments */
40 /* CMD to set or clear a GPIO output */
41 struct mcp_set_clear_outputs
{
49 /* CMD to configure the IOs */
50 struct mcp_configure
{
55 u8 io_default_val_bmap
;
56 u8 config_alt_options
;
62 /* CMD to read all parameters */
68 /* Response to the read all cmd */
69 struct mcp_read_all_resp
{
76 u8 io_default_val_bmap
;
77 u8 config_alt_options
;
85 struct hid_device
*hdev
;
87 struct completion wait_in_report
;
95 u8 config_alt_options
;
101 /* this executes the READ_ALL cmd */
102 static int mcp_cmd_read_all(struct mcp2200
*mcp
)
104 struct mcp_read_all
*read_all
;
107 reinit_completion(&mcp
->wait_in_report
);
109 mutex_lock(&mcp
->lock
);
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
));
116 mutex_unlock(&mcp
->lock
);
118 if (len
!= sizeof(struct mcp_read_all
))
121 t
= wait_for_completion_timeout(&mcp
->wait_in_report
,
122 msecs_to_jiffies(4000));
126 /* return status, negative value if wrong response was received */
130 static void mcp_set_multiple(struct gpio_chip
*gc
, unsigned long *mask
,
133 struct mcp2200
*mcp
= gpiochip_get_data(gc
);
136 struct mcp_set_clear_outputs
*cmd
;
138 mutex_lock(&mcp
->lock
);
139 cmd
= (struct mcp_set_clear_outputs
*) mcp
->hid_report
;
141 value
= mcp
->gpio_val
& ~*mask
;
142 value
|= (*mask
& *bits
);
144 cmd
->cmd
= SET_CLEAR_OUTPUTS
;
145 cmd
->set_bmap
= value
;
146 cmd
->clear_bmap
= ~(value
);
148 status
= hid_hw_output_report(mcp
->hdev
, (u8
*) cmd
,
149 sizeof(struct mcp_set_clear_outputs
));
151 if (status
== sizeof(struct mcp_set_clear_outputs
))
152 mcp
->gpio_val
= value
;
154 mutex_unlock(&mcp
->lock
);
157 static void mcp_set(struct gpio_chip
*gc
, unsigned int gpio_nr
, int value
)
159 unsigned long mask
= 1 << gpio_nr
;
160 unsigned long bmap_value
= value
<< gpio_nr
;
162 mcp_set_multiple(gc
, &mask
, &bmap_value
);
165 static int mcp_get_multiple(struct gpio_chip
*gc
, unsigned long *mask
,
169 struct mcp2200
*mcp
= gpiochip_get_data(gc
);
172 status
= mcp_cmd_read_all(mcp
);
176 val
= mcp
->gpio_inval
;
177 *bits
= (val
& *mask
);
181 static int mcp_get(struct gpio_chip
*gc
, unsigned int gpio_nr
)
183 unsigned long mask
= 0, bits
= 0;
185 mask
= (1 << gpio_nr
);
186 mcp_get_multiple(gc
, &mask
, &bits
);
190 static int mcp_get_direction(struct gpio_chip
*gc
, unsigned int gpio_nr
)
192 struct mcp2200
*mcp
= gpiochip_get_data(gc
);
194 return (mcp
->gpio_dir
& (MCP2200_DIR_IN
<< gpio_nr
))
195 ? GPIO_LINE_DIRECTION_IN
: GPIO_LINE_DIRECTION_OUT
;
198 static int mcp_set_direction(struct gpio_chip
*gc
, unsigned int gpio_nr
,
199 enum MCP_IO_DIR io_direction
)
201 struct mcp2200
*mcp
= gpiochip_get_data(gc
);
202 struct mcp_configure
*conf
;
204 /* after the configure cmd we will need to set the outputs again */
205 unsigned long mask
= ~(mcp
->gpio_dir
); /* only set outputs */
206 unsigned long bits
= mcp
->gpio_val
;
207 /* Offsets of alternative pins in config_alt_pins, 0 is not used */
208 u8 alt_pin_conf
[8] = {SSPND
, USBCFG
, 0, 0, 0, 0, RXLED
, TXLED
};
209 u8 config_alt_pins
= mcp
->config_alt_pins
;
211 /* Read in the reset baudrate first, we need it later */
212 status
= mcp_cmd_read_all(mcp
);
216 mutex_lock(&mcp
->lock
);
217 conf
= (struct mcp_configure
*) mcp
->hid_report
;
219 /* configure will reset the chip! */
220 conf
->cmd
= CONFIGURE
;
221 conf
->io_bmap
= (mcp
->gpio_dir
& ~(1 << gpio_nr
))
222 | (io_direction
<< gpio_nr
);
223 /* Don't overwrite the reset parameters */
224 conf
->baud_h
= mcp
->baud_h
;
225 conf
->baud_l
= mcp
->baud_l
;
226 conf
->config_alt_options
= mcp
->config_alt_options
;
227 conf
->io_default_val_bmap
= mcp
->gpio_reset_val
;
228 /* Adjust alt. func if necessary */
229 if (alt_pin_conf
[gpio_nr
])
230 config_alt_pins
&= ~(1 << alt_pin_conf
[gpio_nr
]);
231 conf
->config_alt_pins
= config_alt_pins
;
233 status
= hid_hw_output_report(mcp
->hdev
, (u8
*) conf
,
234 sizeof(struct mcp_set_clear_outputs
));
236 if (status
== sizeof(struct mcp_set_clear_outputs
)) {
237 mcp
->gpio_dir
= conf
->io_bmap
;
238 mcp
->config_alt_pins
= config_alt_pins
;
240 mutex_unlock(&mcp
->lock
);
244 mutex_unlock(&mcp
->lock
);
246 /* Configure CMD will clear all IOs -> rewrite them */
247 mcp_set_multiple(gc
, &mask
, &bits
);
251 static int mcp_direction_input(struct gpio_chip
*gc
, unsigned int gpio_nr
)
253 return mcp_set_direction(gc
, gpio_nr
, MCP2200_DIR_IN
);
256 static int mcp_direction_output(struct gpio_chip
*gc
, unsigned int gpio_nr
,
260 unsigned long mask
, bmap_value
;
263 bmap_value
= value
<< gpio_nr
;
265 ret
= mcp_set_direction(gc
, gpio_nr
, MCP2200_DIR_OUT
);
267 mcp_set_multiple(gc
, &mask
, &bmap_value
);
271 static const struct gpio_chip template_chip
= {
273 .owner
= THIS_MODULE
,
274 .get_direction
= mcp_get_direction
,
275 .direction_input
= mcp_direction_input
,
276 .direction_output
= mcp_direction_output
,
278 .set_multiple
= mcp_set_multiple
,
280 .get_multiple
= mcp_get_multiple
,
287 * MCP2200 uses interrupt endpoint for input reports. This function
288 * is called by HID layer when it receives i/p report from mcp2200,
289 * which is actually a response to the previously sent command.
291 static int mcp2200_raw_event(struct hid_device
*hdev
, struct hid_report
*report
,
294 struct mcp2200
*mcp
= hid_get_drvdata(hdev
);
295 struct mcp_read_all_resp
*all_resp
;
299 all_resp
= (struct mcp_read_all_resp
*) data
;
301 mcp
->gpio_inval
= all_resp
->io_port_val_bmap
;
302 mcp
->baud_h
= all_resp
->baud_h
;
303 mcp
->baud_l
= all_resp
->baud_l
;
304 mcp
->gpio_reset_val
= all_resp
->io_default_val_bmap
;
305 mcp
->config_alt_pins
= all_resp
->config_alt_pins
;
306 mcp
->config_alt_options
= all_resp
->config_alt_options
;
313 complete(&mcp
->wait_in_report
);
317 static int mcp2200_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
322 mcp
= devm_kzalloc(&hdev
->dev
, sizeof(*mcp
), GFP_KERNEL
);
326 ret
= hid_parse(hdev
);
328 hid_err(hdev
, "can't parse reports\n");
332 ret
= hid_hw_start(hdev
, 0);
334 hid_err(hdev
, "can't start hardware\n");
338 hid_info(hdev
, "USB HID v%x.%02x Device [%s] on %s\n", hdev
->version
>> 8,
339 hdev
->version
& 0xff, hdev
->name
, hdev
->phys
);
341 ret
= hid_hw_open(hdev
);
343 hid_err(hdev
, "can't open device\n");
348 mutex_init(&mcp
->lock
);
349 init_completion(&mcp
->wait_in_report
);
350 hid_set_drvdata(hdev
, mcp
);
353 mcp
->gc
= template_chip
;
354 mcp
->gc
.parent
= &hdev
->dev
;
356 ret
= devm_gpiochip_add_data(&hdev
->dev
, &mcp
->gc
, mcp
);
358 hid_err(hdev
, "Unable to register gpiochip\n");
367 static void mcp2200_remove(struct hid_device
*hdev
)
373 static const struct hid_device_id mcp2200_devices
[] = {
374 { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP
, USB_DEVICE_ID_MCP2200
) },
377 MODULE_DEVICE_TABLE(hid
, mcp2200_devices
);
379 static struct hid_driver mcp2200_driver
= {
381 .id_table
= mcp2200_devices
,
382 .probe
= mcp2200_probe
,
383 .remove
= mcp2200_remove
,
384 .raw_event
= mcp2200_raw_event
,
387 /* Register with HID core */
388 module_hid_driver(mcp2200_driver
);
390 MODULE_AUTHOR("Johannes Roith <johannes@gnu-linux.rocks>");
391 MODULE_DESCRIPTION("MCP2200 Microchip HID USB to GPIO bridge");
392 MODULE_LICENSE("GPL");