Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp3747890ybb; Mon, 23 Mar 2020 07:01:13 -0700 (PDT) X-Google-Smtp-Source: ADFU+vtWX/l2xdLCdOabXqGoOmplgO8EkKhGxCsGIQCy1fcrx2Ybb5Jcs0s6CbbZJ84UCzK1y/81 X-Received: by 2002:a9d:6c58:: with SMTP id g24mr17521363otq.106.1584972072964; Mon, 23 Mar 2020 07:01:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584972072; cv=none; d=google.com; s=arc-20160816; b=qUy7oHgFwewWTFU01AyGO6NELPb5Xf9PZfo8ZFmRTAcIyfRdnfcuuFYozhLt0SJBpT M1ftNfwvri7tlN8OqDtBZCFnTdjjguhQl9bgQOlJeI7fBghlS4QoUkmPpbaOGn2Z+mo1 OpINVYyLIkPSNNzOUr/cmHYiS9oTqQXl0wAfWA8msPTrbqnGyEs13evgPJ87W0jGkyyI dnwTXeqhwhG1VPBvjq20VysIDO1BUaUEsRXDzmaQwUf8oXVtxvpuWbjkoWu2TDrUfyhc wfGi48vtqIQcWyqGmTpYDttSttxFQl4bhwY7WaC+OfW7F3QtF2OxbgT8RqwsFoY4S8vS shHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject; bh=LkXrXB5kMvFPFmwq9xTyWXiLK+OLHNreVZhhWPacuS8=; b=N3NEJsi3t+DCwl35lIC+YhvXa+taAKLdg0PaDr73IVj9W9W8fM1z2AOQvpa/4Jnf7e vopZnWsxmJAqCaytwB4+w099l55/Bmpi/QpjYPdyBHcwWk0MXAh0xIoODDNTc2munMWJ hzPC+l8fmA65EClGMPLlPfE5fM6APatLNYRi3tP7vyHeC2AXRfPQfLkCKQKgy56r98YR X2HVRKeSzF3wqANDxbdKXJePGwYu4G3xGXgBcP2O6biaCVl/soHl92TD8ML3E4gok1Zi kZhYz1sa486Uvgg9/kaERlsoBVL9wvaoJG0G1fG5+Q5UaP81rLWvxLs8GQDpOfDH6S90 AiYA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e24si7663783oti.10.2020.03.23.07.00.49; Mon, 23 Mar 2020 07:01:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728564AbgCWOAZ (ORCPT + 99 others); Mon, 23 Mar 2020 10:00:25 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:36350 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728446AbgCWOAZ (ORCPT ); Mon, 23 Mar 2020 10:00:25 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: eballetbo) with ESMTPSA id 15C09296394 Subject: Re: [PATCH v5 2/4] platform/chrome: Add Type C connector class driver To: Benson Leung , Prashant Malani Cc: linux-kernel@vger.kernel.org, Heikki Krogerus , Benson Leung , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , Guenter Roeck , Mark Rutland , Rob Herring References: <20200316090021.52148-1-pmalani@chromium.org> <20200316090021.52148-3-pmalani@chromium.org> <20200318174302.GA137510@google.com> From: Enric Balletbo i Serra Message-ID: Date: Mon, 23 Mar 2020 15:00:20 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: <20200318174302.GA137510@google.com> Content-Type: text/plain; charset=windows-1252 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Prashant and Benson, On 18/3/20 18:43, Benson Leung wrote: > Hi Prashant, > > On Mon, Mar 16, 2020 at 02:00:17AM -0700, Prashant Malani wrote: >> Add a driver to implement the Type C connector class for Chrome OS >> devices with ECs (Embedded Controllers). >> >> The driver relies on firmware device specifications for various port >> attributes. On ACPI platforms, this is specified using the logical >> device with HID GOOG0014. On DT platforms, this is specified using the >> DT node with compatible string "google,cros-ec-typec". >> >> The driver reads the device FW node and uses the port attributes to >> register the typec ports with the Type C connector class framework, but >> doesn't do much else. >> >> Subsequent patches will add more functionality to the driver, including >> obtaining current port information (polarity, vconn role, current power >> role etc.) after querying the EC. >> >> Signed-off-by: Prashant Malani >> Reviewed-by: Heikki Krogerus > > Thanks for posting this. For my bit: > Co-developed-by: Benson Leung > Squashed 3 and 4 and queued together with 2 for 5.7. Patch 1 will go through the Rob's tree. Thanks, Enric >> --- >> >> Changes in v5: >> - Added Reviewed-by tag which was missed in earlier version. >> >> Changes in v4: >> - Added Reviewed-by tag from previous review cycle >> - Added code to store port caps within the Cros EC type C data structure >> - Added code to use reg to get the port-number in DT platforms. >> >> Changes in v3: >> - Fixed minor spacing nits, and moved a modification to probe() if check >> from later patch to here instead. >> >> Changes in v2: >> - Updated Kconfig to default to MFD_CROS_EC_DEV. >> - Fixed code comments. >> - Moved get_num_ports() code into probe(). >> - Added module author. >> >> drivers/platform/chrome/Kconfig | 11 ++ >> drivers/platform/chrome/Makefile | 1 + >> drivers/platform/chrome/cros_ec_typec.c | 238 ++++++++++++++++++++++++ >> 3 files changed, 250 insertions(+) >> create mode 100644 drivers/platform/chrome/cros_ec_typec.c >> >> diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig >> index 5f57282a28da0..2320a4f0d9301 100644 >> --- a/drivers/platform/chrome/Kconfig >> +++ b/drivers/platform/chrome/Kconfig >> @@ -214,6 +214,17 @@ config CROS_EC_SYSFS >> To compile this driver as a module, choose M here: the >> module will be called cros_ec_sysfs. >> >> +config CROS_EC_TYPEC >> + tristate "ChromeOS EC Type-C Connector Control" >> + depends on MFD_CROS_EC_DEV && TYPEC >> + default MFD_CROS_EC_DEV >> + help >> + If you say Y here, you get support for accessing Type C connector >> + information from the Chrome OS EC. >> + >> + To compile this driver as a module, choose M here: the module will be >> + called cros_ec_typec. >> + >> config CROS_USBPD_LOGGER >> tristate "Logging driver for USB PD charger" >> depends on CHARGER_CROS_USBPD >> diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile >> index aacd5920d8a18..caf2a9cdb5e6d 100644 >> --- a/drivers/platform/chrome/Makefile >> +++ b/drivers/platform/chrome/Makefile >> @@ -12,6 +12,7 @@ obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o >> obj-$(CONFIG_CROS_EC_RPMSG) += cros_ec_rpmsg.o >> obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o >> cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_mec.o >> +obj-$(CONFIG_CROS_EC_TYPEC) += cros_ec_typec.o >> obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o >> obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o >> obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o >> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c >> new file mode 100644 >> index 0000000000000..02e6d5cbbbf7a >> --- /dev/null >> +++ b/drivers/platform/chrome/cros_ec_typec.c >> @@ -0,0 +1,238 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * Copyright 2020 Google LLC >> + * >> + * This driver provides the ability to view and manage Type C ports through the >> + * Chrome OS EC. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define DRV_NAME "cros-ec-typec" >> + >> +/* Platform-specific data for the Chrome OS EC Type C controller. */ >> +struct cros_typec_data { >> + struct device *dev; >> + struct cros_ec_device *ec; >> + int num_ports; >> + /* Array of ports, indexed by port number. */ >> + struct typec_port *ports[EC_USB_PD_MAX_PORTS]; >> + /* Initial capabilities for each port. */ >> + struct typec_capability *caps[EC_USB_PD_MAX_PORTS]; >> +}; >> + >> +static int cros_typec_parse_port_props(struct typec_capability *cap, >> + struct fwnode_handle *fwnode, >> + struct device *dev) >> +{ >> + const char *buf; >> + int ret; >> + >> + memset(cap, 0, sizeof(*cap)); >> + ret = fwnode_property_read_string(fwnode, "power-role", &buf); >> + if (ret) { >> + dev_err(dev, "power-role not found: %d\n", ret); >> + return ret; >> + } >> + >> + ret = typec_find_port_power_role(buf); >> + if (ret < 0) >> + return ret; >> + cap->type = ret; >> + >> + ret = fwnode_property_read_string(fwnode, "data-role", &buf); >> + if (ret) { >> + dev_err(dev, "data-role not found: %d\n", ret); >> + return ret; >> + } >> + >> + ret = typec_find_port_data_role(buf); >> + if (ret < 0) >> + return ret; >> + cap->data = ret; >> + >> + ret = fwnode_property_read_string(fwnode, "try-power-role", &buf); >> + if (ret) { >> + dev_err(dev, "try-power-role not found: %d\n", ret); >> + return ret; >> + } >> + >> + ret = typec_find_power_role(buf); >> + if (ret < 0) >> + return ret; >> + cap->prefer_role = ret; >> + >> + cap->fwnode = fwnode; >> + >> + return 0; >> +} >> + >> +static int cros_typec_init_ports(struct cros_typec_data *typec) >> +{ >> + struct device *dev = typec->dev; >> + struct typec_capability *cap; >> + struct fwnode_handle *fwnode; >> + const char *port_prop; >> + int ret; >> + int i; >> + int nports; >> + u32 port_num = 0; >> + >> + nports = device_get_child_node_count(dev); >> + if (nports == 0) { >> + dev_err(dev, "No port entries found.\n"); >> + return -ENODEV; >> + } >> + >> + if (nports > typec->num_ports) { >> + dev_err(dev, "More ports listed than can be supported.\n"); >> + return -EINVAL; >> + } >> + >> + /* DT uses "reg" to specify port number. */ >> + port_prop = dev->of_node ? "reg" : "port-number"; >> + device_for_each_child_node(dev, fwnode) { >> + if (fwnode_property_read_u32(fwnode, port_prop, &port_num)) { >> + ret = -EINVAL; >> + dev_err(dev, "No port-number for port, aborting.\n"); >> + goto unregister_ports; >> + } >> + >> + if (port_num >= typec->num_ports) { >> + dev_err(dev, "Invalid port number.\n"); >> + ret = -EINVAL; >> + goto unregister_ports; >> + } >> + >> + dev_dbg(dev, "Registering port %d\n", port_num); >> + >> + cap = devm_kzalloc(dev, sizeof(*cap), GFP_KERNEL); >> + if (!cap) { >> + ret = -ENOMEM; >> + goto unregister_ports; >> + } >> + >> + typec->caps[port_num] = cap; >> + >> + ret = cros_typec_parse_port_props(cap, fwnode, dev); >> + if (ret < 0) >> + goto unregister_ports; >> + >> + typec->ports[port_num] = typec_register_port(dev, cap); >> + if (IS_ERR(typec->ports[port_num])) { >> + dev_err(dev, "Failed to register port %d\n", port_num); >> + ret = PTR_ERR(typec->ports[port_num]); >> + goto unregister_ports; >> + } >> + } >> + >> + return 0; >> + >> +unregister_ports: >> + for (i = 0; i < typec->num_ports; i++) >> + typec_unregister_port(typec->ports[i]); >> + return ret; >> +} >> + >> +static int cros_typec_ec_command(struct cros_typec_data *typec, >> + unsigned int version, >> + unsigned int command, >> + void *outdata, >> + unsigned int outsize, >> + void *indata, >> + unsigned int insize) >> +{ >> + struct cros_ec_command *msg; >> + int ret; >> + >> + msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL); >> + if (!msg) >> + return -ENOMEM; >> + >> + msg->version = version; >> + msg->command = command; >> + msg->outsize = outsize; >> + msg->insize = insize; >> + >> + if (outsize) >> + memcpy(msg->data, outdata, outsize); >> + >> + ret = cros_ec_cmd_xfer_status(typec->ec, msg); >> + if (ret >= 0 && insize) >> + memcpy(indata, msg->data, insize); >> + >> + kfree(msg); >> + return ret; >> +} >> + >> +#ifdef CONFIG_ACPI >> +static const struct acpi_device_id cros_typec_acpi_id[] = { >> + { "GOOG0014", 0 }, >> + {} >> +}; >> +MODULE_DEVICE_TABLE(acpi, cros_typec_acpi_id); >> +#endif >> + >> +#ifdef CONFIG_OF >> +static const struct of_device_id cros_typec_of_match[] = { >> + { .compatible = "google,cros-ec-typec", }, >> + {} >> +}; >> +MODULE_DEVICE_TABLE(of, cros_typec_of_match); >> +#endif >> + >> +static int cros_typec_probe(struct platform_device *pdev) >> +{ >> + struct device *dev = &pdev->dev; >> + struct cros_typec_data *typec; >> + struct ec_response_usb_pd_ports resp; >> + int ret; >> + >> + typec = devm_kzalloc(dev, sizeof(*typec), GFP_KERNEL); >> + if (!typec) >> + return -ENOMEM; >> + >> + typec->dev = dev; >> + typec->ec = dev_get_drvdata(pdev->dev.parent); >> + platform_set_drvdata(pdev, typec); >> + >> + ret = cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_PORTS, NULL, 0, >> + &resp, sizeof(resp)); >> + if (ret < 0) >> + return ret; >> + >> + typec->num_ports = resp.num_ports; >> + if (typec->num_ports > EC_USB_PD_MAX_PORTS) { >> + dev_warn(typec->dev, >> + "Too many ports reported: %d, limiting to max: %d\n", >> + typec->num_ports, EC_USB_PD_MAX_PORTS); >> + typec->num_ports = EC_USB_PD_MAX_PORTS; >> + } >> + >> + ret = cros_typec_init_ports(typec); >> + if (ret < 0) >> + return ret; >> + >> + return 0; >> +} >> + >> +static struct platform_driver cros_typec_driver = { >> + .driver = { >> + .name = DRV_NAME, >> + .acpi_match_table = ACPI_PTR(cros_typec_acpi_id), >> + .of_match_table = of_match_ptr(cros_typec_of_match), >> + }, >> + .probe = cros_typec_probe, >> +}; >> + >> +module_platform_driver(cros_typec_driver); >> + >> +MODULE_AUTHOR("Prashant Malani "); >> +MODULE_DESCRIPTION("Chrome OS EC Type C control"); >> +MODULE_LICENSE("GPL"); >> -- >> 2.25.1.481.gfbce0eb801-goog >> >