From patchwork Thu Apr 30 03:33:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Sm9obnNvbiBDSCBDaGVuICjpmbPmmK3li7Mp?= X-Patchwork-Id: 13005302 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from APC01-PU1-obe.outbound.protection.outlook.com (APC01-PU1-obe.outbound.protection.outlook.com [40.107.132.55]) by mx.groups.io with SMTP id smtpd.web11.829.1588217631492708503 for ; Wed, 29 Apr 2020 20:33:52 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@moxa.com header.s=selector1 header.b=JcTk5QbH; spf=pass (domain: moxa.com, ip: 40.107.132.55, mailfrom: johnsonch.chen@moxa.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=k0vyJdpd4jXhYTwUsLWgX22CedpNSa3zAmInNC6dKoXpF9XeLuad/491Kw5kiFFI4+pU3uehtQJ2uXpyl6lC4Rw1sHOlpWDWn+t4cWQ9+NJTsCsUB7ml6Z2vpr4ssyQX4hkSo9ZwwFqdwHPRh8SAeFX+iqvsXS0AD45Jz9lXGSr/wLyvo+bVZqJi3EfeoWvACMiyXqPlWZN7enAjS9lP9YVJ+JIjB5UlFKAXlwlrNNzXGVE9iVO4S0CaGAEXFa5kHAnJzBJitb35eKaEawZDcjRY2np2c6eaNNIrIXAdGHFqZjHAbsnrVJG9QvWzONt1KUVNqk2ZcsgZsH9v2B4tMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=BcrlTVc7kJtLSBAUYyBECVl0twRYu8W8uFNb71D9yR0=; b=JHIEn5bP5jcAtEgXICzqtWyTkildc+j5gr38DxOuGqWsNAU0wS+TJhkMnOx0d6oMuMl/alJQVZ0+heVSoB4vg4lE1h+2p3b7YnzKzKxRuR/TnpP6RFAVZ6q0GRuJHTBYF0EJpSCL6OC2IDiFtVQ4TSsyShKSjLH6CwROScw/XJbfdUC0Xo0IWhhIHYhv9ig19gNyL3gxHiILgkLQe49+HovqksUdawViiHWPERHMGzhLQBNCdrYUzBAihPCVsnCUOHDcTX/Pa4AxL8YzPtJ0nPT6xc5jZxKGum9eBOFc+sjPAgrs9LGBepup2TrOTecroCR0g8cCgInRDiS0/WEnrA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=moxa.com; dmarc=pass action=none header.from=moxa.com; dkim=pass header.d=moxa.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=moxa.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=BcrlTVc7kJtLSBAUYyBECVl0twRYu8W8uFNb71D9yR0=; b=JcTk5QbHfG7utuQtbyLiH1xNWfQx+sZ7XV5j5OOq9XzsE9EsTg5chBffSk+qH4rQLGg/i5FQ5SextO/XqIAox/0GB+qyndNVMD4LkWmAy/AsTftbi31kOHMh6c6Zw6uGT4EBjrYEkbRKODouW97u/yzsye0ALm7HAiWLvgXe4Uc= Received: from HK2PR01MB3281.apcprd01.prod.exchangelabs.com (2603:1096:202:22::12) by HK2PR01MB3313.apcprd01.prod.exchangelabs.com (2603:1096:202:19::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2958.19; Thu, 30 Apr 2020 03:33:48 +0000 Received: from HK2PR01MB3281.apcprd01.prod.exchangelabs.com ([fe80::f0d1:8e7c:a9aa:46b1]) by HK2PR01MB3281.apcprd01.prod.exchangelabs.com ([fe80::f0d1:8e7c:a9aa:46b1%7]) with mapi id 15.20.2937.023; Thu, 30 Apr 2020 03:33:48 +0000 From: =?utf-8?b?Sm9obnNvbiBDSCBDaGVuICjpmbPmmK3li7Mp?= To: "cip-dev@lists.cip-project.org" , "nobuhiro1.iwamatsu@toshiba.co.jp" , "pavel@denx.de" Subject: [cip-dev] [PATCH 4.4.y-cip 2/3] PM / OPP: Parse 'opp-supported-hw' binding Thread-Topic: [cip-dev] [PATCH 4.4.y-cip 2/3] PM / OPP: Parse 'opp-supported-hw' binding Thread-Index: AdYenyd2Y/FHWYseQiebT5Joqk+ONA== Date: Thu, 30 Apr 2020 03:33:48 +0000 Message-ID: Accept-Language: zh-TW, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: lists.cip-project.org; dkim=none (message not signed) header.d=none;lists.cip-project.org; dmarc=none action=none header.from=moxa.com; x-originating-ip: [123.51.145.16] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 58e99d6a-2806-4465-8c21-08d7ecb74b98 x-ms-traffictypediagnostic: HK2PR01MB3313: x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:262; x-forefront-prvs: 0389EDA07F x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: xrkoMHclQGPJglfT57aCurn1ZSUClHB5bpkNJsMCjNpXOGbkPKkleCXOhIBe1m7WEn883FKT2y4xpDxPM6/YucymV2WDylrrZO/JSYUfqRdbcOoKfEIbbC55XM9s50CDJTGiH/MSCEC8hcesLtGxn9WmHMcvh9+YK9Ay0AeNWUYlnjvCpmegirx6myU4c08yo2NBNkTuJHYh4pB02kWivnNstB6XWqmpXpYwGL7SxU/MDgvlefDWUG99rFadgCUDP+zC1pBDd4CQ4qhEabFARvmIJsOemEK1voViX/iLu8gh2c6i0Ebb+qb0nIRGxrKLSdoyQCeTisaNMocoLd0aL2lQZd0QBX+MGFRjHmNXGJknVmqRm9v1rvIPtb4V0IvgD+XpNaSnojxFYYrQiLg8aKsJD6qz5ZixjG6Ix06KKiJYBuu4wBik1UsHKhH5FBL1 x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:HK2PR01MB3281.apcprd01.prod.exchangelabs.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(39850400004)(366004)(396003)(136003)(346002)(376002)(2906002)(71200400001)(55016002)(5660300002)(86362001)(110136005)(9686003)(52536014)(316002)(8936002)(64756008)(66946007)(66476007)(33656002)(8676002)(66556008)(478600001)(186003)(26005)(66446008)(76116006)(7696005)(85182001)(6506007);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata: W6X3WRSxH0+9Slb6crSvv9YOVsCluwV74ekF0rhpOeDgpsEdva0zNCBzo7XfTh7076XiOpxEJY33d0i7YrSXx6YeWR6vzwIIcJhx7K4QPm2WF456UMmfcWvmYmivwrgbvMpiTt4V5bDqe1ewBvcBvFnOKvzIHr3HF48IsnvHSWi93cpWdiMcXs54orzeox+rh8GYGDaYUumf++xNCXCDbHTl/PIycHpRZV9RGNPppdzYH+kqlbv4/xg/yAPcm1ARAGDgNlWvO1jYrUjYCoJ/FGK6R4T9FGFIH1TeGsABzeq0xJgy4m+0vXAHoQ6QPOu/QbuHofktq/FjTM/AStC4dL57uS8J+OJL9bJ8mhMeJ40T4ncoESw/TEX6T9uXipPBcbcQCax4kGEI5Y5cLQGMVp/wJ2nCd9ybNZCkjdNRvo14j4YnrDKYpymLpC6JkodXc1JKbko9seBBfP8blT2q1T+2euVd0e0aouxW1TyxN7Z+C03ty8nk78Gi+CBF4EUsAuPV85itaStxW7EG9lyEJPRdL22xF9SCWXZBPLPwYojyUbSzhri/mcwcwfBTeYzu2lg7j73m539iIFBwRijbqN7p+saB/odBhcMTIoXbafZkifQanCwGQHv7CxoGGk/x/hu9jklWEDxm0T1q3KNJx0DEJREANRKkwp2s2m6+JuFS64tTuZZl01PAszyHTydBFBG8QtcKlJ/lnC1su61S1Nej69rWwxYJs+8GdJO4WJ/d8cKidyT4+ti6/oomDascycIp+ZRM+5TRm1B6gXp08oDzG8DJmFjif1jj7Uur2kM= x-ms-exchange-transport-forked: True MIME-Version: 1.0 X-OriginatorOrg: moxa.com X-MS-Exchange-CrossTenant-Network-Message-Id: 58e99d6a-2806-4465-8c21-08d7ecb74b98 X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Apr 2020 03:33:48.6024 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 5571c7d4-286b-47f6-9dd5-0aa688773c8e X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: Q8cKy1aEMjNrxyfZWx2p3kmelVDSLts8lHLfAp+xB3qQk/8c4OiS9Z3XxSqLrgnPytE9Op8e/iGdMxa34MY1gA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: HK2PR01MB3313 Content-Language: zh-TW List-Id: From: Viresh Kumar commit 7de36b0aa51a5a59e28fb2da768fa3ab07de0674 upstream OPP bindings allow a platform to enable OPPs based on the version of the hardware they are used for. Add support to the OPP-core to parse these bindings, by introducing dev_pm_opp_{set|put}_supported_hw() APIs. Signed-off-by: Viresh Kumar Tested-by: Lee Jones Signed-off-by: Rafael J. Wysocki Signed-off-by: Johnson Chen Signed-off-by: Victor Yu --- drivers/base/power/opp/core.c | 148 ++++++++++++++++++++++++++++++++++++++++++ drivers/base/power/opp/opp.h | 6 ++ include/linux/pm_opp.h | 13 ++++ 3 files changed, 167 insertions(+) diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index e822dc706d67..c53a3e261306 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -551,6 +551,9 @@ static void _remove_device_opp(struct device_opp *dev_opp) if (!list_empty(&dev_opp->opp_list)) return; + if (dev_opp->supported_hw) + return; + list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp, node); @@ -825,6 +828,145 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev) } /** + * dev_pm_opp_set_supported_hw() - Set supported platforms + * @dev: Device for which supported-hw has to be set. + * @versions: Array of hierarchy of versions to match. + * @count: Number of elements in the array. + * + * This is required only for the V2 bindings, and it enables a platform to + * specify the hierarchy of versions it supports. OPP layer will then enable + * OPPs, which are available for those versions, based on its 'opp-supported-hw' + * property. + * + * Locking: The internal device_opp and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, + unsigned int count) +{ + struct device_opp *dev_opp; + int ret = 0; + + /* Hold our list modification lock here */ + mutex_lock(&dev_opp_list_lock); + + dev_opp = _add_device_opp(dev); + if (!dev_opp) { + ret = -ENOMEM; + goto unlock; + } + + /* Make sure there are no concurrent readers while updating dev_opp */ + WARN_ON(!list_empty(&dev_opp->opp_list)); + + /* Do we already have a version hierarchy associated with dev_opp? */ + if (dev_opp->supported_hw) { + dev_err(dev, "%s: Already have supported hardware list\n", + __func__); + ret = -EBUSY; + goto err; + } + + dev_opp->supported_hw = kmemdup(versions, count * sizeof(*versions), + GFP_KERNEL); + if (!dev_opp->supported_hw) { + ret = -ENOMEM; + goto err; + } + + dev_opp->supported_hw_count = count; + mutex_unlock(&dev_opp_list_lock); + return 0; + +err: + _remove_device_opp(dev_opp); +unlock: + mutex_unlock(&dev_opp_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw); + +/** + * dev_pm_opp_put_supported_hw() - Releases resources blocked for supported hw + * @dev: Device for which supported-hw has to be set. + * + * This is required only for the V2 bindings, and is called for a matching + * dev_pm_opp_set_supported_hw(). Until this is called, the device_opp structure + * will not be freed. + * + * Locking: The internal device_opp and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +void dev_pm_opp_put_supported_hw(struct device *dev) +{ + struct device_opp *dev_opp; + + /* Hold our list modification lock here */ + mutex_lock(&dev_opp_list_lock); + + /* Check for existing list for 'dev' first */ + dev_opp = _find_device_opp(dev); + if (IS_ERR(dev_opp)) { + dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp)); + goto unlock; + } + + /* Make sure there are no concurrent readers while updating dev_opp */ + WARN_ON(!list_empty(&dev_opp->opp_list)); + + if (!dev_opp->supported_hw) { + dev_err(dev, "%s: Doesn't have supported hardware list\n", + __func__); + goto unlock; + } + + kfree(dev_opp->supported_hw); + dev_opp->supported_hw = NULL; + dev_opp->supported_hw_count = 0; + + /* Try freeing device_opp if this was the last blocking resource */ + _remove_device_opp(dev_opp); + +unlock: + mutex_unlock(&dev_opp_list_lock); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw); + +static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp, + struct device_node *np) +{ + unsigned int count = dev_opp->supported_hw_count; + u32 version; + int ret; + + if (!dev_opp->supported_hw) + return true; + + while (count--) { + ret = of_property_read_u32_index(np, "opp-supported-hw", count, + &version); + if (ret) { + dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n", + __func__, count, ret); + return false; + } + + /* Both of these are bitwise masks of the versions */ + if (!(version & dev_opp->supported_hw[count])) + return false; + } + + return true; +} + +/** * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings) * @dev: device for which we do this operation * @np: device node @@ -870,6 +1012,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np) goto free_opp; } + /* Check if the OPP supports hardware's hierarchy of versions or not */ + if (!_opp_is_supported(dev, dev_opp, np)) { + dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate); + goto free_opp; + } + /* * Rate is defined as an unsigned long in clk API, and so casting * explicitly to its type. Must be fixed once rate is 64 bit diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 7366b2aa8997..b677670489e0 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -114,6 +114,9 @@ struct device_list_opp { * @opp_list: list of opps * @np: struct device_node pointer for opp's DT node. * @shared_opp: OPP is shared between multiple devices. + * @supported_hw: Array of version number to support. + * @supported_hw_count: Number of elements in supported_hw array. + * * This is an internal data structure maintaining the link to opps attached to * a device. This structure is not meant to be shared to users as it is @@ -135,6 +138,9 @@ struct device_opp { unsigned long clock_latency_ns_max; bool shared_opp; struct dev_pm_opp *suspend_opp; + unsigned int *supported_hw; + unsigned int supported_hw_count; + }; /* Routines internal to opp core */ diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 9a2e50337af9..3a85110242f0 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -55,6 +55,9 @@ int dev_pm_opp_enable(struct device *dev, unsigned long freq); int dev_pm_opp_disable(struct device *dev, unsigned long freq); struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev); +int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, + unsigned int count); +void dev_pm_opp_put_supported_hw(struct device *dev); #else static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { @@ -129,6 +132,16 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( { return ERR_PTR(-EINVAL); } + +static inline int dev_pm_opp_set_supported_hw(struct device *dev, + const u32 *versions, + unsigned int count) +{ + return -EINVAL; +} + +static inline void dev_pm_opp_put_supported_hw(struct device *dev) {} + #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)