chrome-platform: Updates for v6.17

* New
 
   - Support ECC in chromeos_pstore.
   - Allow to control power and data role via sysfs in cros_ec_typec.
 
 * Improvements
 
   - Defer probe when the dependencies are not ready in cros_ec_typec.
   - Retry when a sensor is not ready in cros_ec_sensorhub.
 
 * Fixes
 
   - Unregister the blocking notifier as well when unregistering the
     struct cros_ec_device.
 
 * Cleanups
 
   - Remove redundant code and leverage more suitable helper macro in
     chromeos_laptop.
   - Fix typo.
 -----BEGIN PGP SIGNATURE-----
 
 iIkEABYKADEWIQS0yQeDP3cjLyifNRUrxTEGBto89AUCaIcVZhMcdHp1bmdiaUBr
 ZXJuZWwub3JnAAoJECvFMQYG2jz06+oBAI/DYCKldtOuy+evThTHsvcysYV9bTao
 M0j6jwO0/UyMAP9lnTnkt9xAXwurtGtQndFUEmmXPEiIwFlyOS3e/Jg6BQ==
 =xX5P
 -----END PGP SIGNATURE-----

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

Pull chrome platform updates from Tzung-Bi Shih:
 "New:
   - Support ECC in chromeos_pstore
   - Allow to control power and data role via sysfs in cros_ec_typec

  Improvements:
   - Defer probe when the dependencies are not ready in cros_ec_typec
   - Retry when a sensor is not ready in cros_ec_sensorhub

  Fixes:
   - Unregister the blocking notifier as well when unregistering the
     struct cros_ec_device.

  Cleanups:
   - Remove redundant code and leverage more suitable helper macro in
     chromeos_laptop
   - Fix typo"

* tag 'chrome-platform-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
  platform/chrome: Fix typo in CROS_USBPD_NOTIFY help text
  platform/chrome: cros_ec_typec: Check ec platform device pointer
  platform/chrome: cros_ec: Unregister notifier in cros_ec_unregister()
  platform/chrome: cros_ec_typec: Add role swap ops
  platform/chrome: chromeos_laptop: Replace open coded variant of DEFINE_RES_IRQ()
  platform/chrome: chromeos_laptop: Remove duplicate check
  platform/chrome: cros_ec_sensorhub: Retries when a sensor is not ready
  platform/chrome: chromeos_pstore: Add ecc_size module parameter
  platform/chrome: cros_ec_typec: Defer probe on missing EC parent
This commit is contained in:
Linus Torvalds 2025-07-28 23:26:07 -07:00
commit 86aa721820
6 changed files with 121 additions and 14 deletions

View file

@ -286,7 +286,7 @@ config CROS_USBPD_NOTIFY
default MFD_CROS_EC_DEV
help
If you say Y here, you get support for Type-C PD event notifications
from the ChromeOS EC. On ACPI platorms this driver will bind to the
from the ChromeOS EC. On ACPI platforms this driver will bind to the
GOOG0003 ACPI device, and on platforms which don't have this device it
will get initialized on ECs which support the feature
EC_FEATURE_USB_PD.

View file

@ -726,9 +726,9 @@ static int __init chromeos_laptop_setup_irq(struct i2c_peripheral *i2c_dev)
if (irq < 0)
return irq;
i2c_dev->irq_resource = (struct resource)
DEFINE_RES_NAMED(irq, 1, NULL,
IORESOURCE_IRQ | i2c_dev->irqflags);
i2c_dev->irq_resource = DEFINE_RES_IRQ(irq);
i2c_dev->irq_resource.flags |= i2c_dev->irqflags;
i2c_dev->board_info.resources = &i2c_dev->irq_resource;
i2c_dev->board_info.num_resources = 1;
}
@ -782,8 +782,7 @@ err_out:
while (--i >= 0) {
i2c_dev = &i2c_peripherals[i];
info = &i2c_dev->board_info;
if (!IS_ERR_OR_NULL(info->fwnode))
fwnode_remove_software_node(info->fwnode);
fwnode_remove_software_node(info->fwnode);
}
kfree(i2c_peripherals);
return error;

View file

