Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: misc: Add Intel USBIO bridge driver

Add a driver for the Intel USBIO USB IO-expander used by the MIPI cameras
on various new (Meteor Lake and later) Intel laptops.

This is an USB bridge driver which adds auxbus child devices for the GPIO,
I2C and SPI functions of the USBIO chip and which exports IO-functions for
the drivers for the auxbus child devices to communicate with the USBIO
device's firmware.

Co-developed-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Israel Cepeda <israel.a.cepeda.lopez@intel.com>
Link: https://lore.kernel.org/r/20250911181343.77398-2-hansg@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Israel Cepeda and committed by
Greg Kroah-Hartman
121a0f83 21188e8d

+949
+8
MAINTAINERS
··· 12688 12688 F: Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst 12689 12689 F: drivers/platform/x86/intel/uncore-frequency/ 12690 12690 12691 + INTEL USBIO USB I/O EXPANDER DRIVERS 12692 + M: Israel Cepeda <israel.a.cepeda.lopez@intel.com> 12693 + M: Hans de Goede <hansg@kernel.org> 12694 + R: Sakari Ailus <sakari.ailus@linux.intel.com> 12695 + S: Maintained 12696 + F: drivers/usb/misc/usbio.c 12697 + F: include/linux/usb/usbio.h 12698 + 12691 12699 INTEL VENDOR SPECIFIC EXTENDED CAPABILITIES DRIVER 12692 12700 M: David E. Box <david.e.box@linux.intel.com> 12693 12701 S: Supported
+14
drivers/usb/misc/Kconfig
··· 179 179 This driver can also be built as a module. If so, the module 180 180 will be called usb-ljca. 181 181 182 + config USB_USBIO 183 + tristate "Intel USBIO Bridge support" 184 + depends on USB && ACPI 185 + select AUXILIARY_BUS 186 + help 187 + This adds support for Intel USBIO drivers. 188 + This enables the USBIO bridge driver module in charge to talk 189 + to the USB device. Additional drivers such as GPIO_USBIO and 190 + I2C_USBIO must be enabled in order to use the device's full 191 + functionality. 192 + 193 + This driver can also be built as a module. If so, the module 194 + will be called usbio. 195 + 182 196 source "drivers/usb/misc/sisusbvga/Kconfig" 183 197 184 198 config USB_LD
+1
drivers/usb/misc/Makefile
··· 12 12 obj-$(CONFIG_USB_EZUSB_FX2) += ezusb.o 13 13 obj-$(CONFIG_APPLE_MFI_FASTCHARGE) += apple-mfi-fastcharge.o 14 14 obj-$(CONFIG_USB_LJCA) += usb-ljca.o 15 + obj-$(CONFIG_USB_USBIO) += usbio.o 15 16 obj-$(CONFIG_USB_IDMOUSE) += idmouse.o 16 17 obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o 17 18 obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o
+749
drivers/usb/misc/usbio.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel USBIO Bridge driver 4 + * 5 + * Copyright (c) 2025 Intel Corporation. 6 + * Copyright (c) 2025 Red Hat, Inc. 7 + */ 8 + 9 + #include <linux/acpi.h> 10 + #include <linux/auxiliary_bus.h> 11 + #include <linux/byteorder/generic.h> 12 + #include <linux/cleanup.h> 13 + #include <linux/completion.h> 14 + #include <linux/dev_printk.h> 15 + #include <linux/device.h> 16 + #include <linux/lockdep.h> 17 + #include <linux/mutex.h> 18 + #include <linux/string.h> 19 + #include <linux/types.h> 20 + #include <linux/usb.h> 21 + #include <linux/usb/usbio.h> 22 + 23 + /************************************* 24 + * USBIO Bridge Protocol Definitions * 25 + *************************************/ 26 + 27 + /* USBIO Control Commands */ 28 + #define USBIO_CTRLCMD_PROTVER 0 29 + #define USBIO_CTRLCMD_FWVER 1 30 + #define USBIO_CTRLCMD_HS 2 31 + #define USBIO_CTRLCMD_ENUMGPIO 16 32 + #define USBIO_CTRLCMD_ENUMI2C 17 33 + 34 + /* USBIO Packet Flags */ 35 + #define USBIO_PKTFLAG_ACK BIT(0) 36 + #define USBIO_PKTFLAG_RSP BIT(1) 37 + #define USBIO_PKTFLAG_CMP BIT(2) 38 + #define USBIO_PKTFLAG_ERR BIT(3) 39 + 40 + #define USBIO_PKTFLAGS_REQRESP (USBIO_PKTFLAG_CMP | USBIO_PKTFLAG_ACK) 41 + 42 + #define USBIO_CTRLXFER_TIMEOUT 0 43 + #define USBIO_BULKXFER_TIMEOUT 100 44 + 45 + struct usbio_protver { 46 + u8 ver; 47 + } __packed; 48 + 49 + struct usbio_fwver { 50 + u8 major; 51 + u8 minor; 52 + __le16 patch; 53 + __le16 build; 54 + } __packed; 55 + 56 + /*********************************** 57 + * USBIO Bridge Device Definitions * 58 + ***********************************/ 59 + 60 + /** 61 + * struct usbio_device - the usb device exposing IOs 62 + * 63 + * @dev: the device in the usb interface 64 + * @udev: the detected usb device 65 + * @intf: the usb interface 66 + * @quirks: quirks 67 + * @ctrl_mutex: protects ctrl_buf 68 + * @ctrl_pipe: the control transfer pipe 69 + * @ctrlbuf_len: the size of the control transfer pipe 70 + * @ctrlbuf: the buffer used for control transfers 71 + * @bulk_mutex: protects tx_buf, rx_buf and split bulk-transfers getting interrupted 72 + * @tx_pipe: the bulk out pipe 73 + * @txbuf_len: the size of the bulk out pipe 74 + * @txbuf: the buffer used for bulk out transfers 75 + * @rx_pipe: the bulk in pipe 76 + * @rxbuf_len: the size of the bulk in pipe 77 + * @rxdat_len: the data length at rx buffer 78 + * @rxbuf: the buffer used for bulk in transfers 79 + * @urb: the urb to read bulk pipe 80 + * @done: completion object as request is done 81 + * @cli_list: device's client list 82 + * @nr_gpio_banks: Number of GPIO banks 83 + * @gpios: GPIO bank descriptors 84 + * @nr_gpio_banks: Number of I2C busses 85 + * @gpios: I2C bank descriptors 86 + */ 87 + struct usbio_device { 88 + struct device *dev; 89 + struct usb_device *udev; 90 + struct usb_interface *intf; 91 + unsigned long quirks; 92 + 93 + struct mutex ctrl_mutex; 94 + unsigned int ctrl_pipe; 95 + u16 ctrlbuf_len; 96 + void *ctrlbuf; 97 + 98 + struct mutex bulk_mutex; 99 + unsigned int tx_pipe; 100 + u16 txbuf_len; 101 + void *txbuf; 102 + 103 + unsigned int rx_pipe; 104 + u16 rxbuf_len; 105 + u16 rxdat_len; 106 + void *rxbuf; 107 + struct urb *urb; 108 + 109 + struct completion done; 110 + 111 + struct list_head cli_list; 112 + 113 + unsigned int nr_gpio_banks; 114 + struct usbio_gpio_bank_desc gpios[USBIO_MAX_GPIOBANKS]; 115 + 116 + unsigned int nr_i2c_buses; 117 + struct usbio_i2c_bus_desc i2cs[USBIO_MAX_I2CBUSES]; 118 + }; 119 + 120 + /** 121 + * struct usbio_client - represents a usbio client 122 + * 123 + * @auxdev: auxiliary device object 124 + * @mutex: protects @bridge 125 + * @bridge: usbio bridge who service the client 126 + * @link: usbio bridge clients list member 127 + */ 128 + struct usbio_client { 129 + struct auxiliary_device auxdev; 130 + struct mutex mutex; 131 + struct usbio_device *bridge; 132 + struct list_head link; 133 + }; 134 + 135 + #define adev_to_client(adev) container_of_const(adev, struct usbio_client, auxdev) 136 + 137 + static int usbio_ctrl_msg(struct usbio_device *usbio, u8 type, u8 cmd, 138 + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len) 139 + { 140 + u8 request = USB_TYPE_VENDOR | USB_RECIP_DEVICE; 141 + struct usbio_ctrl_packet *cpkt; 142 + unsigned int pipe; 143 + u16 cpkt_len; 144 + int ret; 145 + 146 + lockdep_assert_held(&usbio->ctrl_mutex); 147 + 148 + if ((obuf_len > (usbio->ctrlbuf_len - sizeof(*cpkt))) || 149 + (ibuf_len > (usbio->ctrlbuf_len - sizeof(*cpkt)))) 150 + return -EMSGSIZE; 151 + 152 + /* Prepare Control Packet Header */ 153 + cpkt = usbio->ctrlbuf; 154 + cpkt->header.type = type; 155 + cpkt->header.cmd = cmd; 156 + if (type == USBIO_PKTTYPE_CTRL || ibuf_len) 157 + cpkt->header.flags = USBIO_PKTFLAGS_REQRESP; 158 + else 159 + cpkt->header.flags = USBIO_PKTFLAG_CMP; 160 + cpkt->len = obuf_len; 161 + 162 + /* Copy the data */ 163 + memcpy(cpkt->data, obuf, obuf_len); 164 + 165 + pipe = usb_sndctrlpipe(usbio->udev, usbio->ctrl_pipe); 166 + cpkt_len = sizeof(*cpkt) + obuf_len; 167 + ret = usb_control_msg(usbio->udev, pipe, 0, request | USB_DIR_OUT, 0, 0, 168 + cpkt, cpkt_len, USBIO_CTRLXFER_TIMEOUT); 169 + dev_dbg(usbio->dev, "control out %d hdr %*phN data %*phN\n", ret, 170 + (int)sizeof(*cpkt), cpkt, (int)cpkt->len, cpkt->data); 171 + 172 + if (ret != cpkt_len) { 173 + dev_err(usbio->dev, "USB control out failed: %d\n", ret); 174 + return (ret < 0) ? ret : -EPROTO; 175 + } 176 + 177 + if (!(cpkt->header.flags & USBIO_PKTFLAG_ACK)) 178 + return 0; 179 + 180 + pipe = usb_rcvctrlpipe(usbio->udev, usbio->ctrl_pipe); 181 + cpkt_len = sizeof(*cpkt) + ibuf_len; 182 + ret = usb_control_msg(usbio->udev, pipe, 0, request | USB_DIR_IN, 0, 0, 183 + cpkt, cpkt_len, USBIO_CTRLXFER_TIMEOUT); 184 + dev_dbg(usbio->dev, "control in %d hdr %*phN data %*phN\n", ret, 185 + (int)sizeof(*cpkt), cpkt, (int)cpkt->len, cpkt->data); 186 + 187 + if (ret < sizeof(*cpkt)) { 188 + dev_err(usbio->dev, "USB control in failed: %d\n", ret); 189 + return (ret < 0) ? ret : -EPROTO; 190 + } 191 + 192 + if (cpkt->header.type != type || cpkt->header.cmd != cmd || 193 + !(cpkt->header.flags & USBIO_PKTFLAG_RSP)) { 194 + dev_err(usbio->dev, "Unexpected reply type: %u, cmd: %u, flags: %u\n", 195 + cpkt->header.type, cpkt->header.cmd, cpkt->header.flags); 196 + return -EPROTO; 197 + } 198 + 199 + if (cpkt->header.flags & USBIO_PKTFLAG_ERR) 200 + return -EREMOTEIO; 201 + 202 + if (ibuf_len < cpkt->len) 203 + return -ENOSPC; 204 + 205 + memcpy(ibuf, cpkt->data, cpkt->len); 206 + 207 + return cpkt->len; 208 + } 209 + 210 + int usbio_control_msg(struct auxiliary_device *adev, u8 type, u8 cmd, 211 + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len) 212 + { 213 + struct usbio_client *client = adev_to_client(adev); 214 + struct usbio_device *usbio; 215 + int ret; 216 + 217 + guard(mutex)(&client->mutex); 218 + 219 + usbio = client->bridge; 220 + if (!usbio) 221 + return -ENODEV; /* Disconnected */ 222 + 223 + ret = usb_autopm_get_interface(usbio->intf); 224 + if (ret) 225 + return ret; 226 + 227 + mutex_lock(&usbio->ctrl_mutex); 228 + 229 + ret = usbio_ctrl_msg(client->bridge, type, cmd, obuf, obuf_len, ibuf, ibuf_len); 230 + 231 + mutex_unlock(&usbio->ctrl_mutex); 232 + usb_autopm_put_interface(usbio->intf); 233 + 234 + return ret; 235 + } 236 + EXPORT_SYMBOL_NS_GPL(usbio_control_msg, "USBIO"); 237 + 238 + static void usbio_bulk_recv(struct urb *urb) 239 + { 240 + struct usbio_bulk_packet *bpkt = urb->transfer_buffer; 241 + struct usbio_device *usbio = urb->context; 242 + 243 + if (!urb->status) { 244 + if (bpkt->header.flags & USBIO_PKTFLAG_RSP) { 245 + usbio->rxdat_len = urb->actual_length; 246 + complete(&usbio->done); 247 + } 248 + } else if (urb->status != -ENOENT) { 249 + dev_err(usbio->dev, "Bulk in error %d\n", urb->status); 250 + } 251 + 252 + usb_submit_urb(usbio->urb, GFP_ATOMIC); 253 + } 254 + 255 + int usbio_bulk_msg(struct auxiliary_device *adev, u8 type, u8 cmd, bool last, 256 + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len) 257 + { 258 + struct usbio_client *client = adev_to_client(adev); 259 + struct usbio_device *usbio = client->bridge; 260 + struct usbio_bulk_packet *bpkt; 261 + int ret, act = 0; 262 + u16 bpkt_len; 263 + 264 + lockdep_assert_held(&client->mutex); 265 + lockdep_assert_held(&usbio->bulk_mutex); 266 + 267 + if ((obuf_len > (usbio->txbuf_len - sizeof(*bpkt))) || 268 + (ibuf_len > (usbio->txbuf_len - sizeof(*bpkt)))) 269 + return -EMSGSIZE; 270 + 271 + if (ibuf_len) 272 + reinit_completion(&usbio->done); 273 + 274 + /* If no data to send, skip to read */ 275 + if (!obuf_len) 276 + goto read; 277 + 278 + /* Prepare Bulk Packet Header */ 279 + bpkt = usbio->txbuf; 280 + bpkt->header.type = type; 281 + bpkt->header.cmd = cmd; 282 + if (!last) 283 + bpkt->header.flags = 0; 284 + else if (ibuf_len) 285 + bpkt->header.flags = USBIO_PKTFLAGS_REQRESP; 286 + else 287 + bpkt->header.flags = USBIO_PKTFLAG_CMP; 288 + bpkt->len = cpu_to_le16(obuf_len); 289 + 290 + /* Copy the data */ 291 + memcpy(bpkt->data, obuf, obuf_len); 292 + 293 + bpkt_len = sizeof(*bpkt) + obuf_len; 294 + ret = usb_bulk_msg(usbio->udev, usbio->tx_pipe, bpkt, bpkt_len, &act, 295 + USBIO_BULKXFER_TIMEOUT); 296 + dev_dbg(usbio->dev, "bulk out %d hdr %*phN data %*phN\n", act, 297 + (int)sizeof(*bpkt), bpkt, obuf_len, bpkt->data); 298 + 299 + if (ret || act != bpkt_len) { 300 + dev_err(usbio->dev, "Bulk out failed: %d\n", ret); 301 + return ret ?: -EPROTO; 302 + } 303 + 304 + if (!(bpkt->header.flags & USBIO_PKTFLAG_ACK)) 305 + return obuf_len; 306 + 307 + read: 308 + ret = wait_for_completion_timeout(&usbio->done, USBIO_BULKXFER_TIMEOUT); 309 + if (ret <= 0) { 310 + dev_err(usbio->dev, "Bulk in wait failed: %d\n", ret); 311 + return ret ?: -ETIMEDOUT; 312 + } 313 + 314 + act = usbio->rxdat_len; 315 + bpkt = usbio->rxbuf; 316 + bpkt_len = le16_to_cpu(bpkt->len); 317 + dev_dbg(usbio->dev, "bulk in %d hdr %*phN data %*phN\n", act, 318 + (int)sizeof(*bpkt), bpkt, bpkt_len, bpkt->data); 319 + 320 + /* 321 + * Unsupported bulk commands get only an usbio_packet_header with 322 + * the error flag set as reply. Return -EPIPE for this case. 323 + */ 324 + if (act == sizeof(struct usbio_packet_header) && 325 + (bpkt->header.flags & USBIO_PKTFLAG_ERR)) 326 + return -EPIPE; 327 + 328 + if (act < sizeof(*bpkt)) { 329 + dev_err(usbio->dev, "Bulk in short read: %d\n", act); 330 + return -EPROTO; 331 + } 332 + 333 + if (bpkt->header.type != type || bpkt->header.cmd != cmd || 334 + !(bpkt->header.flags & USBIO_PKTFLAG_RSP)) { 335 + dev_err(usbio->dev, 336 + "Unexpected bulk in type 0x%02x cmd 0x%02x flags 0x%02x\n", 337 + bpkt->header.type, bpkt->header.cmd, bpkt->header.flags); 338 + return -EPROTO; 339 + } 340 + 341 + if (bpkt->header.flags & USBIO_PKTFLAG_ERR) 342 + return -EREMOTEIO; 343 + 344 + if (ibuf_len < bpkt_len) 345 + return -ENOSPC; 346 + 347 + memcpy(ibuf, bpkt->data, bpkt_len); 348 + 349 + return bpkt_len; 350 + } 351 + EXPORT_SYMBOL_NS_GPL(usbio_bulk_msg, "USBIO"); 352 + 353 + int usbio_acquire(struct auxiliary_device *adev) 354 + { 355 + struct usbio_client *client = adev_to_client(adev); 356 + struct usbio_device *usbio; 357 + int ret; 358 + 359 + mutex_lock(&client->mutex); 360 + 361 + usbio = client->bridge; 362 + if (!usbio) { 363 + ret = -ENODEV; /* Disconnected */ 364 + goto err_unlock; 365 + } 366 + 367 + ret = usb_autopm_get_interface(usbio->intf); 368 + if (ret) 369 + goto err_unlock; 370 + 371 + mutex_lock(&usbio->bulk_mutex); 372 + 373 + /* Leave client locked until release to avoid abba deadlock issues */ 374 + return 0; 375 + 376 + err_unlock: 377 + mutex_unlock(&client->mutex); 378 + 379 + return ret; 380 + } 381 + EXPORT_SYMBOL_NS_GPL(usbio_acquire, "USBIO"); 382 + 383 + void usbio_release(struct auxiliary_device *adev) 384 + { 385 + struct usbio_client *client = adev_to_client(adev); 386 + struct usbio_device *usbio = client->bridge; 387 + 388 + lockdep_assert_held(&client->mutex); 389 + 390 + mutex_unlock(&usbio->bulk_mutex); 391 + usb_autopm_put_interface(usbio->intf); 392 + mutex_unlock(&client->mutex); 393 + } 394 + EXPORT_SYMBOL_NS_GPL(usbio_release, "USBIO"); 395 + 396 + void usbio_get_txrxbuf_len(struct auxiliary_device *adev, u16 *txbuf_len, u16 *rxbuf_len) 397 + { 398 + struct usbio_client *client = adev_to_client(adev); 399 + struct usbio_device *usbio; 400 + 401 + guard(mutex)(&client->mutex); 402 + 403 + usbio = client->bridge; 404 + if (!usbio) 405 + return; /* Disconnected */ 406 + 407 + *txbuf_len = usbio->txbuf_len; 408 + *rxbuf_len = usbio->rxbuf_len; 409 + } 410 + EXPORT_SYMBOL_NS_GPL(usbio_get_txrxbuf_len, "USBIO"); 411 + 412 + unsigned long usbio_get_quirks(struct auxiliary_device *adev) 413 + { 414 + struct usbio_client *client = adev_to_client(adev); 415 + struct usbio_device *usbio; 416 + 417 + guard(mutex)(&client->mutex); 418 + 419 + usbio = client->bridge; 420 + if (!usbio) 421 + return 0; /* Disconnected */ 422 + 423 + return usbio->quirks; 424 + } 425 + EXPORT_SYMBOL_NS_GPL(usbio_get_quirks, "USBIO"); 426 + 427 + static void usbio_auxdev_release(struct device *dev) 428 + { 429 + struct auxiliary_device *adev = to_auxiliary_dev(dev); 430 + struct usbio_client *client = adev_to_client(adev); 431 + 432 + mutex_destroy(&client->mutex); 433 + kfree(client); 434 + } 435 + 436 + static int usbio_add_client(struct usbio_device *usbio, char *name, u8 id, void *data) 437 + { 438 + struct usbio_client *client; 439 + struct auxiliary_device *adev; 440 + int ret; 441 + 442 + client = kzalloc(sizeof(*client), GFP_KERNEL); 443 + if (!client) 444 + return -ENOMEM; 445 + 446 + mutex_init(&client->mutex); 447 + client->bridge = usbio; 448 + adev = &client->auxdev; 449 + adev->name = name; 450 + adev->id = id; 451 + 452 + adev->dev.parent = usbio->dev; 453 + adev->dev.platform_data = data; 454 + adev->dev.release = usbio_auxdev_release; 455 + 456 + ret = auxiliary_device_init(adev); 457 + if (ret) { 458 + usbio_auxdev_release(&adev->dev); 459 + return ret; 460 + } 461 + 462 + ret = auxiliary_device_add(adev); 463 + if (ret) { 464 + auxiliary_device_uninit(adev); 465 + return ret; 466 + } 467 + 468 + list_add_tail(&client->link, &usbio->cli_list); 469 + 470 + return 0; 471 + } 472 + 473 + static int usbio_enum_gpios(struct usbio_device *usbio) 474 + { 475 + struct usbio_gpio_bank_desc *gpio = usbio->gpios; 476 + 477 + dev_dbg(usbio->dev, "GPIO Banks: %d\n", usbio->nr_gpio_banks); 478 + 479 + for (unsigned int i = 0; i < usbio->nr_gpio_banks; i++) 480 + dev_dbg(usbio->dev, "\tBank%d[%d] map: %#08x\n", 481 + gpio[i].id, gpio[i].pins, gpio[i].bmap); 482 + 483 + usbio_add_client(usbio, USBIO_GPIO_CLIENT, 0, gpio); 484 + 485 + return 0; 486 + } 487 + 488 + static int usbio_enum_i2cs(struct usbio_device *usbio) 489 + { 490 + struct usbio_i2c_bus_desc *i2c = usbio->i2cs; 491 + 492 + dev_dbg(usbio->dev, "I2C Busses: %d\n", usbio->nr_i2c_buses); 493 + 494 + for (unsigned int i = 0; i < usbio->nr_i2c_buses; i++) { 495 + dev_dbg(usbio->dev, "\tBus%d caps: %#02x\n", i2c[i].id, i2c[i].caps); 496 + usbio_add_client(usbio, USBIO_I2C_CLIENT, i, &i2c[i]); 497 + } 498 + 499 + return 0; 500 + } 501 + 502 + static int usbio_suspend(struct usb_interface *intf, pm_message_t msg) 503 + { 504 + struct usbio_device *usbio = usb_get_intfdata(intf); 505 + 506 + usb_kill_urb(usbio->urb); 507 + 508 + return 0; 509 + } 510 + 511 + static int usbio_resume(struct usb_interface *intf) 512 + { 513 + struct usbio_device *usbio = usb_get_intfdata(intf); 514 + 515 + return usb_submit_urb(usbio->urb, GFP_KERNEL); 516 + } 517 + 518 + static void usbio_disconnect(struct usb_interface *intf) 519 + { 520 + struct usbio_device *usbio = usb_get_intfdata(intf); 521 + struct usbio_client *client; 522 + 523 + /* Wakeup any clients waiting for a reply */ 524 + usbio->rxdat_len = 0; 525 + complete(&usbio->done); 526 + 527 + /* Let clients know the bridge is gone */ 528 + list_for_each_entry(client, &usbio->cli_list, link) { 529 + mutex_lock(&client->mutex); 530 + client->bridge = NULL; 531 + mutex_unlock(&client->mutex); 532 + } 533 + 534 + /* From here on clients will no longer touch struct usbio_device */ 535 + usb_kill_urb(usbio->urb); 536 + usb_free_urb(usbio->urb); 537 + 538 + list_for_each_entry_reverse(client, &usbio->cli_list, link) { 539 + auxiliary_device_delete(&client->auxdev); 540 + auxiliary_device_uninit(&client->auxdev); 541 + } 542 + } 543 + 544 + static int usbio_probe(struct usb_interface *intf, const struct usb_device_id *id) 545 + { 546 + struct usb_device *udev = interface_to_usbdev(intf); 547 + struct usb_endpoint_descriptor *ep_in, *ep_out; 548 + struct device *dev = &intf->dev; 549 + struct usbio_protver protver; 550 + struct usbio_device *usbio; 551 + struct usbio_fwver fwver; 552 + int ret; 553 + 554 + usbio = devm_kzalloc(dev, sizeof(*usbio), GFP_KERNEL); 555 + if (!usbio) 556 + return -ENOMEM; 557 + 558 + ret = devm_mutex_init(dev, &usbio->ctrl_mutex); 559 + if (ret) 560 + return ret; 561 + 562 + ret = devm_mutex_init(dev, &usbio->bulk_mutex); 563 + if (ret) 564 + return ret; 565 + 566 + usbio->dev = dev; 567 + usbio->udev = udev; 568 + usbio->intf = intf; 569 + usbio->quirks = id ? id->driver_info : 0; 570 + init_completion(&usbio->done); 571 + INIT_LIST_HEAD(&usbio->cli_list); 572 + usb_set_intfdata(intf, usbio); 573 + 574 + usbio->ctrl_pipe = usb_endpoint_num(&udev->ep0.desc); 575 + usbio->ctrlbuf_len = usb_maxpacket(udev, usbio->ctrl_pipe); 576 + usbio->ctrlbuf = devm_kzalloc(dev, usbio->ctrlbuf_len, GFP_KERNEL); 577 + if (!usbio->ctrlbuf) 578 + return -ENOMEM; 579 + 580 + /* Find the first bulk-in and bulk-out endpoints */ 581 + ret = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out, 582 + NULL, NULL); 583 + if (ret) { 584 + dev_err(dev, "Cannot find bulk endpoints: %d\n", ret); 585 + return ret; 586 + } 587 + 588 + usbio->tx_pipe = usb_sndbulkpipe(udev, usb_endpoint_num(ep_out)); 589 + 590 + if (usbio->quirks & USBIO_QUIRK_BULK_MAXP_63) 591 + usbio->txbuf_len = 63; 592 + else 593 + usbio->txbuf_len = usb_endpoint_maxp(ep_out); 594 + 595 + usbio->txbuf = devm_kzalloc(dev, usbio->txbuf_len, GFP_KERNEL); 596 + if (!usbio->txbuf) 597 + return -ENOMEM; 598 + 599 + usbio->rx_pipe = usb_rcvbulkpipe(udev, usb_endpoint_num(ep_in)); 600 + 601 + if (usbio->quirks & USBIO_QUIRK_BULK_MAXP_63) 602 + usbio->rxbuf_len = 63; 603 + else 604 + usbio->rxbuf_len = usb_endpoint_maxp(ep_in); 605 + 606 + usbio->rxbuf = devm_kzalloc(dev, usbio->rxbuf_len, GFP_KERNEL); 607 + if (!usbio->rxbuf) 608 + return -ENOMEM; 609 + 610 + usbio->urb = usb_alloc_urb(0, GFP_KERNEL); 611 + if (!usbio->urb) 612 + return -ENOMEM; 613 + 614 + usb_fill_bulk_urb(usbio->urb, udev, usbio->rx_pipe, usbio->rxbuf, 615 + usbio->rxbuf_len, usbio_bulk_recv, usbio); 616 + ret = usb_submit_urb(usbio->urb, GFP_KERNEL); 617 + if (ret) 618 + return dev_err_probe(dev, ret, "Submitting usb urb\n"); 619 + 620 + mutex_lock(&usbio->ctrl_mutex); 621 + 622 + ret = usbio_ctrl_msg(usbio, USBIO_PKTTYPE_CTRL, USBIO_CTRLCMD_HS, NULL, 0, NULL, 0); 623 + if (ret < 0) 624 + goto err_unlock; 625 + 626 + ret = usbio_ctrl_msg(usbio, USBIO_PKTTYPE_CTRL, USBIO_CTRLCMD_PROTVER, NULL, 0, 627 + &protver, sizeof(protver)); 628 + if (ret < 0) 629 + goto err_unlock; 630 + 631 + ret = usbio_ctrl_msg(usbio, USBIO_PKTTYPE_CTRL, USBIO_CTRLCMD_FWVER, NULL, 0, 632 + &fwver, sizeof(fwver)); 633 + if (ret < 0) 634 + goto err_unlock; 635 + 636 + ret = usbio_ctrl_msg(usbio, USBIO_PKTTYPE_CTRL, USBIO_CTRLCMD_ENUMGPIO, NULL, 0, 637 + usbio->gpios, sizeof(usbio->gpios)); 638 + if (ret < 0 || ret % sizeof(struct usbio_gpio_bank_desc)) { 639 + ret = (ret < 0) ? ret : -EPROTO; 640 + goto err_unlock; 641 + } 642 + usbio->nr_gpio_banks = ret / sizeof(struct usbio_gpio_bank_desc); 643 + 644 + ret = usbio_ctrl_msg(usbio, USBIO_PKTTYPE_CTRL, USBIO_CTRLCMD_ENUMI2C, NULL, 0, 645 + usbio->i2cs, sizeof(usbio->i2cs)); 646 + if (ret < 0 || ret % sizeof(struct usbio_i2c_bus_desc)) { 647 + ret = (ret < 0) ? ret : -EPROTO; 648 + goto err_unlock; 649 + } 650 + usbio->nr_i2c_buses = ret / sizeof(struct usbio_i2c_bus_desc); 651 + 652 + mutex_unlock(&usbio->ctrl_mutex); 653 + 654 + dev_dbg(dev, "ProtVer(BCD): %02x FwVer: %d.%d.%d.%d\n", 655 + protver.ver, fwver.major, fwver.minor, 656 + le16_to_cpu(fwver.patch), le16_to_cpu(fwver.build)); 657 + 658 + usbio_enum_gpios(usbio); 659 + usbio_enum_i2cs(usbio); 660 + 661 + return 0; 662 + 663 + err_unlock: 664 + mutex_unlock(&usbio->ctrl_mutex); 665 + usb_kill_urb(usbio->urb); 666 + usb_free_urb(usbio->urb); 667 + 668 + return ret; 669 + } 670 + 671 + static const struct usb_device_id usbio_table[] = { 672 + { USB_DEVICE(0x2ac1, 0x20c1), /* Lattice NX40 */ 673 + .driver_info = USBIO_QUIRK_I2C_MAX_RW_LEN_52 }, 674 + { USB_DEVICE(0x2ac1, 0x20c9), /* Lattice NX33 */ 675 + .driver_info = USBIO_QUIRK_I2C_NO_INIT_ACK | USBIO_QUIRK_I2C_MAX_RW_LEN_52 | 676 + USBIO_QUIRK_I2C_ALLOW_400KHZ }, 677 + { USB_DEVICE(0x2ac1, 0x20cb) }, /* Lattice NX33U */ 678 + { USB_DEVICE(0x06cb, 0x0701), /* Synaptics Sabre */ 679 + .driver_info = USBIO_QUIRK_BULK_MAXP_63 | USBIO_QUIRK_I2C_USE_CHUNK_LEN }, 680 + { } 681 + }; 682 + MODULE_DEVICE_TABLE(usb, usbio_table); 683 + 684 + static struct usb_driver usbio_driver = { 685 + .name = "usbio-bridge", 686 + .probe = usbio_probe, 687 + .disconnect = usbio_disconnect, 688 + .suspend = usbio_suspend, 689 + .resume = usbio_resume, 690 + .id_table = usbio_table, 691 + .supports_autosuspend = 1, 692 + }; 693 + module_usb_driver(usbio_driver); 694 + 695 + struct usbio_match_ids_walk_data { 696 + struct acpi_device *adev; 697 + const struct acpi_device_id *hids; 698 + unsigned int id; 699 + }; 700 + 701 + static int usbio_match_device_ids(struct acpi_device *adev, void *data) 702 + { 703 + struct usbio_match_ids_walk_data *wd = data; 704 + unsigned int id = 0; 705 + char *uid; 706 + 707 + if (acpi_match_device_ids(adev, wd->hids)) 708 + return 0; 709 + 710 + uid = acpi_device_uid(adev); 711 + if (uid) { 712 + for (int i = 0; i < strlen(uid); i++) { 713 + if (!kstrtouint(&uid[i], 10, &id)) 714 + break; 715 + } 716 + } 717 + 718 + if (!uid || wd->id == id) { 719 + wd->adev = adev; 720 + return 1; 721 + } 722 + 723 + return 0; 724 + } 725 + 726 + void usbio_acpi_bind(struct auxiliary_device *adev, const struct acpi_device_id *hids) 727 + { 728 + struct device *dev = &adev->dev; 729 + struct acpi_device *parent; 730 + struct usbio_match_ids_walk_data wd = { 731 + .adev = NULL, 732 + .hids = hids, 733 + .id = adev->id, 734 + }; 735 + 736 + parent = ACPI_COMPANION(dev->parent); 737 + if (!parent) 738 + return; 739 + 740 + acpi_dev_for_each_child(parent, usbio_match_device_ids, &wd); 741 + if (wd.adev) 742 + ACPI_COMPANION_SET(dev, wd.adev); 743 + } 744 + EXPORT_SYMBOL_NS_GPL(usbio_acpi_bind, "USBIO"); 745 + 746 + MODULE_DESCRIPTION("Intel USBIO Bridge driver"); 747 + MODULE_AUTHOR("Israel Cepeda <israel.a.cepeda.lopez@intel.com>"); 748 + MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 749 + MODULE_LICENSE("GPL");
+177
include/linux/usb/usbio.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2025 Intel Corporation. 4 + * 5 + */ 6 + 7 + #ifndef _LINUX_USBIO_H_ 8 + #define _LINUX_USBIO_H_ 9 + 10 + #include <linux/auxiliary_bus.h> 11 + #include <linux/byteorder/generic.h> 12 + #include <linux/list.h> 13 + #include <linux/types.h> 14 + 15 + /*********************** 16 + * USBIO Clients Names * 17 + ***********************/ 18 + #define USBIO_GPIO_CLIENT "usbio-gpio" 19 + #define USBIO_I2C_CLIENT "usbio-i2c" 20 + 21 + /**************** 22 + * USBIO quirks * 23 + ****************/ 24 + #define USBIO_QUIRK_BULK_MAXP_63 BIT(0) /* Force bulk endpoint maxp to 63 */ 25 + #define USBIO_QUIRK_I2C_NO_INIT_ACK BIT(8) /* Do not ask for ack on I2C init */ 26 + #define USBIO_QUIRK_I2C_MAX_RW_LEN_52 BIT(9) /* Set i2c-adapter max r/w len to 52 */ 27 + #define USBIO_QUIRK_I2C_USE_CHUNK_LEN BIT(10) /* Send chunk-len for split xfers */ 28 + #define USBIO_QUIRK_I2C_ALLOW_400KHZ BIT(11) /* Override desc, allowing 400 KHz */ 29 + 30 + /************************** 31 + * USBIO Type Definitions * 32 + **************************/ 33 + 34 + /* USBIO Packet Type */ 35 + #define USBIO_PKTTYPE_CTRL 1 36 + #define USBIO_PKTTYPE_DBG 2 37 + #define USBIO_PKTTYPE_GPIO 3 38 + #define USBIO_PKTTYPE_I2C 4 39 + 40 + /* USBIO Packet Header */ 41 + struct usbio_packet_header { 42 + u8 type; 43 + u8 cmd; 44 + u8 flags; 45 + } __packed; 46 + 47 + /* USBIO Control Transfer Packet */ 48 + struct usbio_ctrl_packet { 49 + struct usbio_packet_header header; 50 + u8 len; 51 + u8 data[] __counted_by(len); 52 + } __packed; 53 + 54 + /* USBIO Bulk Transfer Packet */ 55 + struct usbio_bulk_packet { 56 + struct usbio_packet_header header; 57 + __le16 len; 58 + u8 data[] __counted_by(len); 59 + } __packed; 60 + 61 + /* USBIO GPIO commands */ 62 + enum usbio_gpio_cmd { 63 + USBIO_GPIOCMD_DEINIT, 64 + USBIO_GPIOCMD_INIT, 65 + USBIO_GPIOCMD_READ, 66 + USBIO_GPIOCMD_WRITE, 67 + USBIO_GPIOCMD_END 68 + }; 69 + 70 + /* USBIO GPIO config */ 71 + enum usbio_gpio_pincfg { 72 + USBIO_GPIO_PINCFG_DEFAULT, 73 + USBIO_GPIO_PINCFG_PULLUP, 74 + USBIO_GPIO_PINCFG_PULLDOWN, 75 + USBIO_GPIO_PINCFG_PUSHPULL 76 + }; 77 + 78 + #define USBIO_GPIO_PINCFG_SHIFT 2 79 + #define USBIO_GPIO_PINCFG_MASK (0x3 << USBIO_GPIO_PINCFG_SHIFT) 80 + #define USBIO_GPIO_SET_PINCFG(pincfg) \ 81 + (((pincfg) << USBIO_GPIO_PINCFG_SHIFT) & USBIO_GPIO_PINCFG_MASK) 82 + 83 + enum usbio_gpio_pinmode { 84 + USBIO_GPIO_PINMOD_INVAL, 85 + USBIO_GPIO_PINMOD_INPUT, 86 + USBIO_GPIO_PINMOD_OUTPUT, 87 + USBIO_GPIO_PINMOD_MAXVAL 88 + }; 89 + 90 + #define USBIO_GPIO_PINMOD_MASK 0x3 91 + #define USBIO_GPIO_SET_PINMOD(pin) (pin & USBIO_GPIO_PINMOD_MASK) 92 + 93 + /************************* 94 + * USBIO GPIO Controller * 95 + *************************/ 96 + 97 + #define USBIO_MAX_GPIOBANKS 5 98 + #define USBIO_GPIOSPERBANK 32 99 + 100 + struct usbio_gpio_bank_desc { 101 + u8 id; 102 + u8 pins; 103 + __le32 bmap; 104 + } __packed; 105 + 106 + struct usbio_gpio_init { 107 + u8 bankid; 108 + u8 config; 109 + u8 pincount; 110 + u8 pin; 111 + } __packed; 112 + 113 + struct usbio_gpio_rw { 114 + u8 bankid; 115 + u8 pincount; 116 + u8 pin; 117 + __le32 value; 118 + } __packed; 119 + 120 + /* USBIO I2C commands */ 121 + enum usbio_i2c_cmd { 122 + USBIO_I2CCMD_UNINIT, 123 + USBIO_I2CCMD_INIT, 124 + USBIO_I2CCMD_READ, 125 + USBIO_I2CCMD_WRITE, 126 + USBIO_I2CCMD_END 127 + }; 128 + 129 + /************************ 130 + * USBIO I2C Controller * 131 + ************************/ 132 + 133 + #define USBIO_MAX_I2CBUSES 5 134 + 135 + #define USBIO_I2C_BUS_ADDR_CAP_10B BIT(3) /* 10bit address support */ 136 + #define USBIO_I2C_BUS_MODE_CAP_MASK 0x3 137 + #define USBIO_I2C_BUS_MODE_CAP_SM 0 /* Standard Mode */ 138 + #define USBIO_I2C_BUS_MODE_CAP_FM 1 /* Fast Mode */ 139 + #define USBIO_I2C_BUS_MODE_CAP_FMP 2 /* Fast Mode+ */ 140 + #define USBIO_I2C_BUS_MODE_CAP_HSM 3 /* High-Speed Mode */ 141 + 142 + struct usbio_i2c_bus_desc { 143 + u8 id; 144 + u8 caps; 145 + } __packed; 146 + 147 + struct usbio_i2c_uninit { 148 + u8 busid; 149 + __le16 config; 150 + } __packed; 151 + 152 + struct usbio_i2c_init { 153 + u8 busid; 154 + __le16 config; 155 + __le32 speed; 156 + } __packed; 157 + 158 + struct usbio_i2c_rw { 159 + u8 busid; 160 + __le16 config; 161 + __le16 size; 162 + u8 data[] __counted_by(size); 163 + } __packed; 164 + 165 + int usbio_control_msg(struct auxiliary_device *adev, u8 type, u8 cmd, 166 + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len); 167 + 168 + int usbio_bulk_msg(struct auxiliary_device *adev, u8 type, u8 cmd, bool last, 169 + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len); 170 + 171 + int usbio_acquire(struct auxiliary_device *adev); 172 + void usbio_release(struct auxiliary_device *adev); 173 + void usbio_get_txrxbuf_len(struct auxiliary_device *adev, u16 *txbuf_len, u16 *rxbuf_len); 174 + unsigned long usbio_get_quirks(struct auxiliary_device *adev); 175 + void usbio_acpi_bind(struct auxiliary_device *adev, const struct acpi_device_id *hids); 176 + 177 + #endif