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: Add support for Intel LJCA device

Implements the USB part of Intel USB-I2C/GPIO/SPI adapter device
named "La Jolla Cove Adapter" (LJCA).

The communication between the various LJCA module drivers and the
hardware will be muxed/demuxed by this driver. Three modules (
I2C, GPIO, and SPI) are supported currently.

Each sub-module of LJCA device is identified by type field within
the LJCA message header.

The sub-modules of LJCA can use ljca_transfer() to issue a transfer
between host and hardware. And ljca_register_event_cb is exported
to LJCA sub-module drivers for hardware event subscription.

The minimum code in ASL that covers this board is
Scope (\_SB.PCI0.DWC3.RHUB.HS01)
{
Device (GPIO)
{
Name (_ADR, Zero)
Name (_STA, 0x0F)
}

Device (I2C)
{
Name (_ADR, One)
Name (_STA, 0x0F)
}

Device (SPI)
{
Name (_ADR, 0x02)
Name (_STA, 0x0F)
}
}

Signed-off-by: Wentong Wu <wentong.wu@intel.com>
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
Link: https://lore.kernel.org/r/1696833205-16716-2-git-send-email-wentong.wu@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Wentong Wu and committed by
Greg Kroah-Hartman
acd6199f efa33cd8

+1061
+13
drivers/usb/misc/Kconfig
··· 165 165 166 166 It is safe to say M here. 167 167 168 + config USB_LJCA 169 + tristate "Intel La Jolla Cove Adapter support" 170 + select AUXILIARY_BUS 171 + depends on USB && ACPI 172 + help 173 + This adds support for Intel La Jolla Cove USB-I2C/SPI/GPIO 174 + Master Adapter (LJCA). Additional drivers such as I2C_LJCA, 175 + GPIO_LJCA and SPI_LJCA must be enabled in order to use the 176 + functionality of the device. 177 + 178 + This driver can also be built as a module. If so, the module 179 + will be called usb-ljca. 180 + 168 181 source "drivers/usb/misc/sisusbvga/Kconfig" 169 182 170 183 config USB_LD
+1
drivers/usb/misc/Makefile
··· 11 11 obj-$(CONFIG_USB_EMI62) += emi62.o 12 12 obj-$(CONFIG_USB_EZUSB_FX2) += ezusb.o 13 13 obj-$(CONFIG_APPLE_MFI_FASTCHARGE) += apple-mfi-fastcharge.o 14 + obj-$(CONFIG_USB_LJCA) += usb-ljca.o 14 15 obj-$(CONFIG_USB_IDMOUSE) += idmouse.o 15 16 obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o 16 17 obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o
+902
drivers/usb/misc/usb-ljca.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Intel La Jolla Cove Adapter USB driver 4 + * 5 + * Copyright (c) 2023, Intel Corporation. 6 + */ 7 + 8 + #include <linux/acpi.h> 9 + #include <linux/auxiliary_bus.h> 10 + #include <linux/dev_printk.h> 11 + #include <linux/kernel.h> 12 + #include <linux/mod_devicetable.h> 13 + #include <linux/module.h> 14 + #include <linux/mutex.h> 15 + #include <linux/slab.h> 16 + #include <linux/spinlock.h> 17 + #include <linux/types.h> 18 + #include <linux/usb.h> 19 + #include <linux/usb/ljca.h> 20 + 21 + #include <asm/unaligned.h> 22 + 23 + /* command flags */ 24 + #define LJCA_ACK_FLAG BIT(0) 25 + #define LJCA_RESP_FLAG BIT(1) 26 + #define LJCA_CMPL_FLAG BIT(2) 27 + 28 + #define LJCA_MAX_PACKET_SIZE 64u 29 + #define LJCA_MAX_PAYLOAD_SIZE \ 30 + (LJCA_MAX_PACKET_SIZE - sizeof(struct ljca_msg)) 31 + 32 + #define LJCA_WRITE_TIMEOUT_MS 200 33 + #define LJCA_WRITE_ACK_TIMEOUT_MS 500 34 + #define LJCA_ENUM_CLIENT_TIMEOUT_MS 20 35 + 36 + /* ljca client type */ 37 + enum ljca_client_type { 38 + LJCA_CLIENT_MNG = 1, 39 + LJCA_CLIENT_GPIO = 3, 40 + LJCA_CLIENT_I2C = 4, 41 + LJCA_CLIENT_SPI = 5, 42 + }; 43 + 44 + /* MNG client commands */ 45 + enum ljca_mng_cmd { 46 + LJCA_MNG_RESET = 2, 47 + LJCA_MNG_ENUM_GPIO = 4, 48 + LJCA_MNG_ENUM_I2C = 5, 49 + LJCA_MNG_ENUM_SPI = 8, 50 + }; 51 + 52 + /* ljca client acpi _ADR */ 53 + enum ljca_client_acpi_adr { 54 + LJCA_GPIO_ACPI_ADR, 55 + LJCA_I2C1_ACPI_ADR, 56 + LJCA_I2C2_ACPI_ADR, 57 + LJCA_SPI1_ACPI_ADR, 58 + LJCA_SPI2_ACPI_ADR, 59 + LJCA_CLIENT_ACPI_ADR_MAX, 60 + }; 61 + 62 + /* ljca cmd message structure */ 63 + struct ljca_msg { 64 + u8 type; 65 + u8 cmd; 66 + u8 flags; 67 + u8 len; 68 + u8 data[] __counted_by(len); 69 + } __packed; 70 + 71 + struct ljca_i2c_ctr_info { 72 + u8 id; 73 + u8 capacity; 74 + u8 intr_pin; 75 + } __packed; 76 + 77 + struct ljca_i2c_descriptor { 78 + u8 num; 79 + struct ljca_i2c_ctr_info info[] __counted_by(num); 80 + } __packed; 81 + 82 + struct ljca_spi_ctr_info { 83 + u8 id; 84 + u8 capacity; 85 + u8 intr_pin; 86 + } __packed; 87 + 88 + struct ljca_spi_descriptor { 89 + u8 num; 90 + struct ljca_spi_ctr_info info[] __counted_by(num); 91 + } __packed; 92 + 93 + struct ljca_bank_descriptor { 94 + u8 bank_id; 95 + u8 pin_num; 96 + 97 + /* 1 bit for each gpio, 1 means valid */ 98 + __le32 valid_pins; 99 + } __packed; 100 + 101 + struct ljca_gpio_descriptor { 102 + u8 pins_per_bank; 103 + u8 bank_num; 104 + struct ljca_bank_descriptor bank_desc[] __counted_by(bank_num); 105 + } __packed; 106 + 107 + /** 108 + * struct ljca_adapter - represent a ljca adapter 109 + * 110 + * @intf: the usb interface for this ljca adapter 111 + * @usb_dev: the usb device for this ljca adapter 112 + * @dev: the specific device info of the usb interface 113 + * @rx_pipe: bulk in pipe for receive data from firmware 114 + * @tx_pipe: bulk out pipe for send data to firmware 115 + * @rx_urb: urb used for the bulk in pipe 116 + * @rx_buf: buffer used to receive command response and event 117 + * @rx_len: length of rx buffer 118 + * @ex_buf: external buffer to save command response 119 + * @ex_buf_len: length of external buffer 120 + * @actual_length: actual length of data copied to external buffer 121 + * @tx_buf: buffer used to download command to firmware 122 + * @tx_buf_len: length of tx buffer 123 + * @lock: spinlock to protect tx_buf and ex_buf 124 + * @cmd_completion: completion object as the command receives ack 125 + * @mutex: mutex to avoid command download concurrently 126 + * @client_list: client device list 127 + * @disconnect: usb disconnect ongoing or not 128 + * @reset_id: used to reset firmware 129 + */ 130 + struct ljca_adapter { 131 + struct usb_interface *intf; 132 + struct usb_device *usb_dev; 133 + struct device *dev; 134 + 135 + unsigned int rx_pipe; 136 + unsigned int tx_pipe; 137 + 138 + struct urb *rx_urb; 139 + void *rx_buf; 140 + unsigned int rx_len; 141 + 142 + u8 *ex_buf; 143 + u8 ex_buf_len; 144 + u8 actual_length; 145 + 146 + void *tx_buf; 147 + u8 tx_buf_len; 148 + 149 + spinlock_t lock; 150 + 151 + struct completion cmd_completion; 152 + struct mutex mutex; 153 + 154 + struct list_head client_list; 155 + 156 + bool disconnect; 157 + 158 + u32 reset_id; 159 + }; 160 + 161 + struct ljca_match_ids_walk_data { 162 + const struct acpi_device_id *ids; 163 + const char *uid; 164 + struct acpi_device *adev; 165 + }; 166 + 167 + static const struct acpi_device_id ljca_gpio_hids[] = { 168 + { "INTC1074" }, 169 + { "INTC1096" }, 170 + { "INTC100B" }, 171 + { "INTC10D1" }, 172 + {}, 173 + }; 174 + 175 + static const struct acpi_device_id ljca_i2c_hids[] = { 176 + { "INTC1075" }, 177 + { "INTC1097" }, 178 + { "INTC100C" }, 179 + { "INTC10D2" }, 180 + {}, 181 + }; 182 + 183 + static const struct acpi_device_id ljca_spi_hids[] = { 184 + { "INTC1091" }, 185 + { "INTC1098" }, 186 + { "INTC100D" }, 187 + { "INTC10D3" }, 188 + {}, 189 + }; 190 + 191 + static void ljca_handle_event(struct ljca_adapter *adap, 192 + struct ljca_msg *header) 193 + { 194 + struct ljca_client *client; 195 + 196 + list_for_each_entry(client, &adap->client_list, link) { 197 + /* 198 + * Currently only GPIO register event callback, but 199 + * firmware message structure should include id when 200 + * multiple same type clients register event callback. 201 + */ 202 + if (client->type == header->type) { 203 + unsigned long flags; 204 + 205 + spin_lock_irqsave(&client->event_cb_lock, flags); 206 + client->event_cb(client->context, header->cmd, 207 + header->data, header->len); 208 + spin_unlock_irqrestore(&client->event_cb_lock, flags); 209 + 210 + break; 211 + } 212 + } 213 + } 214 + 215 + /* process command ack and received data if available */ 216 + static void ljca_handle_cmd_ack(struct ljca_adapter *adap, struct ljca_msg *header) 217 + { 218 + struct ljca_msg *tx_header = adap->tx_buf; 219 + u8 ibuf_len, actual_len = 0; 220 + unsigned long flags; 221 + u8 *ibuf; 222 + 223 + spin_lock_irqsave(&adap->lock, flags); 224 + 225 + if (tx_header->type != header->type || tx_header->cmd != header->cmd) { 226 + spin_unlock_irqrestore(&adap->lock, flags); 227 + dev_err(adap->dev, "cmd ack mismatch error\n"); 228 + return; 229 + } 230 + 231 + ibuf_len = adap->ex_buf_len; 232 + ibuf = adap->ex_buf; 233 + 234 + if (ibuf && ibuf_len) { 235 + actual_len = min(header->len, ibuf_len); 236 + 237 + /* copy received data to external buffer */ 238 + memcpy(ibuf, header->data, actual_len); 239 + } 240 + /* update copied data length */ 241 + adap->actual_length = actual_len; 242 + 243 + spin_unlock_irqrestore(&adap->lock, flags); 244 + 245 + complete(&adap->cmd_completion); 246 + } 247 + 248 + static void ljca_recv(struct urb *urb) 249 + { 250 + struct ljca_msg *header = urb->transfer_buffer; 251 + struct ljca_adapter *adap = urb->context; 252 + int ret; 253 + 254 + switch (urb->status) { 255 + case 0: 256 + /* success */ 257 + break; 258 + case -ENOENT: 259 + /* 260 + * directly complete the possible ongoing transfer 261 + * during disconnect 262 + */ 263 + if (adap->disconnect) 264 + complete(&adap->cmd_completion); 265 + return; 266 + case -ECONNRESET: 267 + case -ESHUTDOWN: 268 + case -EPIPE: 269 + /* rx urb is terminated */ 270 + dev_dbg(adap->dev, "rx urb terminated with status: %d\n", 271 + urb->status); 272 + return; 273 + default: 274 + dev_dbg(adap->dev, "rx urb error: %d\n", urb->status); 275 + goto resubmit; 276 + } 277 + 278 + if (header->len + sizeof(*header) != urb->actual_length) 279 + goto resubmit; 280 + 281 + if (header->flags & LJCA_ACK_FLAG) 282 + ljca_handle_cmd_ack(adap, header); 283 + else 284 + ljca_handle_event(adap, header); 285 + 286 + resubmit: 287 + ret = usb_submit_urb(urb, GFP_ATOMIC); 288 + if (ret && ret != -EPERM) 289 + dev_err(adap->dev, "resubmit rx urb error %d\n", ret); 290 + } 291 + 292 + static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd, 293 + const u8 *obuf, u8 obuf_len, u8 *ibuf, u8 ibuf_len, 294 + bool ack, unsigned long timeout) 295 + { 296 + unsigned int msg_len = sizeof(struct ljca_msg) + obuf_len; 297 + struct ljca_msg *header = adap->tx_buf; 298 + unsigned int transferred; 299 + unsigned long flags; 300 + int ret; 301 + 302 + if (adap->disconnect) 303 + return -ENODEV; 304 + 305 + if (msg_len > adap->tx_buf_len) 306 + return -EINVAL; 307 + 308 + mutex_lock(&adap->mutex); 309 + 310 + spin_lock_irqsave(&adap->lock, flags); 311 + 312 + header->type = type; 313 + header->cmd = cmd; 314 + header->len = obuf_len; 315 + if (obuf) 316 + memcpy(header->data, obuf, obuf_len); 317 + 318 + header->flags = LJCA_CMPL_FLAG | (ack ? LJCA_ACK_FLAG : 0); 319 + 320 + adap->ex_buf = ibuf; 321 + adap->ex_buf_len = ibuf_len; 322 + adap->actual_length = 0; 323 + 324 + spin_unlock_irqrestore(&adap->lock, flags); 325 + 326 + reinit_completion(&adap->cmd_completion); 327 + 328 + ret = usb_autopm_get_interface(adap->intf); 329 + if (ret < 0) 330 + goto out; 331 + 332 + ret = usb_bulk_msg(adap->usb_dev, adap->tx_pipe, header, 333 + msg_len, &transferred, LJCA_WRITE_TIMEOUT_MS); 334 + 335 + usb_autopm_put_interface(adap->intf); 336 + 337 + if (ret < 0) 338 + goto out; 339 + if (transferred != msg_len) { 340 + ret = -EIO; 341 + goto out; 342 + } 343 + 344 + if (ack) { 345 + ret = wait_for_completion_timeout(&adap->cmd_completion, 346 + timeout); 347 + if (!ret) { 348 + ret = -ETIMEDOUT; 349 + goto out; 350 + } 351 + } 352 + ret = adap->actual_length; 353 + 354 + out: 355 + spin_lock_irqsave(&adap->lock, flags); 356 + adap->ex_buf = NULL; 357 + adap->ex_buf_len = 0; 358 + 359 + memset(header, 0, sizeof(*header)); 360 + spin_unlock_irqrestore(&adap->lock, flags); 361 + 362 + mutex_unlock(&adap->mutex); 363 + 364 + return ret; 365 + } 366 + 367 + int ljca_transfer(struct ljca_client *client, u8 cmd, const u8 *obuf, 368 + u8 obuf_len, u8 *ibuf, u8 ibuf_len) 369 + { 370 + return ljca_send(client->adapter, client->type, cmd, 371 + obuf, obuf_len, ibuf, ibuf_len, true, 372 + LJCA_WRITE_ACK_TIMEOUT_MS); 373 + } 374 + EXPORT_SYMBOL_NS_GPL(ljca_transfer, LJCA); 375 + 376 + int ljca_transfer_noack(struct ljca_client *client, u8 cmd, const u8 *obuf, 377 + u8 obuf_len) 378 + { 379 + return ljca_send(client->adapter, client->type, cmd, obuf, 380 + obuf_len, NULL, 0, false, LJCA_WRITE_ACK_TIMEOUT_MS); 381 + } 382 + EXPORT_SYMBOL_NS_GPL(ljca_transfer_noack, LJCA); 383 + 384 + int ljca_register_event_cb(struct ljca_client *client, ljca_event_cb_t event_cb, 385 + void *context) 386 + { 387 + unsigned long flags; 388 + 389 + if (!event_cb) 390 + return -EINVAL; 391 + 392 + spin_lock_irqsave(&client->event_cb_lock, flags); 393 + 394 + if (client->event_cb) { 395 + spin_unlock_irqrestore(&client->event_cb_lock, flags); 396 + return -EALREADY; 397 + } 398 + 399 + client->event_cb = event_cb; 400 + client->context = context; 401 + 402 + spin_unlock_irqrestore(&client->event_cb_lock, flags); 403 + 404 + return 0; 405 + } 406 + EXPORT_SYMBOL_NS_GPL(ljca_register_event_cb, LJCA); 407 + 408 + void ljca_unregister_event_cb(struct ljca_client *client) 409 + { 410 + unsigned long flags; 411 + 412 + spin_lock_irqsave(&client->event_cb_lock, flags); 413 + 414 + client->event_cb = NULL; 415 + client->context = NULL; 416 + 417 + spin_unlock_irqrestore(&client->event_cb_lock, flags); 418 + } 419 + EXPORT_SYMBOL_NS_GPL(ljca_unregister_event_cb, LJCA); 420 + 421 + static int ljca_match_device_ids(struct acpi_device *adev, void *data) 422 + { 423 + struct ljca_match_ids_walk_data *wd = data; 424 + const char *uid = acpi_device_uid(adev); 425 + 426 + if (acpi_match_device_ids(adev, wd->ids)) 427 + return 0; 428 + 429 + if (!wd->uid) 430 + goto match; 431 + 432 + if (!uid) 433 + /* 434 + * Some DSDTs have only one ACPI companion for the two I2C 435 + * controllers and they don't set a UID at all (e.g. Dell 436 + * Latitude 9420). On these platforms only the first I2C 437 + * controller is used, so if a HID match has no UID we use 438 + * "0" as the UID and assign ACPI companion to the first 439 + * I2C controller. 440 + */ 441 + uid = "0"; 442 + else 443 + uid = strchr(uid, wd->uid[0]); 444 + 445 + if (!uid || strcmp(uid, wd->uid)) 446 + return 0; 447 + 448 + match: 449 + wd->adev = adev; 450 + 451 + return 1; 452 + } 453 + 454 + /* bind auxiliary device to acpi device */ 455 + static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap, 456 + struct auxiliary_device *auxdev, 457 + u64 adr, u8 id) 458 + { 459 + struct ljca_match_ids_walk_data wd = { 0 }; 460 + struct acpi_device *parent, *adev; 461 + struct device *dev = adap->dev; 462 + char uid[4]; 463 + 464 + parent = ACPI_COMPANION(dev); 465 + if (!parent) 466 + return; 467 + 468 + /* 469 + * get auxdev ACPI handle from the ACPI device directly 470 + * under the parent that matches _ADR. 471 + */ 472 + adev = acpi_find_child_device(parent, adr, false); 473 + if (adev) { 474 + ACPI_COMPANION_SET(&auxdev->dev, adev); 475 + return; 476 + } 477 + 478 + /* 479 + * _ADR is a grey area in the ACPI specification, some 480 + * platforms use _HID to distinguish children devices. 481 + */ 482 + switch (adr) { 483 + case LJCA_GPIO_ACPI_ADR: 484 + wd.ids = ljca_gpio_hids; 485 + break; 486 + case LJCA_I2C1_ACPI_ADR: 487 + case LJCA_I2C2_ACPI_ADR: 488 + snprintf(uid, sizeof(uid), "%d", id); 489 + wd.uid = uid; 490 + wd.ids = ljca_i2c_hids; 491 + break; 492 + case LJCA_SPI1_ACPI_ADR: 493 + case LJCA_SPI2_ACPI_ADR: 494 + wd.ids = ljca_spi_hids; 495 + break; 496 + default: 497 + dev_warn(dev, "unsupported _ADR\n"); 498 + return; 499 + } 500 + 501 + acpi_dev_for_each_child(parent, ljca_match_device_ids, &wd); 502 + if (wd.adev) { 503 + ACPI_COMPANION_SET(&auxdev->dev, wd.adev); 504 + return; 505 + } 506 + 507 + parent = ACPI_COMPANION(dev->parent->parent); 508 + if (!parent) 509 + return; 510 + 511 + acpi_dev_for_each_child(parent, ljca_match_device_ids, &wd); 512 + if (wd.adev) 513 + ACPI_COMPANION_SET(&auxdev->dev, wd.adev); 514 + } 515 + 516 + static void ljca_auxdev_release(struct device *dev) 517 + { 518 + struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 519 + 520 + kfree(auxdev->dev.platform_data); 521 + } 522 + 523 + static int ljca_new_client_device(struct ljca_adapter *adap, u8 type, u8 id, 524 + char *name, void *data, u64 adr) 525 + { 526 + struct auxiliary_device *auxdev; 527 + struct ljca_client *client; 528 + int ret; 529 + 530 + client = kzalloc(sizeof *client, GFP_KERNEL); 531 + if (!client) 532 + return -ENOMEM; 533 + 534 + client->type = type; 535 + client->id = id; 536 + client->adapter = adap; 537 + spin_lock_init(&client->event_cb_lock); 538 + 539 + auxdev = &client->auxdev; 540 + auxdev->name = name; 541 + auxdev->id = id; 542 + 543 + auxdev->dev.parent = adap->dev; 544 + auxdev->dev.platform_data = data; 545 + auxdev->dev.release = ljca_auxdev_release; 546 + 547 + ret = auxiliary_device_init(auxdev); 548 + if (ret) 549 + goto err_free; 550 + 551 + ljca_auxdev_acpi_bind(adap, auxdev, adr, id); 552 + 553 + ret = auxiliary_device_add(auxdev); 554 + if (ret) 555 + goto err_uninit; 556 + 557 + list_add_tail(&client->link, &adap->client_list); 558 + 559 + return 0; 560 + 561 + err_uninit: 562 + auxiliary_device_uninit(auxdev); 563 + 564 + err_free: 565 + kfree(client); 566 + 567 + return ret; 568 + } 569 + 570 + static int ljca_enumerate_gpio(struct ljca_adapter *adap) 571 + { 572 + u32 valid_pin[LJCA_MAX_GPIO_NUM / BITS_PER_TYPE(u32)]; 573 + struct ljca_gpio_descriptor *desc; 574 + struct ljca_gpio_info *gpio_info; 575 + u8 buf[LJCA_MAX_PAYLOAD_SIZE]; 576 + int ret, gpio_num; 577 + unsigned int i; 578 + 579 + ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_GPIO, NULL, 0, buf, 580 + sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS); 581 + if (ret < 0) 582 + return ret; 583 + 584 + /* check firmware response */ 585 + desc = (struct ljca_gpio_descriptor *)buf; 586 + if (ret != struct_size(desc, bank_desc, desc->bank_num)) 587 + return -EINVAL; 588 + 589 + gpio_num = desc->pins_per_bank * desc->bank_num; 590 + if (gpio_num > LJCA_MAX_GPIO_NUM) 591 + return -EINVAL; 592 + 593 + /* construct platform data */ 594 + gpio_info = kzalloc(sizeof *gpio_info, GFP_KERNEL); 595 + if (!gpio_info) 596 + return -ENOMEM; 597 + gpio_info->num = gpio_num; 598 + 599 + for (i = 0; i < desc->bank_num; i++) 600 + valid_pin[i] = get_unaligned_le32(&desc->bank_desc[i].valid_pins); 601 + bitmap_from_arr32(gpio_info->valid_pin_map, valid_pin, gpio_num); 602 + 603 + ret = ljca_new_client_device(adap, LJCA_CLIENT_GPIO, 0, "ljca-gpio", 604 + gpio_info, LJCA_GPIO_ACPI_ADR); 605 + if (ret) 606 + kfree(gpio_info); 607 + 608 + return ret; 609 + } 610 + 611 + static int ljca_enumerate_i2c(struct ljca_adapter *adap) 612 + { 613 + struct ljca_i2c_descriptor *desc; 614 + struct ljca_i2c_info *i2c_info; 615 + u8 buf[LJCA_MAX_PAYLOAD_SIZE]; 616 + unsigned int i; 617 + int ret; 618 + 619 + ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_I2C, NULL, 0, buf, 620 + sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS); 621 + if (ret < 0) 622 + return ret; 623 + 624 + /* check firmware response */ 625 + desc = (struct ljca_i2c_descriptor *)buf; 626 + if (ret != struct_size(desc, info, desc->num)) 627 + return -EINVAL; 628 + 629 + for (i = 0; i < desc->num; i++) { 630 + /* construct platform data */ 631 + i2c_info = kzalloc(sizeof *i2c_info, GFP_KERNEL); 632 + if (!i2c_info) 633 + return -ENOMEM; 634 + 635 + i2c_info->id = desc->info[i].id; 636 + i2c_info->capacity = desc->info[i].capacity; 637 + i2c_info->intr_pin = desc->info[i].intr_pin; 638 + 639 + ret = ljca_new_client_device(adap, LJCA_CLIENT_I2C, i, 640 + "ljca-i2c", i2c_info, 641 + LJCA_I2C1_ACPI_ADR + i); 642 + if (ret) { 643 + kfree(i2c_info); 644 + return ret; 645 + } 646 + } 647 + 648 + return 0; 649 + } 650 + 651 + static int ljca_enumerate_spi(struct ljca_adapter *adap) 652 + { 653 + struct ljca_spi_descriptor *desc; 654 + struct ljca_spi_info *spi_info; 655 + u8 buf[LJCA_MAX_PAYLOAD_SIZE]; 656 + unsigned int i; 657 + int ret; 658 + 659 + ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf, 660 + sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS); 661 + if (ret < 0) 662 + return ret; 663 + 664 + /* check firmware response */ 665 + desc = (struct ljca_spi_descriptor *)buf; 666 + if (ret != struct_size(desc, info, desc->num)) 667 + return -EINVAL; 668 + 669 + for (i = 0; i < desc->num; i++) { 670 + /* construct platform data */ 671 + spi_info = kzalloc(sizeof *spi_info, GFP_KERNEL); 672 + if (!spi_info) 673 + return -ENOMEM; 674 + 675 + spi_info->id = desc->info[i].id; 676 + spi_info->capacity = desc->info[i].capacity; 677 + 678 + ret = ljca_new_client_device(adap, LJCA_CLIENT_SPI, i, 679 + "ljca-spi", spi_info, 680 + LJCA_SPI1_ACPI_ADR + i); 681 + if (ret) { 682 + kfree(spi_info); 683 + return ret; 684 + } 685 + } 686 + 687 + return 0; 688 + } 689 + 690 + static int ljca_reset_handshake(struct ljca_adapter *adap) 691 + { 692 + __le32 reset_id = cpu_to_le32(adap->reset_id); 693 + __le32 reset_id_ret = 0; 694 + int ret; 695 + 696 + adap->reset_id++; 697 + 698 + ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_RESET, (u8 *)&reset_id, 699 + sizeof(__le32), (u8 *)&reset_id_ret, sizeof(__le32), 700 + true, LJCA_WRITE_ACK_TIMEOUT_MS); 701 + if (ret < 0) 702 + return ret; 703 + 704 + if (reset_id_ret != reset_id) 705 + return -EINVAL; 706 + 707 + return 0; 708 + } 709 + 710 + static int ljca_enumerate_clients(struct ljca_adapter *adap) 711 + { 712 + struct ljca_client *client, *next; 713 + int ret; 714 + 715 + ret = ljca_reset_handshake(adap); 716 + if (ret) 717 + goto err_kill; 718 + 719 + ret = ljca_enumerate_gpio(adap); 720 + if (ret) { 721 + dev_err(adap->dev, "enumerate GPIO error\n"); 722 + goto err_kill; 723 + } 724 + 725 + ret = ljca_enumerate_i2c(adap); 726 + if (ret) { 727 + dev_err(adap->dev, "enumerate I2C error\n"); 728 + goto err_kill; 729 + } 730 + 731 + ret = ljca_enumerate_spi(adap); 732 + if (ret) { 733 + dev_err(adap->dev, "enumerate SPI error\n"); 734 + goto err_kill; 735 + } 736 + 737 + return 0; 738 + 739 + err_kill: 740 + adap->disconnect = true; 741 + 742 + usb_kill_urb(adap->rx_urb); 743 + 744 + list_for_each_entry_safe_reverse(client, next, &adap->client_list, link) { 745 + auxiliary_device_delete(&client->auxdev); 746 + auxiliary_device_uninit(&client->auxdev); 747 + 748 + list_del_init(&client->link); 749 + kfree(client); 750 + } 751 + 752 + return ret; 753 + } 754 + 755 + static int ljca_probe(struct usb_interface *interface, 756 + const struct usb_device_id *id) 757 + { 758 + struct usb_device *usb_dev = interface_to_usbdev(interface); 759 + struct usb_host_interface *alt = interface->cur_altsetting; 760 + struct usb_endpoint_descriptor *ep_in, *ep_out; 761 + struct device *dev = &interface->dev; 762 + struct ljca_adapter *adap; 763 + int ret; 764 + 765 + adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL); 766 + if (!adap) 767 + return -ENOMEM; 768 + 769 + /* separate tx buffer allocation for alignment */ 770 + adap->tx_buf = devm_kzalloc(dev, LJCA_MAX_PACKET_SIZE, GFP_KERNEL); 771 + if (!adap->tx_buf) 772 + return -ENOMEM; 773 + adap->tx_buf_len = LJCA_MAX_PACKET_SIZE; 774 + 775 + mutex_init(&adap->mutex); 776 + spin_lock_init(&adap->lock); 777 + init_completion(&adap->cmd_completion); 778 + INIT_LIST_HEAD(&adap->client_list); 779 + 780 + adap->intf = usb_get_intf(interface); 781 + adap->usb_dev = usb_dev; 782 + adap->dev = dev; 783 + 784 + /* 785 + * find the first bulk in and out endpoints. 786 + * ignore any others. 787 + */ 788 + ret = usb_find_common_endpoints(alt, &ep_in, &ep_out, NULL, NULL); 789 + if (ret) { 790 + dev_err(dev, "bulk endpoints not found\n"); 791 + goto err_put; 792 + } 793 + adap->rx_pipe = usb_rcvbulkpipe(usb_dev, usb_endpoint_num(ep_in)); 794 + adap->tx_pipe = usb_sndbulkpipe(usb_dev, usb_endpoint_num(ep_out)); 795 + 796 + /* setup rx buffer */ 797 + adap->rx_len = usb_endpoint_maxp(ep_in); 798 + adap->rx_buf = devm_kzalloc(dev, adap->rx_len, GFP_KERNEL); 799 + if (!adap->rx_buf) { 800 + ret = -ENOMEM; 801 + goto err_put; 802 + } 803 + 804 + /* alloc rx urb */ 805 + adap->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 806 + if (!adap->rx_urb) { 807 + ret = -ENOMEM; 808 + goto err_put; 809 + } 810 + usb_fill_bulk_urb(adap->rx_urb, usb_dev, adap->rx_pipe, 811 + adap->rx_buf, adap->rx_len, ljca_recv, adap); 812 + 813 + usb_set_intfdata(interface, adap); 814 + 815 + /* submit rx urb before enumerate clients */ 816 + ret = usb_submit_urb(adap->rx_urb, GFP_KERNEL); 817 + if (ret) { 818 + dev_err(dev, "submit rx urb failed: %d\n", ret); 819 + goto err_free; 820 + } 821 + 822 + ret = ljca_enumerate_clients(adap); 823 + if (ret) 824 + goto err_free; 825 + 826 + usb_enable_autosuspend(usb_dev); 827 + 828 + return 0; 829 + 830 + err_free: 831 + usb_free_urb(adap->rx_urb); 832 + 833 + err_put: 834 + usb_put_intf(adap->intf); 835 + 836 + mutex_destroy(&adap->mutex); 837 + 838 + return ret; 839 + } 840 + 841 + static void ljca_disconnect(struct usb_interface *interface) 842 + { 843 + struct ljca_adapter *adap = usb_get_intfdata(interface); 844 + struct ljca_client *client, *next; 845 + 846 + adap->disconnect = true; 847 + 848 + usb_kill_urb(adap->rx_urb); 849 + 850 + list_for_each_entry_safe_reverse(client, next, &adap->client_list, link) { 851 + auxiliary_device_delete(&client->auxdev); 852 + auxiliary_device_uninit(&client->auxdev); 853 + 854 + list_del_init(&client->link); 855 + kfree(client); 856 + } 857 + 858 + usb_free_urb(adap->rx_urb); 859 + 860 + usb_put_intf(adap->intf); 861 + 862 + mutex_destroy(&adap->mutex); 863 + } 864 + 865 + static int ljca_suspend(struct usb_interface *interface, pm_message_t message) 866 + { 867 + struct ljca_adapter *adap = usb_get_intfdata(interface); 868 + 869 + usb_kill_urb(adap->rx_urb); 870 + 871 + return 0; 872 + } 873 + 874 + static int ljca_resume(struct usb_interface *interface) 875 + { 876 + struct ljca_adapter *adap = usb_get_intfdata(interface); 877 + 878 + return usb_submit_urb(adap->rx_urb, GFP_KERNEL); 879 + } 880 + 881 + static const struct usb_device_id ljca_table[] = { 882 + { USB_DEVICE(0x8086, 0x0b63) }, 883 + { /* sentinel */ } 884 + }; 885 + MODULE_DEVICE_TABLE(usb, ljca_table); 886 + 887 + static struct usb_driver ljca_driver = { 888 + .name = "ljca", 889 + .id_table = ljca_table, 890 + .probe = ljca_probe, 891 + .disconnect = ljca_disconnect, 892 + .suspend = ljca_suspend, 893 + .resume = ljca_resume, 894 + .supports_autosuspend = 1, 895 + }; 896 + module_usb_driver(ljca_driver); 897 + 898 + MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>"); 899 + MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>"); 900 + MODULE_AUTHOR("Lixu Zhang <lixu.zhang@intel.com>"); 901 + MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB driver"); 902 + MODULE_LICENSE("GPL");
+145
include/linux/usb/ljca.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2023, Intel Corporation. All rights reserved. 4 + */ 5 + #ifndef _LINUX_USB_LJCA_H_ 6 + #define _LINUX_USB_LJCA_H_ 7 + 8 + #include <linux/auxiliary_bus.h> 9 + #include <linux/list.h> 10 + #include <linux/spinlock.h> 11 + #include <linux/types.h> 12 + 13 + #define LJCA_MAX_GPIO_NUM 64 14 + 15 + #define auxiliary_dev_to_ljca_client(auxiliary_dev) \ 16 + container_of(auxiliary_dev, struct ljca_client, auxdev) 17 + 18 + struct ljca_adapter; 19 + 20 + /** 21 + * typedef ljca_event_cb_t - event callback function signature 22 + * 23 + * @context: the execution context of who registered this callback 24 + * @cmd: the command from device for this event 25 + * @evt_data: the event data payload 26 + * @len: the event data payload length 27 + * 28 + * The callback function is called in interrupt context and the data payload is 29 + * only valid during the call. If the user needs later access of the data, it 30 + * must copy it. 31 + */ 32 + typedef void (*ljca_event_cb_t)(void *context, u8 cmd, const void *evt_data, int len); 33 + 34 + /** 35 + * struct ljca_client - represent a ljca client device 36 + * 37 + * @type: ljca client type 38 + * @id: ljca client id within same client type 39 + * @link: ljca client on the same ljca adapter 40 + * @auxdev: auxiliary device object 41 + * @adapter: ljca adapter the ljca client sit on 42 + * @context: the execution context of the event callback 43 + * @event_cb: ljca client driver register this callback to get 44 + * firmware asynchronous rx buffer pending notifications 45 + * @event_cb_lock: spinlock to protect event callback 46 + */ 47 + struct ljca_client { 48 + u8 type; 49 + u8 id; 50 + struct list_head link; 51 + struct auxiliary_device auxdev; 52 + struct ljca_adapter *adapter; 53 + 54 + void *context; 55 + ljca_event_cb_t event_cb; 56 + /* lock to protect event_cb */ 57 + spinlock_t event_cb_lock; 58 + }; 59 + 60 + /** 61 + * struct ljca_gpio_info - ljca gpio client device info 62 + * 63 + * @num: ljca gpio client device pin number 64 + * @valid_pin_map: ljca gpio client device valid pin mapping 65 + */ 66 + struct ljca_gpio_info { 67 + unsigned int num; 68 + DECLARE_BITMAP(valid_pin_map, LJCA_MAX_GPIO_NUM); 69 + }; 70 + 71 + /** 72 + * struct ljca_i2c_info - ljca i2c client device info 73 + * 74 + * @id: ljca i2c client device identification number 75 + * @capacity: ljca i2c client device capacity 76 + * @intr_pin: ljca i2c client device interrupt pin number if exists 77 + */ 78 + struct ljca_i2c_info { 79 + u8 id; 80 + u8 capacity; 81 + u8 intr_pin; 82 + }; 83 + 84 + /** 85 + * struct ljca_spi_info - ljca spi client device info 86 + * 87 + * @id: ljca spi client device identification number 88 + * @capacity: ljca spi client device capacity 89 + */ 90 + struct ljca_spi_info { 91 + u8 id; 92 + u8 capacity; 93 + }; 94 + 95 + /** 96 + * ljca_register_event_cb - register a callback function to receive events 97 + * 98 + * @client: ljca client device 99 + * @event_cb: callback function 100 + * @context: execution context of event callback 101 + * 102 + * Return: 0 in case of success, negative value in case of error 103 + */ 104 + int ljca_register_event_cb(struct ljca_client *client, ljca_event_cb_t event_cb, void *context); 105 + 106 + /** 107 + * ljca_unregister_event_cb - unregister the callback function for an event 108 + * 109 + * @client: ljca client device 110 + */ 111 + void ljca_unregister_event_cb(struct ljca_client *client); 112 + 113 + /** 114 + * ljca_transfer - issue a LJCA command and wait for a response 115 + * 116 + * @client: ljca client device 117 + * @cmd: the command to be sent to the device 118 + * @obuf: the buffer to be sent to the device; it can be NULL if the user 119 + * doesn't need to transmit data with this command 120 + * @obuf_len: the size of the buffer to be sent to the device; it should 121 + * be 0 when obuf is NULL 122 + * @ibuf: any data associated with the response will be copied here; it can be 123 + * NULL if the user doesn't need the response data 124 + * @ibuf_len: must be initialized to the input buffer size 125 + * 126 + * Return: the actual length of response data for success, negative value for errors 127 + */ 128 + int ljca_transfer(struct ljca_client *client, u8 cmd, const u8 *obuf, 129 + u8 obuf_len, u8 *ibuf, u8 ibuf_len); 130 + 131 + /** 132 + * ljca_transfer_noack - issue a LJCA command without a response 133 + * 134 + * @client: ljca client device 135 + * @cmd: the command to be sent to the device 136 + * @obuf: the buffer to be sent to the device; it can be NULL if the user 137 + * doesn't need to transmit data with this command 138 + * @obuf_len: the size of the buffer to be sent to the device 139 + * 140 + * Return: 0 for success, negative value for errors 141 + */ 142 + int ljca_transfer_noack(struct ljca_client *client, u8 cmd, const u8 *obuf, 143 + u8 obuf_len); 144 + 145 + #endif