@ -9,6 +9,10 @@
#include <linux/platform_device.h>
#include <linux/pstore_ram.h>
static int ecc_size;
module_param(ecc_size, int, 0400);
MODULE_PARM_DESC(ecc_size, "ECC parity data size in bytes. A positive value enables ECC for the ramoops region.");
static const struct dmi_system_id chromeos_pstore_dmi_table[] __initconst = {
{
/*
@ -117,6 +121,9 @@ static int __init chromeos_pstore_init(void)
{
bool acpi_dev_found;
if (ecc_size > 0)
chromeos_ramoops_data.ecc_info.ecc_size = ecc_size;
/* First check ACPI for non-hardcoded values from firmware. */
acpi_dev_found = chromeos_check_acpi();

View file

@ -318,6 +318,9 @@ EXPORT_SYMBOL(cros_ec_register);
*/
void cros_ec_unregister(struct cros_ec_device *ec_dev)
{
if (ec_dev->mkbp_event_supported)
blocking_notifier_chain_unregister(&ec_dev->event_notifier,
&ec_dev->notifier_ready);
platform_device_unregister(ec_dev->pd);
platform_device_unregister(ec_dev->ec);
mutex_destroy(&ec_dev->lock);

View file

@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_data/cros_ec_commands.h>
@ -18,6 +19,7 @@
#include <linux/types.h>
#define DRV_NAME "cros-ec-sensorhub"
#define CROS_EC_CMD_INFO_RETRIES 50
static void cros_ec_sensorhub_free_sensor(void *arg)
{
@ -53,7 +55,7 @@ static int cros_ec_sensorhub_register(struct device *dev,
int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
struct cros_ec_command *msg = sensorhub->msg;
struct cros_ec_dev *ec = sensorhub->ec;
int ret, i;
int ret, i, retries;
char *name;
@ -65,12 +67,25 @@ static int cros_ec_sensorhub_register(struct device *dev,
sensorhub->params->cmd = MOTIONSENSE_CMD_INFO;
sensorhub->params->info.sensor_num = i;
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
retries = CROS_EC_CMD_INFO_RETRIES;
do {
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret == -EBUSY) {
/* The EC is still busy initializing sensors. */
usleep_range(5000, 6000);
retries--;
}
} while (ret == -EBUSY && retries);
if (ret < 0) {
dev_warn(dev, "no info for EC sensor %d : %d/%d\n",
i, ret, msg->result);
dev_err(dev, "no info for EC sensor %d : %d/%d\n",
i, ret, msg->result);
continue;
}
if (retries < CROS_EC_CMD_INFO_RETRIES) {
dev_warn(dev, "%d retries needed to bring up sensor %d\n",
CROS_EC_CMD_INFO_RETRIES - retries, i);
}
switch (sensorhub->resp->info.type) {
case MOTIONSENSE_TYPE_ACCEL:

View file

@ -58,8 +58,91 @@ static int cros_typec_enter_usb_mode(struct typec_port *tc_port, enum usb_mode m
&req, sizeof(req), NULL, 0);
}
static int cros_typec_perform_role_swap(struct typec_port *tc_port, int target_role, u8 swap_type)
{
struct cros_typec_port *port = typec_get_drvdata(tc_port);
struct cros_typec_data *data = port->typec_data;
struct ec_response_usb_pd_control_v2 resp;
struct ec_params_usb_pd_control req;
int role, ret;
/* Must be at least v1 to support role swap. */
if (!data->pd_ctrl_ver)
return -EOPNOTSUPP;
/* First query the state */
req.port = port->port_num;
req.role = USB_PD_CTRL_ROLE_NO_CHANGE;
req.mux = USB_PD_CTRL_MUX_NO_CHANGE;
req.swap = USB_PD_CTRL_SWAP_NONE;
ret = cros_ec_cmd(data->ec, data->pd_ctrl_ver, EC_CMD_USB_PD_CONTROL,
&req, sizeof(req), &resp, sizeof(resp));
if (ret < 0)
return ret;
switch (swap_type) {
case USB_PD_CTRL_SWAP_DATA:
role = (resp.role & PD_CTRL_RESP_ROLE_DATA) ? TYPEC_HOST :
TYPEC_DEVICE;
break;
case USB_PD_CTRL_SWAP_POWER:
role = (resp.role & PD_CTRL_RESP_ROLE_POWER) ? TYPEC_SOURCE :
TYPEC_SINK;
break;
default:
dev_warn(data->dev, "Unsupported role swap type %d\n", swap_type);
return -EOPNOTSUPP;
}
if (role == target_role)
return 0;
req.swap = swap_type;
ret = cros_ec_cmd(data->ec, data->pd_ctrl_ver, EC_CMD_USB_PD_CONTROL,
&req, sizeof(req), &resp, sizeof(resp));
if (ret < 0)
return ret;
switch (swap_type) {
case USB_PD_CTRL_SWAP_DATA:
role = resp.role & PD_CTRL_RESP_ROLE_DATA ? TYPEC_HOST : TYPEC_DEVICE;
if (role != target_role) {
dev_err(data->dev, "Data role swap failed despite EC returning success\n");
return -EIO;
}
typec_set_data_role(tc_port, target_role);
break;
case USB_PD_CTRL_SWAP_POWER:
role = resp.role & PD_CTRL_RESP_ROLE_POWER ? TYPEC_SOURCE : TYPEC_SINK;
if (role != target_role) {
dev_err(data->dev, "Power role swap failed despite EC returning success\n");
return -EIO;
}
typec_set_pwr_role(tc_port, target_role);
break;
default:
/* Should never execute */
break;
}
return 0;
}
static int cros_typec_dr_swap(struct typec_port *port, enum typec_data_role role)
{
return cros_typec_perform_role_swap(port, role, USB_PD_CTRL_SWAP_DATA);
}
static int cros_typec_pr_swap(struct typec_port *port, enum typec_role role)
{
return cros_typec_perform_role_swap(port, role, USB_PD_CTRL_SWAP_POWER);
}
static const struct typec_operations cros_typec_usb_mode_ops = {
.enter_usb_mode = cros_typec_enter_usb_mode
.enter_usb_mode = cros_typec_enter_usb_mode,
.dr_set = cros_typec_dr_swap,
.pr_set = cros_typec_pr_swap,
};
static int cros_typec_parse_port_props(struct typec_capability *cap,
@ -1271,9 +1354,9 @@ static int cros_typec_probe(struct platform_device *pdev)
typec->dev = dev;
typec->ec = dev_get_drvdata(pdev->dev.parent);
if (!typec->ec) {
dev_err(dev, "couldn't find parent EC device\n");
return -ENODEV;
if (!typec->ec || !typec->ec->ec) {
dev_warn(dev, "couldn't find parent EC device\n");
return -EPROBE_DEFER;
}
platform_set_drvdata(pdev, typec);