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.

Merge tag 'chrome-platform-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux

Pull chrome platform updates from Tzung-Bi Shih:
"New cros_ec_lightbar features:
- Report the number of exposed LED segments via sysfs
- Support large sequence of program to be transmitted

Fixes:
- Don't touch fwnode_handle::dev which is a private field
- Fix wrong assignment for response size in cros_ec_lightbar

Cleanups:
- Use acpi_get_local_u64_address() helper"

* tag 'chrome-platform-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
platform/chrome: lightbar: Use flexible array member
platform/chrome: lightbar: Fix lightbar_program_ex alignment
platform/chrome: lightbar: Add support for large sequence
platform/chrome: lightbar: Report number of segments
platform/chrome: cros_ec_lightbar: Fix response size initialization
platform/chrome: cros_typec_switch: Use acpi_get_local_u64_address()
platform/chrome: cros_typec_switch: Don't touch struct fwnode_handle::dev

+134 -42
+105 -28
drivers/platform/chrome/cros_ec_lightbar.c
··· 37 37 */ 38 38 static bool has_manual_suspend; 39 39 40 + /* 41 + * Lightbar version 42 + */ 43 + static int lb_version; 44 + 40 45 static ssize_t interval_msec_show(struct device *dev, 41 46 struct device_attribute *attr, char *buf) 42 47 { ··· 98 93 99 94 static struct cros_ec_command *alloc_lightbar_cmd_msg(struct cros_ec_dev *ec) 100 95 { 96 + int len = max(ec->ec_dev->max_response, ec->ec_dev->max_request); 101 97 struct cros_ec_command *msg; 102 - int len; 103 - 104 - len = max(sizeof(struct ec_params_lightbar), 105 - sizeof(struct ec_response_lightbar)); 106 98 107 99 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL); 108 100 if (!msg) ··· 107 105 108 106 msg->version = 0; 109 107 msg->command = EC_CMD_LIGHTBAR_CMD + ec->cmd_offset; 108 + /* 109 + * Default sizes for regular commands. 110 + * Can be set smaller to optimize transfer, 111 + * larger when sending large light sequences. 112 + */ 110 113 msg->outsize = sizeof(struct ec_params_lightbar); 111 114 msg->insize = sizeof(struct ec_response_lightbar); 112 115 ··· 133 126 param = (struct ec_params_lightbar *)msg->data; 134 127 param->cmd = LIGHTBAR_CMD_VERSION; 135 128 msg->outsize = sizeof(param->cmd); 136 - msg->result = sizeof(resp->version); 129 + msg->insize = sizeof(resp->version); 137 130 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 138 131 if (ret < 0 && ret != -EINVAL) { 139 132 ret = 0; ··· 185 178 return -EIO; 186 179 187 180 return sysfs_emit(buf, "%d %d\n", version, flags); 181 + } 182 + 183 + static ssize_t num_segments_show(struct device *dev, 184 + struct device_attribute *attr, char *buf) 185 + { 186 + struct ec_params_lightbar *param; 187 + struct ec_response_lightbar *resp; 188 + struct cros_ec_command *msg; 189 + struct cros_ec_dev *ec = to_cros_ec_dev(dev); 190 + uint32_t num = 0; 191 + int ret; 192 + 193 + ret = lb_throttle(); 194 + if (ret) 195 + return ret; 196 + 197 + msg = alloc_lightbar_cmd_msg(ec); 198 + if (!msg) 199 + return -ENOMEM; 200 + 201 + param = (struct ec_params_lightbar *)msg->data; 202 + param->cmd = LIGHTBAR_CMD_GET_PARAMS_V3; 203 + msg->outsize = sizeof(param->cmd); 204 + msg->insize = sizeof(resp->get_params_v3); 205 + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 206 + if (ret < 0 && ret != -EINVAL) 207 + goto exit; 208 + 209 + if (msg->result == EC_RES_SUCCESS) { 210 + resp = (struct ec_response_lightbar *)msg->data; 211 + num = resp->get_params_v3.reported_led_num; 212 + } 213 + 214 + /* 215 + * Anything else (ie, EC_RES_INVALID_COMMAND) - no direct control over 216 + * LEDs, return that no leds are supported. 217 + */ 218 + ret = sysfs_emit(buf, "%u\n", num); 219 + exit: 220 + kfree(msg); 221 + return ret; 188 222 } 189 223 190 224 static ssize_t brightness_store(struct device *dev, ··· 478 430 static ssize_t program_store(struct device *dev, struct device_attribute *attr, 479 431 const char *buf, size_t count) 480 432 { 481 - int extra_bytes, max_size, ret; 433 + size_t extra_bytes, max_size; 482 434 struct ec_params_lightbar *param; 483 435 struct cros_ec_command *msg; 484 436 struct cros_ec_dev *ec = to_cros_ec_dev(dev); 437 + int ret; 485 438 486 439 /* 487 440 * We might need to reject the program for size reasons. The EC ··· 490 441 * and send a program that is too big for the protocol. In order 491 442 * to ensure the latter, we also need to ensure we have extra bytes 492 443 * to represent the rest of the packet. 444 + * With V3, larger program can be sent, limited only by the EC. 445 + * Only the protocol limit the payload size. 493 446 */ 494 - extra_bytes = sizeof(*param) - sizeof(param->set_program.data); 495 - max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); 496 - if (count > max_size) { 497 - dev_err(dev, "Program is %u bytes, too long to send (max: %u)", 498 - (unsigned int)count, max_size); 447 + if (lb_version < 3) { 448 + extra_bytes = sizeof(*param) - sizeof(param->set_program.data); 449 + max_size = min(EC_LB_PROG_LEN, ec->ec_dev->max_request - extra_bytes); 450 + if (count > max_size) { 451 + dev_err(dev, "Program is %zu bytes, too long to send (max: %zu)", 452 + count, max_size); 499 453 500 - return -EINVAL; 454 + return -EINVAL; 455 + } 456 + } else { 457 + extra_bytes = offsetof(typeof(*param), set_program_ex) + 458 + sizeof(param->set_program_ex); 459 + max_size = ec->ec_dev->max_request - extra_bytes; 501 460 } 502 461 503 462 msg = alloc_lightbar_cmd_msg(ec); ··· 515 458 ret = lb_throttle(); 516 459 if (ret) 517 460 goto exit; 518 - 519 - dev_info(dev, "Copying %zu byte program to EC", count); 520 - 521 461 param = (struct ec_params_lightbar *)msg->data; 522 - param->cmd = LIGHTBAR_CMD_SET_PROGRAM; 523 462 524 - param->set_program.size = count; 525 - memcpy(param->set_program.data, buf, count); 463 + if (lb_version < 3) { 464 + dev_info(dev, "Copying %zu byte program to EC", count); 526 465 527 - /* 528 - * We need to set the message size manually or else it will use 529 - * EC_LB_PROG_LEN. This might be too long, and the program 530 - * is unlikely to use all of the space. 531 - */ 532 - msg->outsize = count + extra_bytes; 466 + param->cmd = LIGHTBAR_CMD_SET_PROGRAM; 533 467 534 - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 535 - if (ret < 0) 536 - goto exit; 468 + param->set_program.size = count; 469 + memcpy(param->set_program.data, buf, count); 537 470 471 + /* 472 + * We need to set the message size manually or else it will use 473 + * EC_LB_PROG_LEN. This might be too long, and the program 474 + * is unlikely to use all of the space. 475 + */ 476 + msg->outsize = count + extra_bytes; 477 + 478 + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 479 + if (ret < 0) 480 + goto exit; 481 + } else { 482 + size_t offset = 0; 483 + size_t payload = 0; 484 + 485 + param->cmd = LIGHTBAR_CMD_SET_PROGRAM_EX; 486 + while (offset < count) { 487 + payload = min(max_size, count - offset); 488 + param->set_program_ex.offset = offset; 489 + param->set_program_ex.size = payload; 490 + memcpy(param->set_program_ex.data, &buf[offset], payload); 491 + msg->outsize = payload + extra_bytes; 492 + 493 + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 494 + if (ret < 0) 495 + goto exit; 496 + offset += payload; 497 + } 498 + } 538 499 ret = count; 539 500 exit: 540 501 kfree(msg); ··· 587 512 /* Module initialization */ 588 513 589 514 static DEVICE_ATTR_RW(interval_msec); 515 + static DEVICE_ATTR_RO(num_segments); 590 516 static DEVICE_ATTR_RO(version); 591 517 static DEVICE_ATTR_WO(brightness); 592 518 static DEVICE_ATTR_WO(led_rgb); ··· 597 521 598 522 static struct attribute *__lb_cmds_attrs[] = { 599 523 &dev_attr_interval_msec.attr, 524 + &dev_attr_num_segments.attr, 600 525 &dev_attr_version.attr, 601 526 &dev_attr_brightness.attr, 602 527 &dev_attr_led_rgb.attr, ··· 630 553 * Ask then for the lightbar version, if it's 0 then the 'cros_ec' 631 554 * doesn't have a lightbar. 632 555 */ 633 - if (!get_lightbar_version(ec_dev, NULL, NULL)) 556 + if (!get_lightbar_version(ec_dev, &lb_version, NULL)) 634 557 return -ENODEV; 635 558 636 559 /* Take control of the lightbar from the EC. */
+5 -14
drivers/platform/chrome/cros_typec_switch.c
··· 211 211 struct cros_typec_port *port; 212 212 struct device *dev = sdata->dev; 213 213 struct fwnode_handle *fwnode; 214 - struct acpi_device *adev; 215 - unsigned long long index; 216 214 int nports, ret; 215 + u64 index; 217 216 218 217 nports = device_get_child_node_count(dev); 219 218 if (nports == 0) { ··· 227 228 goto err_switch; 228 229 } 229 230 230 - adev = to_acpi_device_node(fwnode); 231 - if (!adev) { 232 - dev_err(fwnode->dev, "Couldn't get ACPI device handle\n"); 233 - ret = -ENODEV; 234 - goto err_switch; 235 - } 236 - 237 - ret = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &index); 238 - if (ACPI_FAILURE(ret)) { 239 - dev_err(fwnode->dev, "_ADR wasn't evaluated\n"); 240 - ret = -ENODATA; 231 + ret = acpi_get_local_u64_address(ACPI_HANDLE_FWNODE(fwnode), &index); 232 + if (ret) { 233 + dev_err(dev, "_ADR wasn't evaluated for %pfwP\n", fwnode); 241 234 goto err_switch; 242 235 } 243 236 244 237 if (index >= EC_USB_PD_MAX_PORTS) { 245 - dev_err(fwnode->dev, "Invalid port index number: %llu\n", index); 238 + dev_err(dev, "%pfwP: Invalid port index number: %llu\n", fwnode, index); 246 239 ret = -EINVAL; 247 240 goto err_switch; 248 241 }
+24
include/linux/platform_data/cros_ec_commands.h
··· 2005 2005 struct rgb_s color[8]; /* 0-3 are Google colors */ 2006 2006 } __ec_todo_packed; 2007 2007 2008 + struct lightbar_params_v3 { 2009 + /* 2010 + * Number of LEDs reported by the EC. 2011 + * May be less than the actual number of LEDs in the lightbar. 2012 + */ 2013 + uint8_t reported_led_num; 2014 + } __ec_todo_packed; 2015 + 2008 2016 /* Lightbar program. */ 2009 2017 #define EC_LB_PROG_LEN 192 2010 2018 struct lightbar_program { 2011 2019 uint8_t size; 2012 2020 uint8_t data[EC_LB_PROG_LEN]; 2013 2021 } __ec_todo_unpacked; 2022 + 2023 + /* 2024 + * Lightbar program for large sequences. Sequences are sent in pieces, with 2025 + * increasing offset. The sequences are still limited by the amount reserved in 2026 + * EC RAM. 2027 + */ 2028 + struct lightbar_program_ex { 2029 + uint8_t size; 2030 + uint16_t offset; 2031 + uint8_t data[]; 2032 + } __ec_todo_packed; 2014 2033 2015 2034 struct ec_params_lightbar { 2016 2035 uint8_t cmd; /* Command (see enum lightbar_command) */ ··· 2077 2058 struct lightbar_params_v2_colors set_v2par_colors; 2078 2059 2079 2060 struct lightbar_program set_program; 2061 + struct lightbar_program_ex set_program_ex; 2080 2062 }; 2081 2063 } __ec_todo_packed; 2082 2064 ··· 2105 2085 struct lightbar_params_v2_brightness get_params_v2_bright; 2106 2086 struct lightbar_params_v2_thresholds get_params_v2_thlds; 2107 2087 struct lightbar_params_v2_colors get_params_v2_colors; 2088 + 2089 + struct lightbar_params_v3 get_params_v3; 2108 2090 2109 2091 struct __ec_todo_unpacked { 2110 2092 uint32_t num; ··· 2165 2143 LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS = 31, 2166 2144 LIGHTBAR_CMD_GET_PARAMS_V2_COLORS = 32, 2167 2145 LIGHTBAR_CMD_SET_PARAMS_V2_COLORS = 33, 2146 + LIGHTBAR_CMD_GET_PARAMS_V3 = 34, 2147 + LIGHTBAR_CMD_SET_PROGRAM_EX = 35, 2168 2148 LIGHTBAR_NUM_CMDS 2169 2149 }; 2170 2150