From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Cyrus-Session-Id: sloti22d1t05-1269041-1524492822-2-2835673077344067626 X-Sieve: CMU Sieve 3.0 X-Spam-known-sender: no ("Email failed DMARC policy for domain") X-Spam-score: 0.0 X-Spam-hits: BAYES_00 -1.9, FROM_WORDY 2.5, HEADER_FROM_DIFFERENT_DOMAINS 0.25, MAILING_LIST_MULTI -1, ME_NOAUTH 0.01, RCVD_IN_DNSWL_HI -5, LANGUAGES enro, BAYES_USED global, SA_VERSION 3.4.0 X-Spam-source: IP='209.132.180.67', Host='vger.kernel.org', Country='US', FromHeader='com', MailFrom='org', XOriginatingCountry='GB' X-Spam-charsets: X-IgnoreVacation: yes ("Email failed DMARC policy for domain") X-Resolved-to: greg@kroah.com X-Delivered-to: greg@kroah.com X-Mail-from: linux-usb-owner@vger.kernel.org ARC-Seal: i=1; a=rsa-sha256; cv=none; d=messagingengine.com; s=fm2; t= 1524492820; b=PbB+yHi5KAGud+Q1CcBTdN47jXzvLoFVyby2HXz//ox4b/YxZb KH7Tp/m6VZAX1nmuKwx2E4C1zHahqdoEpQcgZIVrvL91JYn6XLTbzhQy1ZpvzsbY /X9s7DPvrFzMU1JmXlORMjyx5Tc1B5M0AhX2hVgfU7SkxxHyxF3x8cKTaRr+vTIU LuiUOsz7B2q3CenatuStebBNKP67E8tXJts6eryjHju5D/aRVUHonSQIRXUt4lgv 6uoEwgLxkCkYiGJi7d8J6DqDzA30NjRSyAVbF0V/cNXXNuqvACWNTLUMwZWVSxIA KdkGZ8X4UwWdVmtLSc8ANI/A42MNLePTiXug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=message-id:in-reply-to:references:from :date:subject:to:cc:mime-version:content-type:sender:list-id; s= fm2; t=1524492820; bh=wiZdDXtar9rzjGhTT/l85Zdmn8P0vfQFbQvNcaf1Z7 Q=; b=ev5IHWISOT55Zu6k7pXnMTBGf0th01RiffpK9Wr9wWBFxU2ZkG18QIb3FP 6DbeoHvCo4kWvn7TNKY6w0OPVZNwTL6Gk/u023GU1UGz+gCd/SP4rPfpgEo6QyDg 8mRjcXQIItRaxiu2c3ZotFDmFYdLyTUQb3ttTMIiXZvB/RdMDE219cCRH6JJOEVz RqWSSukKwXbH+hVEbrQ5l/gDRElhhcFimzffIlM069h4fjq4UaJE2+0rqm8gvZ7O 5wOT/yp+BGzrdDPpasjRcQKiRG+BON/1emfJmTr1QOAELx8yA/qUw0IULnn1Iam2 5cK2JONNYz0G/oHTVE2CTGvUL/RQ== ARC-Authentication-Results: i=1; mx4.messagingengine.com; arc=none (no signatures found); dkim=none (no signatures found); dmarc=fail (p=none,has-list-id=yes,d=none) header.from=diasemi.com; iprev=pass policy.iprev=209.132.180.67 (vger.kernel.org); spf=none smtp.mailfrom=linux-usb-owner@vger.kernel.org smtp.helo=vger.kernel.org; x-aligned-from=fail; x-cm=none score=0; x-ptr=pass x-ptr-helo=vger.kernel.org x-ptr-lookup=vger.kernel.org; x-return-mx=pass smtp.domain=vger.kernel.org smtp.result=pass smtp_org.domain=kernel.org smtp_org.result=pass smtp_is_org_domain=no header.domain=diasemi.com header.result=pass header_is_org_domain=yes; x-vs=clean score=-100 state=0 Authentication-Results: mx4.messagingengine.com; arc=none (no signatures found); dkim=none (no signatures found); dmarc=fail (p=none,has-list-id=yes,d=none) header.from=diasemi.com; iprev=pass policy.iprev=209.132.180.67 (vger.kernel.org); spf=none smtp.mailfrom=linux-usb-owner@vger.kernel.org smtp.helo=vger.kernel.org; x-aligned-from=fail; x-cm=none score=0; x-ptr=pass x-ptr-helo=vger.kernel.org x-ptr-lookup=vger.kernel.org; x-return-mx=pass smtp.domain=vger.kernel.org smtp.result=pass smtp_org.domain=kernel.org smtp_org.result=pass smtp_is_org_domain=no header.domain=diasemi.com header.result=pass header_is_org_domain=yes; x-vs=clean score=-100 state=0 X-ME-VSCategory: clean X-CM-Envelope: MS4wfOYhZBPcN3V4hV1FDYx5X97JOzmChc6Gy7RDEgf/Ir+v53WQM0pgVg1YJVCt0qxs09cw1Rg7DbjX9ubexgDepXHpNDtkpaI0Q1ewYB+07V9dATvh8Kkf KIH1IFZ8h3xCKTmasXvJxzbFzEaFZu2qw0McifApuGs2T04gv2IBhLLLKjVMFQS15GPPJPfhbjr285CKVoGP6nke8ustNGGi1tAairB/w+7UOY9KRlbP+8Cv X-CM-Analysis: v=2.3 cv=JLoVTfCb c=1 sm=1 tr=0 a=UK1r566ZdBxH71SXbqIOeA==:117 a=UK1r566ZdBxH71SXbqIOeA==:17 a=QRjQRLzp78EA:10 a=Kd1tUaAdevIA:10 a=X3a0BiUdAAAA:8 a=_jlGtV7tAAAA:8 a=VwQbUJbxAAAA:8 a=I19jlynAXRwjjud8xtwA:9 a=t1kEl2L6EXVecZ7_:21 a=fkqapZOYkiAfHoL-:21 a=x8gzFH9gYPwA:10 a=aWu3muFgq6otJbhCXpL5:22 a=nlm17XC03S6CtCLSeiRr:22 a=AjGcO6oz07-iQ99wixmX:22 X-ME-CMScore: 0 X-ME-CMCategory: none Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755520AbeDWOLK (ORCPT ); Mon, 23 Apr 2018 10:11:10 -0400 Received: from mail1.bemta26.messagelabs.com ([85.158.142.113]:26345 "EHLO mail1.bemta26.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755419AbeDWOLD (ORCPT ); Mon, 23 Apr 2018 10:11:03 -0400 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupkleJIrShJLcpLzFFi42KJ27nUWLf05d0 ogwldHBbNi9ezWbw5Pp3Jomv1ThaLa8d6mSwu75rDZvG59wijxaJlrcwWTxaeYbI4vbvEgdNj 06pONo95JwM99s9dw+6x8d0OJo/3+66yeez83sDu8XmTXAB7FGtmXlJ+RQJrxukp59kLZhdUX Hi/kq2BsTG+i5GLQ0hgPaPEsiWnmboYOYCcComJZ4W7GDk5eAUyJRrvvGEGsTkF3CW6J31kA7 GFBNwkLre9YQSx2QQsJCafeAAWZxFQlVjeeA6sXlggUOLywvcsIPNFBN4zSnx6/IEFJMEsUCf R+/stC8QCQYmTM59AxSUkDr54wQyxwEDi9IJGsLiEgL3E9PdXmUFukxDQl2g8FgsRNpT4Pusb VIm5xP3DXWwTGAVnIZk6C8nUBYxMqxgtk4oy0zNKchMzc3QNDQx0DQ2NdU11DS0M9BKrdJP0U kt1k1PzSooSgbJ6ieXFesWVuck5KXp5qSWbGIFRxAAEOxinHUo8xCjJwaQkymt5/m6UEF9Sfk plRmJxRnxRaU5q8SFGGQ4OJQneTS+AcoJFqempFWmZOcB4hklLcPAoifDGgaR5iwsSc4sz0yF SpxgVpcR5N4MkBEASGaV5cG2wFHKJUVZKmJcR6BAhnoLUotzMElT5V4ziHIxKwhBTeDLzSuCm vwJazAS0uEPyDsjikkSElFQDY5yMepHko7WNdz7dX7V+5YWr+SGJV3sebVpgY8WXIONRYXXvz /3DS2qOuzbOqdwgH8FhaxVzKC/tzYSSr5oP3S7ICT080ShxkrHjf4pByEfW9y4r9S0X1//LeC znx2bwe8PbR17qzhp35Oa8+OPaauTfukZ4ukPIa7drnNOfRz/Nr86dk9n0S4mlOCPRUIu5qDg RAFStczgcAwAA X-Env-Sender: Adam.Thomson.Opensource@diasemi.com X-Msg-Ref: server-37.tower-246.messagelabs.com!1524492660!1328244!1 X-Originating-IP: [94.185.165.51] X-SYMC-ESS-Client-Auth: outbound-route-from=pass X-StarScan-Received: X-StarScan-Version: 9.9.15; banners=-,-,- X-VirusChecked: Checked Message-ID: In-Reply-To: References: From: Adam Thomson Date: Mon, 23 Apr 2018 15:11:00 +0100 Subject: [PATCH v8 5/6] typec: tcpm: Represent source supply through power_supply To: Heikki Krogerus , Guenter Roeck , Greg Kroah-Hartman , Sebastian Reichel , Hans de Goede , Jun Li CC: , , , MIME-Version: 1.0 Content-Type: text/plain X-KSE-AttachmentFiltering-Interceptor-Info: protection disabled X-KSE-ServerInfo: sw-ex-cashub01.diasemi.com, 9 X-KSE-Antivirus-Interceptor-Info: scan successful X-KSE-Antivirus-Info: Clean, bases: 23/04/2018 11:44:00 Sender: linux-usb-owner@vger.kernel.org X-Mailing-List: linux-usb@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-Mailing-List: linux-kernel@vger.kernel.org List-ID: This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +-------- drivers/usb/typec/tcpm.c | 251 +++++++++++++++++++++++++++++++++++- 4 files changed, 251 insertions(+), 66 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 030f88c..2c8eab1 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -49,6 +49,7 @@ config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB select USB_ROLE_SWITCH + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 664463d..eba6bb8 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -99,11 +98,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -862,13 +856,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -884,11 +876,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1682,43 +1669,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get_property = fusb302_psy_get_property, -}; - static int init_gpio(struct fusb302_chip *chip) { struct device_node *node; @@ -1781,7 +1731,6 @@ static int fusb302_probe(struct i2c_client *client, struct fusb302_chip *chip; struct i2c_adapter *adapter; struct device *dev = &client->dev; - struct power_supply_config cfg = {}; const char *name; int ret = 0; u32 v; @@ -1823,14 +1772,6 @@ static int fusb302_probe(struct i2c_client *client, return -EPROBE_DEFER; } - cfg.drv_data = chip; - chip->psy = devm_power_supply_register(dev, &fusb302_psy_desc, &cfg); - if (IS_ERR(chip->psy)) { - ret = PTR_ERR(chip->psy); - dev_err(chip->dev, "Error registering power-supply: %d\n", ret); - return ret; - } - ret = fusb302_debugfs_init(chip); if (ret < 0) return ret; diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index b160da3..7547097 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,11 @@ struct tcpm_port { u32 current_limit; u32 supply_voltage; + /* Used to export TA voltage and current */ + struct power_supply *psy; + struct power_supply_desc psy_desc; + enum power_supply_usb_type usb_type; + u32 bist_request; /* PD state for Vendor Defined Messages */ @@ -1895,6 +1901,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, int ret = -EINVAL; port->pps_data.supported = false; + port->usb_type = POWER_SUPPLY_USB_TYPE_PD; /* * Select the source PDO providing the most power which has a @@ -1915,8 +1922,11 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, min_src_mv = pdo_min_voltage(pdo); break; case PDO_TYPE_APDO: - if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) + if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) { port->pps_data.supported = true; + port->usb_type = + POWER_SUPPLY_USB_TYPE_PD_PPS; + } continue; default: tcpm_log(port, "Invalid source PDO type, ignoring"); @@ -2472,6 +2482,9 @@ static void tcpm_reset_port(struct tcpm_port *port) port->try_snk_count = 0; port->supply_voltage = 0; port->current_limit = 0; + port->usb_type = POWER_SUPPLY_USB_TYPE_C; + + power_supply_changed(port->psy); } static void tcpm_detach(struct tcpm_port *port) @@ -2999,6 +3012,8 @@ static void run_state_machine(struct tcpm_port *port) tcpm_check_send_discover(port); tcpm_pps_complete(port, port->pps_status); + power_supply_changed(port->psy); + break; /* Accessory states */ @@ -3849,7 +3864,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role) return ret; } -static int __maybe_unused tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) +static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) { unsigned int target_mw; int ret; @@ -3901,7 +3916,7 @@ static int __maybe_unused tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_cu return ret; } -static int __maybe_unused tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) +static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) { unsigned int target_mw; int ret; @@ -3954,7 +3969,7 @@ static int __maybe_unused tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_ return ret; } -static int __maybe_unused tcpm_pps_activate(struct tcpm_port *port, bool activate) +static int tcpm_pps_activate(struct tcpm_port *port, bool activate) { int ret = 0; @@ -4159,6 +4174,230 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, } EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); +/* Power Supply access to expose source power information */ +enum tcpm_psy_online_states { + TCPM_PSY_OFFLINE = 0, + TCPM_PSY_FIXED_ONLINE, + TCPM_PSY_PROG_ONLINE, +}; + +static enum power_supply_property tcpm_psy_props[] = { + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, +}; + +static int tcpm_psy_get_online(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->vbus_charge) { + if (port->pps_data.active) + val->intval = TCPM_PSY_PROG_ONLINE; + else + val->intval = TCPM_PSY_FIXED_ONLINE; + } else { + val->intval = TCPM_PSY_OFFLINE; + } + + return 0; +} + +static int tcpm_psy_get_voltage_min(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->pps_data.active) + val->intval = port->pps_data.min_volt * 1000; + else + val->intval = port->supply_voltage * 1000; + + return 0; +} + +static int tcpm_psy_get_voltage_max(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->pps_data.active) + val->intval = port->pps_data.max_volt * 1000; + else + val->intval = port->supply_voltage * 1000; + + return 0; +} + +static int tcpm_psy_get_voltage_now(struct tcpm_port *port, + union power_supply_propval *val) +{ + val->intval = port->supply_voltage * 1000; + + return 0; +} + +static int tcpm_psy_get_current_max(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->pps_data.active) + val->intval = port->pps_data.max_curr * 1000; + else + val->intval = port->current_limit * 1000; + + return 0; +} + +static int tcpm_psy_get_current_now(struct tcpm_port *port, + union power_supply_propval *val) +{ + val->intval = port->current_limit * 1000; + + return 0; +} + +static int tcpm_psy_get_prop(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct tcpm_port *port = power_supply_get_drvdata(psy); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = port->usb_type; + break; + case POWER_SUPPLY_PROP_ONLINE: + ret = tcpm_psy_get_online(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + ret = tcpm_psy_get_voltage_min(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + ret = tcpm_psy_get_voltage_max(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret = tcpm_psy_get_voltage_now(port, val); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + ret = tcpm_psy_get_current_max(port, val); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + ret = tcpm_psy_get_current_now(port, val); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int tcpm_psy_set_online(struct tcpm_port *port, + const union power_supply_propval *val) +{ + int ret; + + switch (val->intval) { + case TCPM_PSY_FIXED_ONLINE: + ret = tcpm_pps_activate(port, false); + break; + case TCPM_PSY_PROG_ONLINE: + ret = tcpm_pps_activate(port, true); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int tcpm_psy_set_prop(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct tcpm_port *port = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + ret = tcpm_psy_set_online(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + if (val->intval < port->pps_data.min_volt * 1000 || + val->intval > port->pps_data.max_volt * 1000) + ret = -EINVAL; + else + ret = tcpm_pps_set_out_volt(port, val->intval / 1000); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + if (val->intval > port->pps_data.max_curr * 1000) + ret = -EINVAL; + else + ret = tcpm_pps_set_op_curr(port, val->intval / 1000); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int tcpm_psy_prop_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + case POWER_SUPPLY_PROP_CURRENT_NOW: + return 1; + default: + return 0; + } +} + +static enum power_supply_usb_type tcpm_psy_usb_types[] = { + POWER_SUPPLY_USB_TYPE_C, + POWER_SUPPLY_USB_TYPE_PD, + POWER_SUPPLY_USB_TYPE_PD_PPS, +}; + +static const char *tcpm_psy_name_prefix = "tcpm-source-psy-"; + +static int devm_tcpm_psy_register(struct tcpm_port *port) +{ + struct power_supply_config psy_cfg = {}; + const char *port_dev_name = dev_name(port->dev); + size_t psy_name_len = strlen(tcpm_psy_name_prefix) + + strlen(port_dev_name) + 1; + char *psy_name; + + psy_cfg.drv_data = port; + psy_name = devm_kzalloc(port->dev, psy_name_len, GFP_KERNEL); + if (!psy_name) + return -ENOMEM; + + snprintf(psy_name, psy_name_len, "%s%s", tcpm_psy_name_prefix, + port_dev_name); + port->psy_desc.name = psy_name; + port->psy_desc.type = POWER_SUPPLY_TYPE_USB, + port->psy_desc.usb_types = tcpm_psy_usb_types; + port->psy_desc.num_usb_types = ARRAY_SIZE(tcpm_psy_usb_types); + port->psy_desc.properties = tcpm_psy_props, + port->psy_desc.num_properties = ARRAY_SIZE(tcpm_psy_props), + port->psy_desc.get_property = tcpm_psy_get_prop, + port->psy_desc.set_property = tcpm_psy_set_prop, + port->psy_desc.property_is_writeable = tcpm_psy_prop_writeable, + + port->usb_type = POWER_SUPPLY_USB_TYPE_C; + + port->psy = devm_power_supply_register(port->dev, &port->psy_desc, + &psy_cfg); + + return PTR_ERR_OR_ZERO(port->psy); +} + struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) { struct tcpm_port *port; @@ -4234,6 +4473,10 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) goto out_destroy_wq; } + err = devm_tcpm_psy_register(port); + if (err) + goto out_destroy_wq; + port->typec_port = typec_register_port(port->dev, &port->typec_caps); if (IS_ERR(port->typec_port)) { err = PTR_ERR(port->typec_port); -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [v8,5/6] typec: tcpm: Represent source supply through power_supply From: "Opensource \[Adam Thomson\]" Message-Id: Date: Mon, 23 Apr 2018 15:11:00 +0100 To: Heikki Krogerus , Guenter Roeck , Greg Kroah-Hartman , Sebastian Reichel , Hans de Goede , Jun Li Cc: linux-usb@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, support.opensource@diasemi.com List-ID: VGhpcyBjb21taXQgYWRkcyBhIHBvd2VyX3N1cHBseSBjbGFzcyBpbnN0YW5jZSB0byByZXByZXNl bnQgYQpQRCBzb3VyY2UncyB2b2x0YWdlIGFuZCBjdXJyZW50IHByb3BlcnRpZXMuIFRoaXMgcHJv dmlkZXMgYW4KaW50ZXJmYWNlIGZvciByZWFkaW5nIHRoZXNlIHByb3BlcnRpZXMgZnJvbSB1c2Vy LXNwYWNlIG9yIG90aGVyCmRyaXZlcnMuCgpGb3IgUFBTIGVuYWJsZWQgU291cmNlcywgdGhpcyBh bHNvIHByb3ZpZGVzIHdyaXRlIGFjY2VzcyB0byBzZXQKdGhlIGN1cnJlbnQgYW5kIHZvbHRhZ2Ug YW5kIGFsbG93cyBmb3Igc3dhcHBpbmcgYmV0d2VlbiBzdGFuZGFyZApQRE8gYW5kIFBQUyBBUERP LgoKQXMgdGhpcyByZXByZXNlbnRzIGEgc3VwZXJzZXQgb2YgdGhlIGluZm9ybWF0aW9uIHByb3Zp ZGVkIGluIHRoZQpmdXNiMzAyIGRyaXZlciwgdGhlIHBvd2VyX3N1cHBseSBpbnN0YW5jZSBpbiB0 aGF0IGNvZGUgaXMgcmVtb3ZlZAphcyBwYXJ0IG9mIHRoaXMgY2hhbmdlLCBzbyByZXZlcnRpbmcg dGhlIGNvbW1pdCB0aXRsZWQKJ3R5cGVjOiB0Y3BtOiBSZXByZXNlbnQgc291cmNlIHN1cHBseSB0 aHJvdWdoIHBvd2VyX3N1cHBseSBjbGFzcycKClNpZ25lZC1vZmYtYnk6IEFkYW0gVGhvbXNvbiA8 QWRhbS5UaG9tc29uLk9wZW5zb3VyY2VAZGlhc2VtaS5jb20+ClJldmlld2VkLWJ5OiBHdWVudGVy IFJvZWNrIDxsaW51eEByb2Vjay11cy5uZXQ+Ci0tLQogZHJpdmVycy91c2IvdHlwZWMvS2NvbmZp ZyAgICAgICAgICAgfCAgIDEgKwogZHJpdmVycy91c2IvdHlwZWMvZnVzYjMwMi9LY29uZmlnICAg fCAgIDIgKy0KIGRyaXZlcnMvdXNiL3R5cGVjL2Z1c2IzMDIvZnVzYjMwMi5jIHwgIDYzICstLS0t LS0tLQogZHJpdmVycy91c2IvdHlwZWMvdGNwbS5jICAgICAgICAgICAgfCAyNTEgKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKystCiA0IGZpbGVzIGNoYW5nZWQsIDI1MSBpbnNlcnRp b25zKCspLCA2NiBkZWxldGlvbnMoLSkKCmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi90eXBlYy9L Y29uZmlnIGIvZHJpdmVycy91c2IvdHlwZWMvS2NvbmZpZwppbmRleCAwMzBmODhjLi4yYzhlYWIx IDEwMDY0NAotLS0gYS9kcml2ZXJzL3VzYi90eXBlYy9LY29uZmlnCisrKyBiL2RyaXZlcnMvdXNi L3R5cGVjL0tjb25maWcKQEAgLTQ5LDYgKzQ5LDcgQEAgY29uZmlnIFRZUEVDX1RDUE0KIAl0cmlz dGF0ZSAiVVNCIFR5cGUtQyBQb3J0IENvbnRyb2xsZXIgTWFuYWdlciIKIAlkZXBlbmRzIG9uIFVT QgogCXNlbGVjdCBVU0JfUk9MRV9TV0lUQ0gKKwlzZWxlY3QgUE9XRVJfU1VQUExZCiAJaGVscAog CSAgVGhlIFR5cGUtQyBQb3J0IENvbnRyb2xsZXIgTWFuYWdlciBwcm92aWRlcyBhIFVTQiBQRCBh bmQgVVNCIFR5cGUtQwogCSAgc3RhdGUgbWFjaGluZSBmb3IgdXNlIHdpdGggVHlwZS1DIFBvcnQg Q29udHJvbGxlcnMuCmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi90eXBlYy9mdXNiMzAyL0tjb25m aWcgYi9kcml2ZXJzL3VzYi90eXBlYy9mdXNiMzAyL0tjb25maWcKaW5kZXggNDhhNGYyZi4uZmNl MDk5ZiAxMDA2NDQKLS0tIGEvZHJpdmVycy91c2IvdHlwZWMvZnVzYjMwMi9LY29uZmlnCisrKyBi L2RyaXZlcnMvdXNiL3R5cGVjL2Z1c2IzMDIvS2NvbmZpZwpAQCAtMSw2ICsxLDYgQEAKIGNvbmZp ZyBUWVBFQ19GVVNCMzAyCiAJdHJpc3RhdGUgIkZhaXJjaGlsZCBGVVNCMzAyIFR5cGUtQyBjaGlw IGRyaXZlciIKLQlkZXBlbmRzIG9uIEkyQyAmJiBQT1dFUl9TVVBQTFkKKwlkZXBlbmRzIG9uIEky QwogCWhlbHAKIAkgIFRoZSBGYWlyY2hpbGQgRlVTQjMwMiBUeXBlLUMgY2hpcCBkcml2ZXIgdGhh dCB3b3JrcyB3aXRoCiAJICBUeXBlLUMgUG9ydCBDb250cm9sbGVyIE1hbmFnZXIgdG8gcHJvdmlk ZSBVU0IgUEQgYW5kIFVTQgpkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvdHlwZWMvZnVzYjMwMi9m dXNiMzAyLmMgYi9kcml2ZXJzL3VzYi90eXBlYy9mdXNiMzAyL2Z1c2IzMDIuYwppbmRleCA2NjQ0 NjNkLi5lYmE2YmI4IDEwMDY0NAotLS0gYS9kcml2ZXJzL3VzYi90eXBlYy9mdXNiMzAyL2Z1c2Iz MDIuYworKysgYi9kcml2ZXJzL3VzYi90eXBlYy9mdXNiMzAyL2Z1c2IzMDIuYwpAQCAtMTgsNyAr MTgsNiBAQAogI2luY2x1ZGUgPGxpbnV4L29mX2RldmljZS5oPgogI2luY2x1ZGUgPGxpbnV4L29m X2dwaW8uaD4KICNpbmNsdWRlIDxsaW51eC9waW5jdHJsL2NvbnN1bWVyLmg+Ci0jaW5jbHVkZSA8 bGludXgvcG93ZXJfc3VwcGx5Lmg+CiAjaW5jbHVkZSA8bGludXgvcHJvY19mcy5oPgogI2luY2x1 ZGUgPGxpbnV4L3JlZ3VsYXRvci9jb25zdW1lci5oPgogI2luY2x1ZGUgPGxpbnV4L3NjaGVkL2Ns b2NrLmg+CkBAIC05OSwxMSArOTgsNiBAQCBzdHJ1Y3QgZnVzYjMwMl9jaGlwIHsKIAkvKiBsb2Nr IGZvciBzaGFyaW5nIGNoaXAgc3RhdGVzICovCiAJc3RydWN0IG11dGV4IGxvY2s7CiAKLQkvKiBw c3kgKyBwc3kgc3RhdHVzICovCi0Jc3RydWN0IHBvd2VyX3N1cHBseSAqcHN5OwotCXUzMiBjdXJy ZW50X2xpbWl0OwotCXUzMiBzdXBwbHlfdm9sdGFnZTsKLQogCS8qIGNoaXAgc3RhdHVzICovCiAJ ZW51bSB0b2dnbGluZ19tb2RlIHRvZ2dsaW5nX21vZGU7CiAJZW51bSBzcmNfY3VycmVudF9zdGF0 dXMgc3JjX2N1cnJlbnRfc3RhdHVzOwpAQCAtODYyLDEzICs4NTYsMTEgQEAgc3RhdGljIGludCB0 Y3BtX3NldF92YnVzKHN0cnVjdCB0Y3BjX2RldiAqZGV2LCBib29sIG9uLCBib29sIGNoYXJnZSkK IAkJY2hpcC0+dmJ1c19vbiA9IG9uOwogCQlmdXNiMzAyX2xvZyhjaGlwLCAidmJ1cyA6PSAlcyIs IG9uID8gIk9uIiA6ICJPZmYiKTsKIAl9Ci0JaWYgKGNoaXAtPmNoYXJnZV9vbiA9PSBjaGFyZ2Up IHsKKwlpZiAoY2hpcC0+Y2hhcmdlX29uID09IGNoYXJnZSkKIAkJZnVzYjMwMl9sb2coY2hpcCwg ImNoYXJnZSBpcyBhbHJlYWR5ICVzIiwKIAkJCSAgICBjaGFyZ2UgPyAiT24iIDogIk9mZiIpOwot CX0gZWxzZSB7CisJZWxzZQogCQljaGlwLT5jaGFyZ2Vfb24gPSBjaGFyZ2U7Ci0JCXBvd2VyX3N1 cHBseV9jaGFuZ2VkKGNoaXAtPnBzeSk7Ci0JfQogCiBkb25lOgogCW11dGV4X3VubG9jaygmY2hp cC0+bG9jayk7CkBAIC04ODQsMTEgKzg3Niw2IEBAIHN0YXRpYyBpbnQgdGNwbV9zZXRfY3VycmVu dF9saW1pdChzdHJ1Y3QgdGNwY19kZXYgKmRldiwgdTMyIG1heF9tYSwgdTMyIG12KQogCWZ1c2Iz MDJfbG9nKGNoaXAsICJjdXJyZW50IGxpbWl0OiAlZCBtYSwgJWQgbXYgKG5vdCBpbXBsZW1lbnRl ZCkiLAogCQkgICAgbWF4X21hLCBtdik7CiAKLQljaGlwLT5zdXBwbHlfdm9sdGFnZSA9IG12Owot CWNoaXAtPmN1cnJlbnRfbGltaXQgPSBtYXhfbWE7Ci0KLQlwb3dlcl9zdXBwbHlfY2hhbmdlZChj aGlwLT5wc3kpOwotCiAJcmV0dXJuIDA7CiB9CiAKQEAgLTE2ODIsNDMgKzE2NjksNiBAQCBzdGF0 aWMgaXJxcmV0dXJuX3QgZnVzYjMwMl9pcnFfaW50bihpbnQgaXJxLCB2b2lkICpkZXZfaWQpCiAJ cmV0dXJuIElSUV9IQU5ETEVEOwogfQogCi1zdGF0aWMgaW50IGZ1c2IzMDJfcHN5X2dldF9wcm9w ZXJ0eShzdHJ1Y3QgcG93ZXJfc3VwcGx5ICpwc3ksCi0JCQkJICAgIGVudW0gcG93ZXJfc3VwcGx5 X3Byb3BlcnR5IHBzcCwKLQkJCQkgICAgdW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2YWwgKnZhbCkK LXsKLQlzdHJ1Y3QgZnVzYjMwMl9jaGlwICpjaGlwID0gcG93ZXJfc3VwcGx5X2dldF9kcnZkYXRh KHBzeSk7Ci0KLQlzd2l0Y2ggKHBzcCkgewotCWNhc2UgUE9XRVJfU1VQUExZX1BST1BfT05MSU5F OgotCQl2YWwtPmludHZhbCA9IGNoaXAtPmNoYXJnZV9vbjsKLQkJYnJlYWs7Ci0JY2FzZSBQT1dF Ul9TVVBQTFlfUFJPUF9WT0xUQUdFX05PVzoKLQkJdmFsLT5pbnR2YWwgPSBjaGlwLT5zdXBwbHlf dm9sdGFnZSAqIDEwMDA7IC8qIG1WIC0+IMK1ViAqLwotCQlicmVhazsKLQljYXNlIFBPV0VSX1NV UFBMWV9QUk9QX0NVUlJFTlRfTUFYOgotCQl2YWwtPmludHZhbCA9IGNoaXAtPmN1cnJlbnRfbGlt aXQgKiAxMDAwOyAvKiBtQSAtPiDCtUEgKi8KLQkJYnJlYWs7Ci0JZGVmYXVsdDoKLQkJcmV0dXJu IC1FTk9EQVRBOwotCX0KLQotCXJldHVybiAwOwotfQotCi1zdGF0aWMgZW51bSBwb3dlcl9zdXBw bHlfcHJvcGVydHkgZnVzYjMwMl9wc3lfcHJvcGVydGllc1tdID0gewotCVBPV0VSX1NVUFBMWV9Q Uk9QX09OTElORSwKLQlQT1dFUl9TVVBQTFlfUFJPUF9WT0xUQUdFX05PVywKLQlQT1dFUl9TVVBQ TFlfUFJPUF9DVVJSRU5UX01BWCwKLX07Ci0KLXN0YXRpYyBjb25zdCBzdHJ1Y3QgcG93ZXJfc3Vw cGx5X2Rlc2MgZnVzYjMwMl9wc3lfZGVzYyA9IHsKLQkubmFtZQkJPSAiZnVzYjMwMi10eXBlYy1z b3VyY2UiLAotCS50eXBlCQk9IFBPV0VSX1NVUFBMWV9UWVBFX1VTQl9UWVBFX0MsCi0JLnByb3Bl cnRpZXMJPSBmdXNiMzAyX3BzeV9wcm9wZXJ0aWVzLAotCS5udW1fcHJvcGVydGllcwk9IEFSUkFZ X1NJWkUoZnVzYjMwMl9wc3lfcHJvcGVydGllcyksCi0JLmdldF9wcm9wZXJ0eQk9IGZ1c2IzMDJf cHN5X2dldF9wcm9wZXJ0eSwKLX07Ci0KIHN0YXRpYyBpbnQgaW5pdF9ncGlvKHN0cnVjdCBmdXNi MzAyX2NoaXAgKmNoaXApCiB7CiAJc3RydWN0IGRldmljZV9ub2RlICpub2RlOwpAQCAtMTc4MSw3 ICsxNzMxLDYgQEAgc3RhdGljIGludCBmdXNiMzAyX3Byb2JlKHN0cnVjdCBpMmNfY2xpZW50ICpj bGllbnQsCiAJc3RydWN0IGZ1c2IzMDJfY2hpcCAqY2hpcDsKIAlzdHJ1Y3QgaTJjX2FkYXB0ZXIg KmFkYXB0ZXI7CiAJc3RydWN0IGRldmljZSAqZGV2ID0gJmNsaWVudC0+ZGV2OwotCXN0cnVjdCBw b3dlcl9zdXBwbHlfY29uZmlnIGNmZyA9IHt9OwogCWNvbnN0IGNoYXIgKm5hbWU7CiAJaW50IHJl dCA9IDA7CiAJdTMyIHY7CkBAIC0xODIzLDE0ICsxNzcyLDYgQEAgc3RhdGljIGludCBmdXNiMzAy X3Byb2JlKHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsCiAJCQlyZXR1cm4gLUVQUk9CRV9ERUZF UjsKIAl9CiAKLQljZmcuZHJ2X2RhdGEgPSBjaGlwOwotCWNoaXAtPnBzeSA9IGRldm1fcG93ZXJf c3VwcGx5X3JlZ2lzdGVyKGRldiwgJmZ1c2IzMDJfcHN5X2Rlc2MsICZjZmcpOwotCWlmIChJU19F UlIoY2hpcC0+cHN5KSkgewotCQlyZXQgPSBQVFJfRVJSKGNoaXAtPnBzeSk7Ci0JCWRldl9lcnIo Y2hpcC0+ZGV2LCAiRXJyb3IgcmVnaXN0ZXJpbmcgcG93ZXItc3VwcGx5OiAlZFxuIiwgcmV0KTsK LQkJcmV0dXJuIHJldDsKLQl9Ci0KIAlyZXQgPSBmdXNiMzAyX2RlYnVnZnNfaW5pdChjaGlwKTsK IAlpZiAocmV0IDwgMCkKIAkJcmV0dXJuIHJldDsKZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL3R5 cGVjL3RjcG0uYyBiL2RyaXZlcnMvdXNiL3R5cGVjL3RjcG0uYwppbmRleCBiMTYwZGEzLi43NTQ3 MDk3IDEwMDY0NAotLS0gYS9kcml2ZXJzL3VzYi90eXBlYy90Y3BtLmMKKysrIGIvZHJpdmVycy91 c2IvdHlwZWMvdGNwbS5jCkBAIC0xMiw2ICsxMiw3IEBACiAjaW5jbHVkZSA8bGludXgva2VybmVs Lmg+CiAjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CiAjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4K KyNpbmNsdWRlIDxsaW51eC9wb3dlcl9zdXBwbHkuaD4KICNpbmNsdWRlIDxsaW51eC9wcm9jX2Zz Lmg+CiAjaW5jbHVkZSA8bGludXgvc2NoZWQvY2xvY2suaD4KICNpbmNsdWRlIDxsaW51eC9zZXFf ZmlsZS5oPgpAQCAtMjc2LDYgKzI3NywxMSBAQCBzdHJ1Y3QgdGNwbV9wb3J0IHsKIAl1MzIgY3Vy cmVudF9saW1pdDsKIAl1MzIgc3VwcGx5X3ZvbHRhZ2U7CiAKKwkvKiBVc2VkIHRvIGV4cG9ydCBU QSB2b2x0YWdlIGFuZCBjdXJyZW50ICovCisJc3RydWN0IHBvd2VyX3N1cHBseSAqcHN5OworCXN0 cnVjdCBwb3dlcl9zdXBwbHlfZGVzYyBwc3lfZGVzYzsKKwllbnVtIHBvd2VyX3N1cHBseV91c2Jf dHlwZSB1c2JfdHlwZTsKKwogCXUzMiBiaXN0X3JlcXVlc3Q7CiAKIAkvKiBQRCBzdGF0ZSBmb3Ig VmVuZG9yIERlZmluZWQgTWVzc2FnZXMgKi8KQEAgLTE4OTUsNiArMTkwMSw3IEBAIHN0YXRpYyBp bnQgdGNwbV9wZF9zZWxlY3RfcGRvKHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQsIGludCAqc2lua19w ZG8sCiAJaW50IHJldCA9IC1FSU5WQUw7CiAKIAlwb3J0LT5wcHNfZGF0YS5zdXBwb3J0ZWQgPSBm YWxzZTsKKwlwb3J0LT51c2JfdHlwZSA9IFBPV0VSX1NVUFBMWV9VU0JfVFlQRV9QRDsKIAogCS8q CiAJICogU2VsZWN0IHRoZSBzb3VyY2UgUERPIHByb3ZpZGluZyB0aGUgbW9zdCBwb3dlciB3aGlj aCBoYXMgYQpAQCAtMTkxNSw4ICsxOTIyLDExIEBAIHN0YXRpYyBpbnQgdGNwbV9wZF9zZWxlY3Rf cGRvKHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQsIGludCAqc2lua19wZG8sCiAJCQltaW5fc3JjX212 ID0gcGRvX21pbl92b2x0YWdlKHBkbyk7CiAJCQlicmVhazsKIAkJY2FzZSBQRE9fVFlQRV9BUERP OgotCQkJaWYgKHBkb19hcGRvX3R5cGUocGRvKSA9PSBBUERPX1RZUEVfUFBTKQorCQkJaWYgKHBk b19hcGRvX3R5cGUocGRvKSA9PSBBUERPX1RZUEVfUFBTKSB7CiAJCQkJcG9ydC0+cHBzX2RhdGEu c3VwcG9ydGVkID0gdHJ1ZTsKKwkJCQlwb3J0LT51c2JfdHlwZSA9CisJCQkJCVBPV0VSX1NVUFBM WV9VU0JfVFlQRV9QRF9QUFM7CisJCQl9CiAJCQljb250aW51ZTsKIAkJZGVmYXVsdDoKIAkJCXRj cG1fbG9nKHBvcnQsICJJbnZhbGlkIHNvdXJjZSBQRE8gdHlwZSwgaWdub3JpbmciKTsKQEAgLTI0 NzIsNiArMjQ4Miw5IEBAIHN0YXRpYyB2b2lkIHRjcG1fcmVzZXRfcG9ydChzdHJ1Y3QgdGNwbV9w b3J0ICpwb3J0KQogCXBvcnQtPnRyeV9zbmtfY291bnQgPSAwOwogCXBvcnQtPnN1cHBseV92b2x0 YWdlID0gMDsKIAlwb3J0LT5jdXJyZW50X2xpbWl0ID0gMDsKKwlwb3J0LT51c2JfdHlwZSA9IFBP V0VSX1NVUFBMWV9VU0JfVFlQRV9DOworCisJcG93ZXJfc3VwcGx5X2NoYW5nZWQocG9ydC0+cHN5 KTsKIH0KIAogc3RhdGljIHZvaWQgdGNwbV9kZXRhY2goc3RydWN0IHRjcG1fcG9ydCAqcG9ydCkK QEAgLTI5OTksNiArMzAxMiw4IEBAIHN0YXRpYyB2b2lkIHJ1bl9zdGF0ZV9tYWNoaW5lKHN0cnVj dCB0Y3BtX3BvcnQgKnBvcnQpCiAJCXRjcG1fY2hlY2tfc2VuZF9kaXNjb3Zlcihwb3J0KTsKIAkJ dGNwbV9wcHNfY29tcGxldGUocG9ydCwgcG9ydC0+cHBzX3N0YXR1cyk7CiAKKwkJcG93ZXJfc3Vw cGx5X2NoYW5nZWQocG9ydC0+cHN5KTsKKwogCQlicmVhazsKIAogCS8qIEFjY2Vzc29yeSBzdGF0 ZXMgKi8KQEAgLTM4NDksNyArMzg2NCw3IEBAIHN0YXRpYyBpbnQgdGNwbV90cnlfcm9sZShjb25z dCBzdHJ1Y3QgdHlwZWNfY2FwYWJpbGl0eSAqY2FwLCBpbnQgcm9sZSkKIAlyZXR1cm4gcmV0Owog fQogCi1zdGF0aWMgaW50IF9fbWF5YmVfdW51c2VkIHRjcG1fcHBzX3NldF9vcF9jdXJyKHN0cnVj dCB0Y3BtX3BvcnQgKnBvcnQsIHUxNiBvcF9jdXJyKQorc3RhdGljIGludCB0Y3BtX3Bwc19zZXRf b3BfY3VycihzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0LCB1MTYgb3BfY3VycikKIHsKIAl1bnNpZ25l ZCBpbnQgdGFyZ2V0X213OwogCWludCByZXQ7CkBAIC0zOTAxLDcgKzM5MTYsNyBAQCBzdGF0aWMg aW50IF9fbWF5YmVfdW51c2VkIHRjcG1fcHBzX3NldF9vcF9jdXJyKHN0cnVjdCB0Y3BtX3BvcnQg KnBvcnQsIHUxNiBvcF9jdQogCXJldHVybiByZXQ7CiB9CiAKLXN0YXRpYyBpbnQgX19tYXliZV91 bnVzZWQgdGNwbV9wcHNfc2V0X291dF92b2x0KHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQsIHUxNiBv dXRfdm9sdCkKK3N0YXRpYyBpbnQgdGNwbV9wcHNfc2V0X291dF92b2x0KHN0cnVjdCB0Y3BtX3Bv cnQgKnBvcnQsIHUxNiBvdXRfdm9sdCkKIHsKIAl1bnNpZ25lZCBpbnQgdGFyZ2V0X213OwogCWlu dCByZXQ7CkBAIC0zOTU0LDcgKzM5NjksNyBAQCBzdGF0aWMgaW50IF9fbWF5YmVfdW51c2VkIHRj cG1fcHBzX3NldF9vdXRfdm9sdChzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0LCB1MTYgb3V0XwogCXJl dHVybiByZXQ7CiB9CiAKLXN0YXRpYyBpbnQgX19tYXliZV91bnVzZWQgdGNwbV9wcHNfYWN0aXZh dGUoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCwgYm9vbCBhY3RpdmF0ZSkKK3N0YXRpYyBpbnQgdGNw bV9wcHNfYWN0aXZhdGUoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCwgYm9vbCBhY3RpdmF0ZSkKIHsK IAlpbnQgcmV0ID0gMDsKIApAQCAtNDE1OSw2ICs0MTc0LDIzMCBAQCBpbnQgdGNwbV91cGRhdGVf c2lua19jYXBhYmlsaXRpZXMoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCwgY29uc3QgdTMyICpwZG8s CiB9CiBFWFBPUlRfU1lNQk9MX0dQTCh0Y3BtX3VwZGF0ZV9zaW5rX2NhcGFiaWxpdGllcyk7CiAK Ky8qIFBvd2VyIFN1cHBseSBhY2Nlc3MgdG8gZXhwb3NlIHNvdXJjZSBwb3dlciBpbmZvcm1hdGlv biAqLworZW51bSB0Y3BtX3BzeV9vbmxpbmVfc3RhdGVzIHsKKwlUQ1BNX1BTWV9PRkZMSU5FID0g MCwKKwlUQ1BNX1BTWV9GSVhFRF9PTkxJTkUsCisJVENQTV9QU1lfUFJPR19PTkxJTkUsCit9Owor CitzdGF0aWMgZW51bSBwb3dlcl9zdXBwbHlfcHJvcGVydHkgdGNwbV9wc3lfcHJvcHNbXSA9IHsK KwlQT1dFUl9TVVBQTFlfUFJPUF9VU0JfVFlQRSwKKwlQT1dFUl9TVVBQTFlfUFJPUF9PTkxJTkUs CisJUE9XRVJfU1VQUExZX1BST1BfVk9MVEFHRV9NSU4sCisJUE9XRVJfU1VQUExZX1BST1BfVk9M VEFHRV9NQVgsCisJUE9XRVJfU1VQUExZX1BST1BfVk9MVEFHRV9OT1csCisJUE9XRVJfU1VQUExZ X1BST1BfQ1VSUkVOVF9NQVgsCisJUE9XRVJfU1VQUExZX1BST1BfQ1VSUkVOVF9OT1csCit9Owor CitzdGF0aWMgaW50IHRjcG1fcHN5X2dldF9vbmxpbmUoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCwK KwkJCSAgICAgICB1bmlvbiBwb3dlcl9zdXBwbHlfcHJvcHZhbCAqdmFsKQoreworCWlmIChwb3J0 LT52YnVzX2NoYXJnZSkgeworCQlpZiAocG9ydC0+cHBzX2RhdGEuYWN0aXZlKQorCQkJdmFsLT5p bnR2YWwgPSBUQ1BNX1BTWV9QUk9HX09OTElORTsKKwkJZWxzZQorCQkJdmFsLT5pbnR2YWwgPSBU Q1BNX1BTWV9GSVhFRF9PTkxJTkU7CisJfSBlbHNlIHsKKwkJdmFsLT5pbnR2YWwgPSBUQ1BNX1BT WV9PRkZMSU5FOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHRjcG1fcHN5X2dl dF92b2x0YWdlX21pbihzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0LAorCQkJCSAgICB1bmlvbiBwb3dl cl9zdXBwbHlfcHJvcHZhbCAqdmFsKQoreworCWlmIChwb3J0LT5wcHNfZGF0YS5hY3RpdmUpCisJ CXZhbC0+aW50dmFsID0gcG9ydC0+cHBzX2RhdGEubWluX3ZvbHQgKiAxMDAwOworCWVsc2UKKwkJ dmFsLT5pbnR2YWwgPSBwb3J0LT5zdXBwbHlfdm9sdGFnZSAqIDEwMDA7CisKKwlyZXR1cm4gMDsK K30KKworc3RhdGljIGludCB0Y3BtX3BzeV9nZXRfdm9sdGFnZV9tYXgoc3RydWN0IHRjcG1fcG9y dCAqcG9ydCwKKwkJCQkgICAgdW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2YWwgKnZhbCkKK3sKKwlp ZiAocG9ydC0+cHBzX2RhdGEuYWN0aXZlKQorCQl2YWwtPmludHZhbCA9IHBvcnQtPnBwc19kYXRh Lm1heF92b2x0ICogMTAwMDsKKwllbHNlCisJCXZhbC0+aW50dmFsID0gcG9ydC0+c3VwcGx5X3Zv bHRhZ2UgKiAxMDAwOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgdGNwbV9wc3lfZ2V0 X3ZvbHRhZ2Vfbm93KHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQsCisJCQkJICAgIHVuaW9uIHBvd2Vy X3N1cHBseV9wcm9wdmFsICp2YWwpCit7CisJdmFsLT5pbnR2YWwgPSBwb3J0LT5zdXBwbHlfdm9s dGFnZSAqIDEwMDA7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCB0Y3BtX3BzeV9nZXRf Y3VycmVudF9tYXgoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCwKKwkJCQkgICAgdW5pb24gcG93ZXJf c3VwcGx5X3Byb3B2YWwgKnZhbCkKK3sKKwlpZiAocG9ydC0+cHBzX2RhdGEuYWN0aXZlKQorCQl2 YWwtPmludHZhbCA9IHBvcnQtPnBwc19kYXRhLm1heF9jdXJyICogMTAwMDsKKwllbHNlCisJCXZh bC0+aW50dmFsID0gcG9ydC0+Y3VycmVudF9saW1pdCAqIDEwMDA7CisKKwlyZXR1cm4gMDsKK30K Kworc3RhdGljIGludCB0Y3BtX3BzeV9nZXRfY3VycmVudF9ub3coc3RydWN0IHRjcG1fcG9ydCAq cG9ydCwKKwkJCQkgICAgdW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2YWwgKnZhbCkKK3sKKwl2YWwt PmludHZhbCA9IHBvcnQtPmN1cnJlbnRfbGltaXQgKiAxMDAwOworCisJcmV0dXJuIDA7Cit9CisK K3N0YXRpYyBpbnQgdGNwbV9wc3lfZ2V0X3Byb3Aoc3RydWN0IHBvd2VyX3N1cHBseSAqcHN5LAor CQkJICAgICBlbnVtIHBvd2VyX3N1cHBseV9wcm9wZXJ0eSBwc3AsCisJCQkgICAgIHVuaW9uIHBv d2VyX3N1cHBseV9wcm9wdmFsICp2YWwpCit7CisJc3RydWN0IHRjcG1fcG9ydCAqcG9ydCA9IHBv d2VyX3N1cHBseV9nZXRfZHJ2ZGF0YShwc3kpOworCWludCByZXQgPSAwOworCisJc3dpdGNoIChw c3ApIHsKKwljYXNlIFBPV0VSX1NVUFBMWV9QUk9QX1VTQl9UWVBFOgorCQl2YWwtPmludHZhbCA9 IHBvcnQtPnVzYl90eXBlOworCQlicmVhazsKKwljYXNlIFBPV0VSX1NVUFBMWV9QUk9QX09OTElO RToKKwkJcmV0ID0gdGNwbV9wc3lfZ2V0X29ubGluZShwb3J0LCB2YWwpOworCQlicmVhazsKKwlj YXNlIFBPV0VSX1NVUFBMWV9QUk9QX1ZPTFRBR0VfTUlOOgorCQlyZXQgPSB0Y3BtX3BzeV9nZXRf dm9sdGFnZV9taW4ocG9ydCwgdmFsKTsKKwkJYnJlYWs7CisJY2FzZSBQT1dFUl9TVVBQTFlfUFJP UF9WT0xUQUdFX01BWDoKKwkJcmV0ID0gdGNwbV9wc3lfZ2V0X3ZvbHRhZ2VfbWF4KHBvcnQsIHZh bCk7CisJCWJyZWFrOworCWNhc2UgUE9XRVJfU1VQUExZX1BST1BfVk9MVEFHRV9OT1c6CisJCXJl dCA9IHRjcG1fcHN5X2dldF92b2x0YWdlX25vdyhwb3J0LCB2YWwpOworCQlicmVhazsKKwljYXNl IFBPV0VSX1NVUFBMWV9QUk9QX0NVUlJFTlRfTUFYOgorCQlyZXQgPSB0Y3BtX3BzeV9nZXRfY3Vy cmVudF9tYXgocG9ydCwgdmFsKTsKKwkJYnJlYWs7CisJY2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9D VVJSRU5UX05PVzoKKwkJcmV0ID0gdGNwbV9wc3lfZ2V0X2N1cnJlbnRfbm93KHBvcnQsIHZhbCk7 CisJCWJyZWFrOworCWRlZmF1bHQ6CisJCXJldCA9IC1FSU5WQUw7CisJCWJyZWFrOworCX0KKwor CXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgdGNwbV9wc3lfc2V0X29ubGluZShzdHJ1Y3Qg dGNwbV9wb3J0ICpwb3J0LAorCQkJICAgICAgIGNvbnN0IHVuaW9uIHBvd2VyX3N1cHBseV9wcm9w dmFsICp2YWwpCit7CisJaW50IHJldDsKKworCXN3aXRjaCAodmFsLT5pbnR2YWwpIHsKKwljYXNl IFRDUE1fUFNZX0ZJWEVEX09OTElORToKKwkJcmV0ID0gdGNwbV9wcHNfYWN0aXZhdGUocG9ydCwg ZmFsc2UpOworCQlicmVhazsKKwljYXNlIFRDUE1fUFNZX1BST0dfT05MSU5FOgorCQlyZXQgPSB0 Y3BtX3Bwc19hY3RpdmF0ZShwb3J0LCB0cnVlKTsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0 ID0gLUVJTlZBTDsKKwkJYnJlYWs7CisJfQorCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGlu dCB0Y3BtX3BzeV9zZXRfcHJvcChzdHJ1Y3QgcG93ZXJfc3VwcGx5ICpwc3ksCisJCQkgICAgIGVu dW0gcG93ZXJfc3VwcGx5X3Byb3BlcnR5IHBzcCwKKwkJCSAgICAgY29uc3QgdW5pb24gcG93ZXJf c3VwcGx5X3Byb3B2YWwgKnZhbCkKK3sKKwlzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0ID0gcG93ZXJf c3VwcGx5X2dldF9kcnZkYXRhKHBzeSk7CisJaW50IHJldDsKKworCXN3aXRjaCAocHNwKSB7CisJ Y2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9PTkxJTkU6CisJCXJldCA9IHRjcG1fcHN5X3NldF9vbmxp bmUocG9ydCwgdmFsKTsKKwkJYnJlYWs7CisJY2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9WT0xUQUdF X05PVzoKKwkJaWYgKHZhbC0+aW50dmFsIDwgcG9ydC0+cHBzX2RhdGEubWluX3ZvbHQgKiAxMDAw IHx8CisJCSAgICB2YWwtPmludHZhbCA+IHBvcnQtPnBwc19kYXRhLm1heF92b2x0ICogMTAwMCkK KwkJCXJldCA9IC1FSU5WQUw7CisJCWVsc2UKKwkJCXJldCA9IHRjcG1fcHBzX3NldF9vdXRfdm9s dChwb3J0LCB2YWwtPmludHZhbCAvIDEwMDApOworCQlicmVhazsKKwljYXNlIFBPV0VSX1NVUFBM WV9QUk9QX0NVUlJFTlRfTk9XOgorCQlpZiAodmFsLT5pbnR2YWwgPiBwb3J0LT5wcHNfZGF0YS5t YXhfY3VyciAqIDEwMDApCisJCQlyZXQgPSAtRUlOVkFMOworCQllbHNlCisJCQlyZXQgPSB0Y3Bt X3Bwc19zZXRfb3BfY3Vycihwb3J0LCB2YWwtPmludHZhbCAvIDEwMDApOworCQlicmVhazsKKwlk ZWZhdWx0OgorCQlyZXQgPSAtRUlOVkFMOworCQlicmVhazsKKwl9CisKKwlyZXR1cm4gcmV0Owor fQorCitzdGF0aWMgaW50IHRjcG1fcHN5X3Byb3Bfd3JpdGVhYmxlKHN0cnVjdCBwb3dlcl9zdXBw bHkgKnBzeSwKKwkJCQkgICBlbnVtIHBvd2VyX3N1cHBseV9wcm9wZXJ0eSBwc3ApCit7CisJc3dp dGNoIChwc3ApIHsKKwljYXNlIFBPV0VSX1NVUFBMWV9QUk9QX09OTElORToKKwljYXNlIFBPV0VS X1NVUFBMWV9QUk9QX1ZPTFRBR0VfTk9XOgorCWNhc2UgUE9XRVJfU1VQUExZX1BST1BfQ1VSUkVO VF9OT1c6CisJCXJldHVybiAxOworCWRlZmF1bHQ6CisJCXJldHVybiAwOworCX0KK30KKworc3Rh dGljIGVudW0gcG93ZXJfc3VwcGx5X3VzYl90eXBlIHRjcG1fcHN5X3VzYl90eXBlc1tdID0gewor CVBPV0VSX1NVUFBMWV9VU0JfVFlQRV9DLAorCVBPV0VSX1NVUFBMWV9VU0JfVFlQRV9QRCwKKwlQ T1dFUl9TVVBQTFlfVVNCX1RZUEVfUERfUFBTLAorfTsKKworc3RhdGljIGNvbnN0IGNoYXIgKnRj cG1fcHN5X25hbWVfcHJlZml4ID0gInRjcG0tc291cmNlLXBzeS0iOworCitzdGF0aWMgaW50IGRl dm1fdGNwbV9wc3lfcmVnaXN0ZXIoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCkKK3sKKwlzdHJ1Y3Qg cG93ZXJfc3VwcGx5X2NvbmZpZyBwc3lfY2ZnID0ge307CisJY29uc3QgY2hhciAqcG9ydF9kZXZf bmFtZSA9IGRldl9uYW1lKHBvcnQtPmRldik7CisJc2l6ZV90IHBzeV9uYW1lX2xlbiA9IHN0cmxl bih0Y3BtX3BzeV9uYW1lX3ByZWZpeCkgKworCQkJCSAgICAgc3RybGVuKHBvcnRfZGV2X25hbWUp ICsgMTsKKwljaGFyICpwc3lfbmFtZTsKKworCXBzeV9jZmcuZHJ2X2RhdGEgPSBwb3J0OworCXBz eV9uYW1lID0gZGV2bV9remFsbG9jKHBvcnQtPmRldiwgcHN5X25hbWVfbGVuLCBHRlBfS0VSTkVM KTsKKwlpZiAoIXBzeV9uYW1lKQorCQlyZXR1cm4gLUVOT01FTTsKKworCXNucHJpbnRmKHBzeV9u YW1lLCBwc3lfbmFtZV9sZW4sICIlcyVzIiwgdGNwbV9wc3lfbmFtZV9wcmVmaXgsCisJCSBwb3J0 X2Rldl9uYW1lKTsKKwlwb3J0LT5wc3lfZGVzYy5uYW1lID0gcHN5X25hbWU7CisJcG9ydC0+cHN5 X2Rlc2MudHlwZSA9IFBPV0VSX1NVUFBMWV9UWVBFX1VTQiwKKwlwb3J0LT5wc3lfZGVzYy51c2Jf dHlwZXMgPSB0Y3BtX3BzeV91c2JfdHlwZXM7CisJcG9ydC0+cHN5X2Rlc2MubnVtX3VzYl90eXBl cyA9IEFSUkFZX1NJWkUodGNwbV9wc3lfdXNiX3R5cGVzKTsKKwlwb3J0LT5wc3lfZGVzYy5wcm9w ZXJ0aWVzID0gdGNwbV9wc3lfcHJvcHMsCisJcG9ydC0+cHN5X2Rlc2MubnVtX3Byb3BlcnRpZXMg PSBBUlJBWV9TSVpFKHRjcG1fcHN5X3Byb3BzKSwKKwlwb3J0LT5wc3lfZGVzYy5nZXRfcHJvcGVy dHkgPSB0Y3BtX3BzeV9nZXRfcHJvcCwKKwlwb3J0LT5wc3lfZGVzYy5zZXRfcHJvcGVydHkgPSB0 Y3BtX3BzeV9zZXRfcHJvcCwKKwlwb3J0LT5wc3lfZGVzYy5wcm9wZXJ0eV9pc193cml0ZWFibGUg PSB0Y3BtX3BzeV9wcm9wX3dyaXRlYWJsZSwKKworCXBvcnQtPnVzYl90eXBlID0gUE9XRVJfU1VQ UExZX1VTQl9UWVBFX0M7CisKKwlwb3J0LT5wc3kgPSBkZXZtX3Bvd2VyX3N1cHBseV9yZWdpc3Rl cihwb3J0LT5kZXYsICZwb3J0LT5wc3lfZGVzYywKKwkJCQkJICAgICAgICZwc3lfY2ZnKTsKKwor CXJldHVybiBQVFJfRVJSX09SX1pFUk8ocG9ydC0+cHN5KTsKK30KKwogc3RydWN0IHRjcG1fcG9y dCAqdGNwbV9yZWdpc3Rlcl9wb3J0KHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHRjcGNfZGV2 ICp0Y3BjKQogewogCXN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQ7CkBAIC00MjM0LDYgKzQ0NzMsMTAg QEAgc3RydWN0IHRjcG1fcG9ydCAqdGNwbV9yZWdpc3Rlcl9wb3J0KHN0cnVjdCBkZXZpY2UgKmRl diwgc3RydWN0IHRjcGNfZGV2ICp0Y3BjKQogCQlnb3RvIG91dF9kZXN0cm95X3dxOwogCX0KIAor CWVyciA9IGRldm1fdGNwbV9wc3lfcmVnaXN0ZXIocG9ydCk7CisJaWYgKGVycikKKwkJZ290byBv dXRfZGVzdHJveV93cTsKKwogCXBvcnQtPnR5cGVjX3BvcnQgPSB0eXBlY19yZWdpc3Rlcl9wb3J0 KHBvcnQtPmRldiwgJnBvcnQtPnR5cGVjX2NhcHMpOwogCWlmIChJU19FUlIocG9ydC0+dHlwZWNf cG9ydCkpIHsKIAkJZXJyID0gUFRSX0VSUihwb3J0LT50eXBlY19wb3J0KTsK From mboxrd@z Thu Jan 1 00:00:00 1970 From: Adam Thomson Subject: [PATCH v8 5/6] typec: tcpm: Represent source supply through power_supply Date: Mon, 23 Apr 2018 15:11:00 +0100 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain Return-path: In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org To: Heikki Krogerus , Guenter Roeck , Greg Kroah-Hartman , Sebastian Reichel , Hans de Goede , Jun Li Cc: linux-usb@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, support.opensource@diasemi.com List-Id: linux-pm@vger.kernel.org This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson Reviewed-by: Guenter Roeck --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +-------- drivers/usb/typec/tcpm.c | 251 +++++++++++++++++++++++++++++++++++- 4 files changed, 251 insertions(+), 66 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 030f88c..2c8eab1 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -49,6 +49,7 @@ config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB select USB_ROLE_SWITCH + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 664463d..eba6bb8 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -99,11 +98,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -862,13 +856,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -884,11 +876,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1682,43 +1669,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get_property = fusb302_psy_get_property, -}; - static int init_gpio(struct fusb302_chip *chip) { struct device_node *node; @@ -1781,7 +1731,6 @@ static int fusb302_probe(struct i2c_client *client, struct fusb302_chip *chip; struct i2c_adapter *adapter; struct device *dev = &client->dev; - struct power_supply_config cfg = {}; const char *name; int ret = 0; u32 v; @@ -1823,14 +1772,6 @@ static int fusb302_probe(struct i2c_client *client, return -EPROBE_DEFER; } - cfg.drv_data = chip; - chip->psy = devm_power_supply_register(dev, &fusb302_psy_desc, &cfg); - if (IS_ERR(chip->psy)) { - ret = PTR_ERR(chip->psy); - dev_err(chip->dev, "Error registering power-supply: %d\n", ret); - return ret; - } - ret = fusb302_debugfs_init(chip); if (ret < 0) return ret; diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index b160da3..7547097 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,11 @@ struct tcpm_port { u32 current_limit; u32 supply_voltage; + /* Used to export TA voltage and current */ + struct power_supply *psy; + struct power_supply_desc psy_desc; + enum power_supply_usb_type usb_type; + u32 bist_request; /* PD state for Vendor Defined Messages */ @@ -1895,6 +1901,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, int ret = -EINVAL; port->pps_data.supported = false; + port->usb_type = POWER_SUPPLY_USB_TYPE_PD; /* * Select the source PDO providing the most power which has a @@ -1915,8 +1922,11 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, min_src_mv = pdo_min_voltage(pdo); break; case PDO_TYPE_APDO: - if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) + if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) { port->pps_data.supported = true; + port->usb_type = + POWER_SUPPLY_USB_TYPE_PD_PPS; + } continue; default: tcpm_log(port, "Invalid source PDO type, ignoring"); @@ -2472,6 +2482,9 @@ static void tcpm_reset_port(struct tcpm_port *port) port->try_snk_count = 0; port->supply_voltage = 0; port->current_limit = 0; + port->usb_type = POWER_SUPPLY_USB_TYPE_C; + + power_supply_changed(port->psy); } static void tcpm_detach(struct tcpm_port *port) @@ -2999,6 +3012,8 @@ static void run_state_machine(struct tcpm_port *port) tcpm_check_send_discover(port); tcpm_pps_complete(port, port->pps_status); + power_supply_changed(port->psy); + break; /* Accessory states */ @@ -3849,7 +3864,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role) return ret; } -static int __maybe_unused tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) +static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) { unsigned int target_mw; int ret; @@ -3901,7 +3916,7 @@ static int __maybe_unused tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_cu return ret; } -static int __maybe_unused tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) +static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) { unsigned int target_mw; int ret; @@ -3954,7 +3969,7 @@ static int __maybe_unused tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_ return ret; } -static int __maybe_unused tcpm_pps_activate(struct tcpm_port *port, bool activate) +static int tcpm_pps_activate(struct tcpm_port *port, bool activate) { int ret = 0; @@ -4159,6 +4174,230 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, } EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); +/* Power Supply access to expose source power information */ +enum tcpm_psy_online_states { + TCPM_PSY_OFFLINE = 0, + TCPM_PSY_FIXED_ONLINE, + TCPM_PSY_PROG_ONLINE, +}; + +static enum power_supply_property tcpm_psy_props[] = { + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, +}; + +static int tcpm_psy_get_online(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->vbus_charge) { + if (port->pps_data.active) + val->intval = TCPM_PSY_PROG_ONLINE; + else + val->intval = TCPM_PSY_FIXED_ONLINE; + } else { + val->intval = TCPM_PSY_OFFLINE; + } + + return 0; +} + +static int tcpm_psy_get_voltage_min(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->pps_data.active) + val->intval = port->pps_data.min_volt * 1000; + else + val->intval = port->supply_voltage * 1000; + + return 0; +} + +static int tcpm_psy_get_voltage_max(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->pps_data.active) + val->intval = port->pps_data.max_volt * 1000; + else + val->intval = port->supply_voltage * 1000; + + return 0; +} + +static int tcpm_psy_get_voltage_now(struct tcpm_port *port, + union power_supply_propval *val) +{ + val->intval = port->supply_voltage * 1000; + + return 0; +} + +static int tcpm_psy_get_current_max(struct tcpm_port *port, + union power_supply_propval *val) +{ + if (port->pps_data.active) + val->intval = port->pps_data.max_curr * 1000; + else + val->intval = port->current_limit * 1000; + + return 0; +} + +static int tcpm_psy_get_current_now(struct tcpm_port *port, + union power_supply_propval *val) +{ + val->intval = port->current_limit * 1000; + + return 0; +} + +static int tcpm_psy_get_prop(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct tcpm_port *port = power_supply_get_drvdata(psy); + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = port->usb_type; + break; + case POWER_SUPPLY_PROP_ONLINE: + ret = tcpm_psy_get_online(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + ret = tcpm_psy_get_voltage_min(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + ret = tcpm_psy_get_voltage_max(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret = tcpm_psy_get_voltage_now(port, val); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + ret = tcpm_psy_get_current_max(port, val); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + ret = tcpm_psy_get_current_now(port, val); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int tcpm_psy_set_online(struct tcpm_port *port, + const union power_supply_propval *val) +{ + int ret; + + switch (val->intval) { + case TCPM_PSY_FIXED_ONLINE: + ret = tcpm_pps_activate(port, false); + break; + case TCPM_PSY_PROG_ONLINE: + ret = tcpm_pps_activate(port, true); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int tcpm_psy_set_prop(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct tcpm_port *port = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + ret = tcpm_psy_set_online(port, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + if (val->intval < port->pps_data.min_volt * 1000 || + val->intval > port->pps_data.max_volt * 1000) + ret = -EINVAL; + else + ret = tcpm_pps_set_out_volt(port, val->intval / 1000); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + if (val->intval > port->pps_data.max_curr * 1000) + ret = -EINVAL; + else + ret = tcpm_pps_set_op_curr(port, val->intval / 1000); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int tcpm_psy_prop_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + case POWER_SUPPLY_PROP_CURRENT_NOW: + return 1; + default: + return 0; + } +} + +static enum power_supply_usb_type tcpm_psy_usb_types[] = { + POWER_SUPPLY_USB_TYPE_C, + POWER_SUPPLY_USB_TYPE_PD, + POWER_SUPPLY_USB_TYPE_PD_PPS, +}; + +static const char *tcpm_psy_name_prefix = "tcpm-source-psy-"; + +static int devm_tcpm_psy_register(struct tcpm_port *port) +{ + struct power_supply_config psy_cfg = {}; + const char *port_dev_name = dev_name(port->dev); + size_t psy_name_len = strlen(tcpm_psy_name_prefix) + + strlen(port_dev_name) + 1; + char *psy_name; + + psy_cfg.drv_data = port; + psy_name = devm_kzalloc(port->dev, psy_name_len, GFP_KERNEL); + if (!psy_name) + return -ENOMEM; + + snprintf(psy_name, psy_name_len, "%s%s", tcpm_psy_name_prefix, + port_dev_name); + port->psy_desc.name = psy_name; + port->psy_desc.type = POWER_SUPPLY_TYPE_USB, + port->psy_desc.usb_types = tcpm_psy_usb_types; + port->psy_desc.num_usb_types = ARRAY_SIZE(tcpm_psy_usb_types); + port->psy_desc.properties = tcpm_psy_props, + port->psy_desc.num_properties = ARRAY_SIZE(tcpm_psy_props), + port->psy_desc.get_property = tcpm_psy_get_prop, + port->psy_desc.set_property = tcpm_psy_set_prop, + port->psy_desc.property_is_writeable = tcpm_psy_prop_writeable, + + port->usb_type = POWER_SUPPLY_USB_TYPE_C; + + port->psy = devm_power_supply_register(port->dev, &port->psy_desc, + &psy_cfg); + + return PTR_ERR_OR_ZERO(port->psy); +} + struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) { struct tcpm_port *port; @@ -4234,6 +4473,10 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) goto out_destroy_wq; } + err = devm_tcpm_psy_register(port); + if (err) + goto out_destroy_wq; + port->typec_port = typec_register_port(port->dev, &port->typec_caps); if (IS_ERR(port->typec_port)) { err = PTR_ERR(port->typec_port); -- 1.9.1