diff options
Diffstat (limited to 'drivers/platform/chrome')
-rw-r--r-- | drivers/platform/chrome/cros_ec_lpc.c | 22 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_sysfs.c | 71 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_typec.c | 28 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_typec.h | 1 |
4 files changed, 114 insertions, 8 deletions
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 5a2f1d98b350..be319949b941 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -30,6 +30,7 @@ #define DRV_NAME "cros_ec_lpcs" #define ACPI_DRV_NAME "GOOG0004" +#define FRMW_ACPI_DRV_NAME "FRMWC004" /* True if ACPI device is present */ static bool cros_ec_lpc_acpi_device_found; @@ -514,7 +515,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) acpi_status status; struct cros_ec_device *ec_dev; struct cros_ec_lpc *ec_lpc; - struct lpc_driver_data *driver_data; + const struct lpc_driver_data *driver_data; u8 buf[2] = {}; int irq, ret; u32 quirks; @@ -526,6 +527,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) ec_lpc->mmio_memory_base = EC_LPC_ADDR_MEMMAP; driver_data = platform_get_drvdata(pdev); + if (!driver_data) + driver_data = acpi_device_get_match_data(dev); + if (driver_data) { quirks = driver_data->quirks; @@ -696,12 +700,6 @@ static void cros_ec_lpc_remove(struct platform_device *pdev) cros_ec_unregister(ec_dev); } -static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = { - { ACPI_DRV_NAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids); - static const struct lpc_driver_data framework_laptop_npcx_lpc_driver_data __initconst = { .quirks = CROS_EC_LPC_QUIRK_REMAP_MEMORY, .quirk_mmio_memory_base = 0xE00, @@ -713,6 +711,13 @@ static const struct lpc_driver_data framework_laptop_mec_lpc_driver_data __initc .quirk_aml_mutex_name = "ECMT", }; +static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = { + { ACPI_DRV_NAME, 0 }, + { FRMW_ACPI_DRV_NAME, (kernel_ulong_t)&framework_laptop_npcx_lpc_driver_data }, + { } +}; +MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids); + static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = { { /* @@ -866,7 +871,8 @@ static int __init cros_ec_lpc_init(void) int ret; const struct dmi_system_id *dmi_match; - cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME); + cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME) || + !!cros_ec_lpc_get_device(FRMW_ACPI_DRV_NAME); dmi_match = dmi_first_match(cros_ec_lpc_dmi_table); diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index bc1a5ba09528..f22e9523da3e 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -296,18 +296,81 @@ static ssize_t kb_wake_angle_store(struct device *dev, return count; } +static ssize_t usbpdmuxinfo_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + ssize_t count = 0; + struct ec_response_usb_pd_ports resp_pd_ports; + int ret; + int i; + + ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_USB_PD_PORTS, NULL, 0, + &resp_pd_ports, sizeof(resp_pd_ports)); + if (ret < 0) + return -EIO; + + for (i = 0; i < resp_pd_ports.num_ports; i++) { + struct ec_response_usb_pd_mux_info resp_mux; + struct ec_params_usb_pd_mux_info req = { + .port = i, + }; + + ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_USB_PD_MUX_INFO, + &req, sizeof(req), &resp_mux, sizeof(resp_mux)); + + if (ret >= 0) { + count += sysfs_emit_at(buf, count, "Port %d:", i); + count += sysfs_emit_at(buf, count, " USB=%d", + !!(resp_mux.flags & USB_PD_MUX_USB_ENABLED)); + count += sysfs_emit_at(buf, count, " DP=%d", + !!(resp_mux.flags & USB_PD_MUX_DP_ENABLED)); + count += sysfs_emit_at(buf, count, " POLARITY=%s", + (resp_mux.flags & USB_PD_MUX_POLARITY_INVERTED) ? + "INVERTED" : "NORMAL"); + count += sysfs_emit_at(buf, count, " HPD_IRQ=%d", + !!(resp_mux.flags & USB_PD_MUX_HPD_IRQ)); + count += sysfs_emit_at(buf, count, " HPD_LVL=%d", + !!(resp_mux.flags & USB_PD_MUX_HPD_LVL)); + count += sysfs_emit_at(buf, count, " SAFE=%d", + !!(resp_mux.flags & USB_PD_MUX_SAFE_MODE)); + count += sysfs_emit_at(buf, count, " TBT=%d", + !!(resp_mux.flags & USB_PD_MUX_TBT_COMPAT_ENABLED)); + count += sysfs_emit_at(buf, count, " USB4=%d\n", + !!(resp_mux.flags & USB_PD_MUX_USB4_ENABLED)); + } + } + + return count ? : -EIO; +} + +static ssize_t ap_mode_entry_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + const bool ap_driven_altmode = cros_ec_check_features( + ec, EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY); + + return sysfs_emit(buf, "%s\n", ap_driven_altmode ? "yes" : "no"); +} + /* Module initialization */ static DEVICE_ATTR_RW(reboot); static DEVICE_ATTR_RO(version); static DEVICE_ATTR_RO(flashinfo); static DEVICE_ATTR_RW(kb_wake_angle); +static DEVICE_ATTR_RO(usbpdmuxinfo); +static DEVICE_ATTR_RO(ap_mode_entry); static struct attribute *__ec_attrs[] = { &dev_attr_kb_wake_angle.attr, &dev_attr_reboot.attr, &dev_attr_version.attr, &dev_attr_flashinfo.attr, + &dev_attr_usbpdmuxinfo.attr, + &dev_attr_ap_mode_entry.attr, NULL, }; @@ -320,6 +383,14 @@ static umode_t cros_ec_ctrl_visible(struct kobject *kobj, if (a == &dev_attr_kb_wake_angle.attr && !ec->has_kb_wake_angle) return 0; + if (a == &dev_attr_usbpdmuxinfo.attr || + a == &dev_attr_ap_mode_entry.attr) { + struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); + + if (strcmp(ec_platform->ec_name, CROS_EC_DEV_NAME)) + return 0; + } + return a->mode; } diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 6ee182101bc9..d2228720991f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -42,6 +42,24 @@ static void cros_typec_role_switch_quirk(struct fwnode_handle *fwnode) #endif } +static int cros_typec_enter_usb_mode(struct typec_port *tc_port, enum usb_mode mode) +{ + struct cros_typec_port *port = typec_get_drvdata(tc_port); + struct ec_params_typec_control req = { + .port = port->port_num, + .command = (mode == USB_MODE_USB4) ? + TYPEC_CONTROL_COMMAND_ENTER_MODE : TYPEC_CONTROL_COMMAND_EXIT_MODES, + .mode_to_enter = CROS_EC_ALTMODE_USB4 + }; + + return cros_ec_cmd(port->typec_data->ec, 0, EC_CMD_TYPEC_CONTROL, + &req, sizeof(req), NULL, 0); +} + +static const struct typec_operations cros_typec_usb_mode_ops = { + .enter_usb_mode = cros_typec_enter_usb_mode +}; + static int cros_typec_parse_port_props(struct typec_capability *cap, struct fwnode_handle *fwnode, struct device *dev) @@ -84,6 +102,13 @@ static int cros_typec_parse_port_props(struct typec_capability *cap, cap->prefer_role = ret; } + if (fwnode_property_present(fwnode, "usb2-port")) + cap->usb_capability |= USB_CAPABILITY_USB2; + if (fwnode_property_present(fwnode, "usb3-port")) + cap->usb_capability |= USB_CAPABILITY_USB3; + if (fwnode_property_present(fwnode, "usb4-port")) + cap->usb_capability |= USB_CAPABILITY_USB4; + cros_typec_role_switch_quirk(fwnode); cap->fwnode = fwnode; @@ -379,6 +404,9 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) if (ret < 0) goto unregister_ports; + cap->driver_data = cros_port; + cap->ops = &cros_typec_usb_mode_ops; + cros_port->port = typec_register_port(dev, cap); if (IS_ERR(cros_port->port)) { ret = PTR_ERR(cros_port->port); diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h index 9fd5342bb0ad..f9c31f04c102 100644 --- a/drivers/platform/chrome/cros_ec_typec.h +++ b/drivers/platform/chrome/cros_ec_typec.h @@ -18,6 +18,7 @@ enum { CROS_EC_ALTMODE_DP = 0, CROS_EC_ALTMODE_TBT, + CROS_EC_ALTMODE_USB4, CROS_EC_ALTMODE_MAX, }; |