From patchwork Wed Jun 29 13:52:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 9205311 X-Patchwork-Delegate: sboyd@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 84FB0607D8 for ; Wed, 29 Jun 2016 14:01:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7679E2865A for ; Wed, 29 Jun 2016 14:01:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6B3D62865C; Wed, 29 Jun 2016 14:01:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D2EF82865B for ; Wed, 29 Jun 2016 14:01:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752869AbcF2N72 (ORCPT ); Wed, 29 Jun 2016 09:59:28 -0400 Received: from mail-bn1on0083.outbound.protection.outlook.com ([157.56.110.83]:6416 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752536AbcF2N7Y (ORCPT ); Wed, 29 Jun 2016 09:59:24 -0400 Received: from BLUPR0301CA0029.namprd03.prod.outlook.com (10.162.113.167) by BY2PR03MB1927.namprd03.prod.outlook.com (10.164.114.31) with Microsoft SMTP Server (TLS) id 15.1.447.15; Wed, 29 Jun 2016 13:59:21 +0000 Received: from BY2FFO11FD046.protection.gbl (2a01:111:f400:7c0c::186) by BLUPR0301CA0029.outlook.office365.com (2a01:111:e400:5259::39) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.528.16 via Frontend Transport; Wed, 29 Jun 2016 13:59:20 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none; nxp.com; dmarc=fail action=none header.from=nxp.com; nxp.com; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BY2FFO11FD046.mail.protection.outlook.com (10.1.15.170) with Microsoft SMTP Server (TLS) id 15.1.523.9 via Frontend Transport; Wed, 29 Jun 2016 13:59:20 +0000 Received: from shlinux2.ap.freescale.net (shlinux2.ap.freescale.net [10.192.224.44]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id u5TDx9x4014881; Wed, 29 Jun 2016 06:59:16 -0700 From: Dong Aisheng To: CC: , , , , , , , , , , , Subject: [PATCH RFC 1/7] clk: add prepare_hw and prepare_done support Date: Wed, 29 Jun 2016 21:52:09 +0800 Message-ID: <1467208335-29876-2-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1467208335-29876-1-git-send-email-aisheng.dong@nxp.com> References: <1467208335-29876-1-git-send-email-aisheng.dong@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131116823606237562; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(2980300002)(1109001)(1110001)(339900001)(199003)(189002)(86362001)(85426001)(50226002)(33646002)(36756003)(229853001)(11100500001)(6806005)(586003)(68736007)(189998001)(356003)(7846002)(305945005)(77096005)(92566002)(48376002)(2950100001)(97736004)(50466002)(105606002)(2351001)(5003940100001)(106466001)(76176999)(87936001)(50986999)(8676002)(47776003)(8666005)(81156014)(19580405001)(2906002)(4326007)(81166006)(19580395003)(8936002)(110136002)(104016004)(7059030)(217873001); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR03MB1927; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD046; 1:mlY9i7ygSUu0GsONXssF74ynKxBstg5ggBA99ttoTXuItC6GYJGCekhGjwbZ+Ho0IUiGmc6agvzhz0Vu9SsdV50h/L8T1inOadudhMBGJnmTyag2d693uk+27xhTLNv20JqNYgmjgjt3heuZZ6LnXSy/rI40NCZ0uzh54UPzkxRhQ8l/4nSCmEPrUAHMBzKr5+cN3A8VDfVNRti0sYxT+Rar/t12qlrosyTjB2FMpHMfGo3mRnl/joggIZHbGDvygTYVkKj+lv+rFdxYXq9Vli7XcRa/qdPYDvQuporpXEqbz7/G5MzrWGiBI/TfRKaZqoAOk9OxVqR4wHfOJaPma7a7IuWR3lGDb0a3HY18j1fe3u+QKUJ48JMCIaJi7TRCaBjgNJrY6/ZXtA/Ltb1Xhjbl4YCivEfx6Z+xtoJ4Oe238crG6a6lf9ym7qQEyVF2pUM6NhJXeqTDIzzljQOiPNuUZ/IKg4Cwjogg1KvUtX6pk3LWEk+juaD/qifnDr/Es0Wn0ZYFwkNSIyycZR5m3/7/GXiJqpvnhY6W0FVhCyenmnVdErg6LtyRJUR/V5uuedweYHnA+HjtqHWjSRdmBbDO5BS3oBWF6ESOZb8Sxn+jLKptmlVFSz9Zq9Ib4aJkzEm/tbF2IV2UK7pJiwgyUTmFkk0qlj77zXX+9efGBAmOHSXykfAXPVnu3Ncq5xhHyz2D4hz8xrHUqjsfSHR2K/2zTIVKejBb5BlB7fXfNC4= MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: 731fd1ec-21d1-4d4f-997a-08d3a0259197 X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB1927; 2:EUlDSzIwILJxZ/IWvCuBYm5MopEPMJ0lGAGvpT2KAaU+eNh6qU+jtuVpCYkOymcrc9x18KyjM5rqTtRyqesOyxLUoASpJZzyo88nC78bSIFGva7qMyD1ZRQdGok4Qc7qQ5HAUK+TMDe923yDiL0VvovlUgISWE2s5ZvKgcaqYWPq6gPyy+Xb4c/9qWsYKr0T; 3:Yf/kJRZgR17FHBhF1G3cuZel1HX0xyH2qJ/JXn7InvZf12Coz4lMY/7z9ogwepaqKtIbJB8yQYKbglal82b8RZAddL5DiCYmsKJyj6E6H18xaHLpET30WKE5u17M/TdY+odOR5rSvBkB0DNB8/eRvoTQkv0KPiDJ9kpuEDcncDgnp3snQgn1BhMwmLwNqit4GFJyq4w+7SWeZj1dxyTLCrF9AUbHbgQdGhS/U7RQIOs=; 25:0sl2gqObMgh8LgModhqZQWL9hE/A0+K3BkpqQ5xJJSm+xQybsXsM8i7QsvukCLmLAPPJ8nhCutQpK8njSE3jrOUf10deso4Q7cUydb2ufCub8wcFRjKHMzwX1809MxhBXcTYqIFIEzSAO/nJJaJkeRHBzj0ZnSEuPxQUFiYjZlD6jk+CzVF151n5rp6Ot60xAuVSzKv1Hv8+V8B0QK75w4Ej0Y6CKvVuNfekvmKiWwkjdZKRSG7mnMQpqmmeNFC4 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR03MB1927; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(13018025)(8121501046)(13015025)(13023025)(13024025)(13017025)(3002001)(10201501046)(6055026); SRVR:BY2PR03MB1927; BCL:0; PCL:0; RULEID:(400006); SRVR:BY2PR03MB1927; X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB1927; 4:l13ixHK7t10px/pf0th7Jnmj38F8Oyw5L18syI6mibB7dN1njKIc1O0KW6aRrBK0nPXvsMoaPZ/2elSGaAc96+OrJCMIO4jzEzIHptV8VwOGk9exBEa33VUSideV6L5tOmc5Dd0otGaYtbeNPowq8clAYCrFSCw2ydB6PAjqUC3+jx7vu7G50QG3FgGV8oR+S1bqebw/3Pg3rGdqQlXrkFJETr8hUg15iHV71QKPt0LHqfjFG2GXjuqCHWiEvBBmX2xzXvKwJIQb/VnRvI/oI9sMsOSuaMdq0jJjw8U20rDBqqbwtNQRM28L27kJT8FLg+OA+Yh8fS+nDs3JVtsmzyAuWtD9BcNS2HC7/SaVsUgFodqyt18b5qNXWxT05Z+9jzKOECBpAMsEaaShEoAxAxPPCRrUAyvxUmpfnSeSoMZdOM7EETs557KzJ8nQizZExckJ7q5lmkTWOzSpu0QuKzWRxL9ScFO1qKBconYm3LU1OvGdDAMQWdETnmgvo4+GfL7R7AVdKVLSmeHlTtd6Jw== X-Forefront-PRVS: 09888BC01D X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR03MB1927; 23:TlM7t8fFLML+weMe2FycZzPT06YelBq+VubWmrKSv?= =?us-ascii?Q?lvcVWMJzTzOWfYu0QUmLXuB4fu3MID5evdgVryeDAMTDxXLHjktPt1YfdD5O?= =?us-ascii?Q?/ATSOHzf+FG9OigV3jc47vg07l6uGGLV5lE+o2MtBN3bu066TYdu3jXNxuIw?= =?us-ascii?Q?39GJ/S3fvLg+yh2m7FFSr3tTfiIXF7G47IRql53MVGgEQxByaiZVBKm1YHcZ?= =?us-ascii?Q?6J39EGGazD49ZY7qrHZnZzo/WCu9L5h7+h+Oc/GLy9frFj0SAOtkVaN3l1X3?= =?us-ascii?Q?NQgWy0ShJ/6/fRuPmOiACxWTiYI7umuAoGYyrqUjglqyr0tECEoemdwuyZA5?= =?us-ascii?Q?FPwNMG6XPt3X0pb5AOZYwf94YwwjajV40Shbtu9l95lxueyLnetcultiLq7J?= =?us-ascii?Q?Um0WMa+MDNdxwZ7JbHZrPZpHDg3UmYUi9O2xJY60pFuFFQrFboc/7l/a7bcx?= =?us-ascii?Q?qJWhiIdDPuWXp/neHkAm1yKvV2c+oHr8X3LUbrygXcXdhYcya9VlMCVZzRJ/?= =?us-ascii?Q?1ZTvZzJ7lRDcYco5vYNfalCkQVc5jr5tQBsnNUftlTbqKR7CtDGuFKrJONad?= =?us-ascii?Q?qVLdU8tFBVzr2RMbhkLp9hcx61C1tgJMRXjyW974n3J30F9om+LTi1nqQn5P?= =?us-ascii?Q?EyHgrz2shz41O9U89LELcdGqSmIuftX+o4dsNt+mjXmjSD6xLmvm3/xkc/xO?= =?us-ascii?Q?46l29pMvuU9gKgKN2/AlcAbGYpKTJkAM1U+G5n2eBatWPVVyNamUH4rX88CR?= =?us-ascii?Q?4lq6eZUa4kh0pSZnWuzcFmvQDaHOu7QSJ50+Mzo+eG1XFofuIyVO+JSrSQnj?= =?us-ascii?Q?/24E+S0GJXa7sN3Lw5wK2D/vbiyI2pdwZcvAc/QKqsZrzcgadEY9FtCk5pFR?= =?us-ascii?Q?v5zjA+Do2SvNYTnKDZZ2LPzKlxQEMmE3eAzAgg5XwIEEBsypX7p//SSCm3gP?= =?us-ascii?Q?BwFYh9VjkMY4nA3cFj32Cf4w3QpW9GYGWJm2GsQUAUxZgESmh5J7Ij9ETdsS?= =?us-ascii?Q?P2oMVitW86eqrGyej8Jvw//nZGW7DgBO1XywImV0J0vVcWcRTqnHNKrjBMBK?= =?us-ascii?Q?kGulveCfHS0LUl1Mu7qRb8B7p7S0DuRJytA6FHsF24YKAZMcCRDFna6Fa9tk?= =?us-ascii?Q?OhYBeXns6+m7ilXY9HWryuvj+ev8HvZNp2DPt0YjMjwxhFgDivPAkwghbGj7?= =?us-ascii?Q?41G1Dl1RpwHOxmhx2a5HW+6gJNHprjt9Ebr?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB1927; 5:WhtZbqLmCovhrONbtukQM8T6Qass+elt/kYiFXP7LtdXNxfWl9yloEWFQg5JcPu9+3NrL1h44kAV3exg+JYbc9yztPYyvjswVQQ3LssDSVYs9gGQyIkjqc2dv0pZ8G2vUbwZIVRn7wvJurI5t/KU0knTWJ1xMAgMbKDsxKrHUzg=; 24:DM6KDMxRBDkeybTjy/+E2SeUSlDKK5JYN/Zhu/9TzGMTJZ0oQQZ9IJ88CKA6KuH9VZFXZqalPov8Q4Hdffq2//t99V5suCC+HKciqvqdwuY= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jun 2016 13:59:20.4209 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR03MB1927 Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Introduce prepare_hw and prepare_done to support calling clk_prepare_enable in early kernel booting where we still can't schedule. The prepare_hw callback is intended to do the hw part initialization of prepare work. It should cooperate with prepare_done callback to do the whole prepare work. The clock core will check @prepare_done in sleep or polling way according to system state to decide whether the whole prepare work is done. Suggested-by: Thomas Gleixner Signed-off-by: Dong Aisheng --- drivers/clk/clk.c | 57 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/clk-provider.h | 32 +++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d584004f7af7..7dcb34c75a9f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,8 @@ struct clk_core { bool orphan; unsigned int enable_count; unsigned int prepare_count; + unsigned long delay_min; + unsigned long delay_max; unsigned long min_rate; unsigned long max_rate; unsigned long accuracy; @@ -566,6 +569,8 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); static void clk_core_unprepare(struct clk_core *core) { + unsigned long timeout; + lockdep_assert_held(&prepare_lock); if (!core) @@ -584,8 +589,30 @@ static void clk_core_unprepare(struct clk_core *core) trace_clk_unprepare(core); - if (core->ops->unprepare) + if (core->ops->unprepare) { core->ops->unprepare(core->hw); + } else if (core->ops->unprepare_hw) { + core->ops->unprepare_hw(core->hw); + if (core->ops->unprepare_done) { + timeout = jiffies + msecs_to_jiffies(10); + while (!core->ops->unprepare_done(core->hw)) { + if (time_after(jiffies, timeout)) { + pr_err("%s: clock %s unprepare timeout\n", + __func__, core->name); + break; + } + if (system_state == SYSTEM_BOOTING) + /* + * Busy loop as we can't schedule in + * early boot + */ + continue; + else + usleep_range(core->delay_min, + core->delay_max); + } + } + } trace_clk_unprepare_complete(core); clk_core_unprepare(core->parent); @@ -615,6 +642,7 @@ EXPORT_SYMBOL_GPL(clk_unprepare); static int clk_core_prepare(struct clk_core *core) { + unsigned long timeout; int ret = 0; lockdep_assert_held(&prepare_lock); @@ -629,8 +657,31 @@ static int clk_core_prepare(struct clk_core *core) trace_clk_prepare(core); - if (core->ops->prepare) + if (core->ops->prepare) { ret = core->ops->prepare(core->hw); + } else if (core->ops->prepare_hw) { + ret = core->ops->prepare_hw(core->hw); + if (!ret && core->ops->prepare_done) { + timeout = jiffies + msecs_to_jiffies(10); + while (!core->ops->prepare_done(core->hw)) { + if (time_after(jiffies, timeout)) { + pr_err("%s: clock %s prepare timeout\n", + __func__, core->name); + ret = -ETIMEDOUT; + break; + } + if (system_state == SYSTEM_BOOTING) + /* + * Busy loop as we can't + * schedule in early boot + */ + continue; + else + usleep_range(core->delay_min, + core->delay_max); + } + } + } trace_clk_prepare_complete(core); @@ -2490,6 +2541,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) core->hw = hw; core->flags = hw->init->flags; core->num_parents = hw->init->num_parents; + core->delay_min = hw->init->delay_min; + core->delay_max = hw->init->delay_max; core->min_rate = 0; core->max_rate = ULONG_MAX; hw->core = core; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index fb39d5add173..b37174360f1c 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -72,10 +72,34 @@ struct clk_rate_request { * do any initialisation that may sleep. Called with * prepare_lock held. * + * @prepare_hw: Prepare the clock hw for enabling. This callback is intended + * to do the hw part initialization of prepare work. It should + * cooperate with @prepare_done callback to do the whole prepare + * work. The clock core will check @prepare_done in sleep or + * polling way according to system state to decide whether the + * whole prepare work is done. Optional if @prepare is used. + * This function must not sleep. + * + * @prepare_done: Queries the hardware to determine if the clock hw is prepared. + * Optional, if this op is not set then the prepare simply return. + * This function must not sleep. + * * @unprepare: Release the clock from its prepared state. This will typically * undo any work done in the @prepare callback. Called with * prepare_lock held. * + * @unprepare_hw: Release the clock from its prepared hw state. This will + * typically undo any work done in the @prepare_hw callback. + * It should cooperate with @unprepare_done callback to + * do the whole unprepare work. The clock core will check + * @unprepare_done in either sleep or polling way according to + * system state to decide whether the whole unprepare work is done. + * Optional if @prepare is used. This function must not sleep. + * + * @unprepare_done: Queries the hardware to determine if the clock hw + * is unprepared. Optional, if this op is not set then the + * unprepare simply return. This function must not sleep. + * * @is_prepared: Queries the hardware to determine if the clock is prepared. * This function is allowed to sleep. Optional, if this op is not * set then the prepare count will be used. @@ -189,7 +213,11 @@ struct clk_rate_request { */ struct clk_ops { int (*prepare)(struct clk_hw *hw); + int (*prepare_hw)(struct clk_hw *hw); + int (*prepare_done)(struct clk_hw *hw); void (*unprepare)(struct clk_hw *hw); + void (*unprepare_hw)(struct clk_hw *hw); + int (*unprepare_done)(struct clk_hw *hw); int (*is_prepared)(struct clk_hw *hw); void (*unprepare_unused)(struct clk_hw *hw); int (*enable)(struct clk_hw *hw); @@ -226,6 +254,8 @@ struct clk_ops { * @parent_names: array of string names for all possible parents * @num_parents: number of possible parents * @flags: framework-level hints and quirks + * @delay_min: min delays in us for clock hw prepare + * @delay_max: max delays in us for clock hw prepare */ struct clk_init_data { const char *name; @@ -233,6 +263,8 @@ struct clk_init_data { const char * const *parent_names; u8 num_parents; unsigned long flags; + unsigned int delay_min; + unsigned int delay_max; }; /**