From patchwork Thu Feb 21 15:25:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1046206 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="G2f/oGpE"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 444ywr0XJ7z9sBF for ; Fri, 22 Feb 2019 02:26:04 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727611AbfBUP0D (ORCPT ); Thu, 21 Feb 2019 10:26:03 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:46812 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727527AbfBUP0C (ORCPT ); Thu, 21 Feb 2019 10:26:02 -0500 Received: by mail-wr1-f66.google.com with SMTP id i16so22756891wrs.13; Thu, 21 Feb 2019 07:26:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=2mPuomQdxwqWDdG5gE3W/vPTRBsJaygtW8uJE6nsHgs=; b=G2f/oGpE/YIvrDT0Wk1FlV4o5enGTcVXPPm7PK5mdHxgjyxlhdy42sNJrVprVsQ9b+ iN47lTgcqHUu8WpexU3opJs820EiWWgRkkYGd0CyLplROqJxrHOS87bqwU/r6gTSDnx3 lwLdsO9anfakvo9+3y7mNQWXLzC1xtFcZE94atc4gZxpN5rbyFXRN0g4iiDL79XznpFv QqYqyJcGmbMgk2Pk0cyocLPJRTUOE2U74aJzW5HKEuu95Bihbszq7PI/o4UQX0pA3SFI VRHRFq/ecA0v6oZ0ZS199zIdk78wTDAc3jBaLlvXmQpqgAH21Pnr2KYfeCAmHnAef3XK so4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=2mPuomQdxwqWDdG5gE3W/vPTRBsJaygtW8uJE6nsHgs=; b=QA+2EMzDILbnYM+VV5VbqLMpdBHMjRg8gGTGBY28jfeDKUqSDFjFyAnEwipvG6esNi 40Rm5VK7L+wchA7ksvL6Tt3BwMux+JQ4i07DEgfW6znmMEEioDHES+fhmOchGTP7ea6Y +6WW0c6pDp5xXEB9GF7c4FgyzHQq/QAwGuqpT17JADf4YoNhu3tifNjMeofgCiP8QIxO quFVnRHcNN+waS4vdLyGpQK5USSJ8n+JkaE9zYv2mBNjeo81SCRgo/tY15szJSmMUFyj cgCDWYMLYSCLCcyHzBOEIAV1BwZm5lAZseYscGIgTL7oFPAPjIfFPZ/e/TU6T5YPoe1J 2RuQ== X-Gm-Message-State: AHQUAuYbspTh9YaPb4K6EHA4TW50Wonbud9094iFrNSvUJ7oE1U+auY6 YM0zIk1BqYrUs8+aD9DL6bU= X-Google-Smtp-Source: AHgI3IavC27+If29yMbN0ki/mlVjQGOZP44RCpyWg5wuHEqrcJa7N5Gus1+Ec7txtpD2K9a9bO5FUw== X-Received: by 2002:a05:600c:2144:: with SMTP id v4mr10617956wml.4.1550762759160; Thu, 21 Feb 2019 07:25:59 -0800 (PST) Received: from localhost (pD9E51D2D.dip0.t-ipconnect.de. [217.229.29.45]) by smtp.gmail.com with ESMTPSA id a1sm22260280wrq.96.2019.02.21.07.25.58 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 21 Feb 2019 07:25:58 -0800 (PST) From: Thierry Reding To: Philipp Zabel Cc: Jonathan Hunter , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/5] reset: add acquired/released state for exclusive reset controls Date: Thu, 21 Feb 2019 16:25:53 +0100 Message-Id: <20190221152557.8534-1-thierry.reding@gmail.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Philipp Zabel There are cases where a driver needs explicit control over a reset line that is exclusively conneted to its device, but this control has to be temporarily handed over to the power domain controller to handle reset requirements during power transitions. Allow multiple exclusive reset controls to be requested in 'released' state for the same physical reset line, only one of which can be acquired at the same time. Signed-off-by: Philipp Zabel Signed-off-by: Thierry Reding --- drivers/reset/core.c | 139 ++++++++++++++++++++++++++++++++++++++---- include/linux/reset.h | 93 ++++++++++++++++++++++------ 2 files changed, 200 insertions(+), 32 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 9582efb70025..1e8a42b16f23 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -34,6 +34,7 @@ static LIST_HEAD(reset_lookup_list); * @id: ID of the reset controller in the reset * controller device * @refcnt: Number of gets of this reset_control + * @acquired: Only one reset_control may be acquired for a given rcdev and id. * @shared: Is this a shared (1), or an exclusive (0) reset_control? * @deassert_cnt: Number of times this reset line has been deasserted * @triggered_count: Number of times this reset line has been reset. Currently @@ -45,6 +46,7 @@ struct reset_control { struct list_head list; unsigned int id; struct kref refcnt; + bool acquired; bool shared; bool array; atomic_t deassert_count; @@ -63,6 +65,17 @@ struct reset_control_array { struct reset_control *rstc[]; }; +static const char *rcdev_name(struct reset_controller_dev *rcdev) +{ + if (rcdev->dev) + return dev_name(rcdev->dev); + + if (rcdev->of_node) + return rcdev->of_node->full_name; + + return NULL; +} + /** * of_reset_simple_xlate - translate reset_spec to the reset line number * @rcdev: a pointer to the reset controller device @@ -272,6 +285,9 @@ int reset_control_reset(struct reset_control *rstc) if (atomic_inc_return(&rstc->triggered_count) != 1) return 0; + } else { + if (!rstc->acquired) + return -EPERM; } ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); @@ -334,6 +350,12 @@ int reset_control_assert(struct reset_control *rstc) */ if (!rstc->rcdev->ops->assert) return -ENOTSUPP; + + if (!rstc->acquired) { + WARN(1, "reset %s (ID: %u) is not acquired\n", + rcdev_name(rstc->rcdev), rstc->id); + return -EPERM; + } } return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); @@ -369,6 +391,12 @@ int reset_control_deassert(struct reset_control *rstc) if (atomic_inc_return(&rstc->deassert_count) != 1) return 0; + } else { + if (!rstc->acquired) { + WARN(1, "reset %s (ID: %u) is not acquired\n", + rcdev_name(rstc->rcdev), rstc->id); + return -EPERM; + } } /* @@ -406,9 +434,81 @@ int reset_control_status(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_status); +/** + * reset_control_acquire() - acquires a reset control for exclusive use + * @rstc: reset control + * + * This is used to explicitly acquire a reset control for exclusive use. Note + * that exclusive resets are requested as acquired by default. In order for a + * second consumer to be able to control the reset, the first consumer has to + * release it first. Typically the easiest way to achieve this is to call the + * reset_control_get_exclusive_released() to obtain an instance of the reset + * control. Such reset controls are not acquired by default. + * + * Consumers implementing shared access to an exclusive reset need to follow + * a specific protocol in order to work together. Before consumers can change + * a reset they must acquire exclusive access using reset_control_acquire(). + * After they are done operating the reset, they must release exclusive access + * with a call to reset_control_release(). Consumers are not granted exclusive + * access to the reset as long as another consumer hasn't released a reset. + * + * See also: reset_control_release() + */ +int reset_control_acquire(struct reset_control *rstc) +{ + struct reset_control *rc; + + if (!rstc) + return 0; + + if (WARN_ON(IS_ERR(rstc))) + return -EINVAL; + + mutex_lock(&reset_list_mutex); + + if (rstc->acquired) { + mutex_unlock(&reset_list_mutex); + return 0; + } + + list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { + if (rstc != rc && rstc->id == rc->id) { + if (rc->acquired) { + mutex_unlock(&reset_list_mutex); + return -EBUSY; + } + } + } + + rstc->acquired = true; + + mutex_unlock(&reset_list_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(reset_control_acquire); + +/** + * reset_control_release() - releases exclusive access to a reset control + * @rstc: reset control + * + * Releases exclusive access right to a reset control previously obtained by a + * call to reset_control_acquire(). Until a consumer calls this function, no + * other consumers will be granted exclusive access. + * + * See also: reset_control_acquire() + */ +void reset_control_release(struct reset_control *rstc) +{ + if (!rstc || WARN_ON(IS_ERR(rstc))) + return; + + rstc->acquired = false; +} +EXPORT_SYMBOL_GPL(reset_control_release); + static struct reset_control *__reset_control_get_internal( struct reset_controller_dev *rcdev, - unsigned int index, bool shared) + unsigned int index, bool shared, bool acquired) { struct reset_control *rstc; @@ -416,6 +516,14 @@ static struct reset_control *__reset_control_get_internal( list_for_each_entry(rstc, &rcdev->reset_control_head, list) { if (rstc->id == index) { + /* + * Allow creating a secondary exclusive reset_control + * that is initially not acquired for an already + * controlled reset line. + */ + if (!rstc->shared && !shared && !acquired) + break; + if (WARN_ON(!rstc->shared || !shared)) return ERR_PTR(-EBUSY); @@ -434,6 +542,7 @@ static struct reset_control *__reset_control_get_internal( list_add(&rstc->list, &rcdev->reset_control_head); rstc->id = index; kref_init(&rstc->refcnt); + rstc->acquired = acquired; rstc->shared = shared; return rstc; @@ -461,7 +570,7 @@ static void __reset_control_put_internal(struct reset_control *rstc) struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, - bool optional) + bool optional, bool acquired) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; @@ -514,7 +623,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } /* reset_list_mutex also protects the rcdev's reset_control list */ - rstc = __reset_control_get_internal(rcdev, rstc_id, shared); + rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired); out: mutex_unlock(&reset_list_mutex); @@ -544,7 +653,7 @@ __reset_controller_by_name(const char *name) static struct reset_control * __reset_control_get_from_lookup(struct device *dev, const char *con_id, - bool shared, bool optional) + bool shared, bool optional, bool acquired) { const struct reset_control_lookup *lookup; struct reset_controller_dev *rcdev; @@ -574,7 +683,7 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, rstc = __reset_control_get_internal(rcdev, lookup->index, - shared); + shared, acquired); mutex_unlock(&reset_list_mutex); break; } @@ -589,13 +698,18 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, } struct reset_control *__reset_control_get(struct device *dev, const char *id, - int index, bool shared, bool optional) + int index, bool shared, bool optional, + bool acquired) { + if (WARN_ON(shared && acquired)) + return ERR_PTR(-EINVAL); + if (dev->of_node) return __of_reset_control_get(dev->of_node, id, index, shared, - optional); + optional, acquired); - return __reset_control_get_from_lookup(dev, id, shared, optional); + return __reset_control_get_from_lookup(dev, id, shared, optional, + acquired); } EXPORT_SYMBOL_GPL(__reset_control_get); @@ -636,7 +750,7 @@ static void devm_reset_control_release(struct device *dev, void *res) struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, - bool optional) + bool optional, bool acquired) { struct reset_control **ptr, *rstc; @@ -645,7 +759,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); - rstc = __reset_control_get(dev, id, index, shared, optional); + rstc = __reset_control_get(dev, id, index, shared, optional, acquired); if (!IS_ERR(rstc)) { *ptr = rstc; devres_add(dev, ptr); @@ -672,7 +786,7 @@ int __device_reset(struct device *dev, bool optional) struct reset_control *rstc; int ret; - rstc = __reset_control_get(dev, NULL, 0, 0, optional); + rstc = __reset_control_get(dev, NULL, 0, 0, optional, true); if (IS_ERR(rstc)) return PTR_ERR(rstc); @@ -736,7 +850,8 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) return ERR_PTR(-ENOMEM); for (i = 0; i < num; i++) { - rstc = __of_reset_control_get(np, NULL, i, shared, optional); + rstc = __of_reset_control_get(np, NULL, i, shared, optional, + true); if (IS_ERR(rstc)) goto err_rst; resets->rstc[i] = rstc; diff --git a/include/linux/reset.h b/include/linux/reset.h index c1901b61ca30..ea9a8a1ce4b1 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -14,18 +14,20 @@ int reset_control_reset(struct reset_control *rstc); int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc); +int reset_control_acquire(struct reset_control *rstc); +void reset_control_release(struct reset_control *rstc); struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, - bool optional); + bool optional, bool acquired); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, - bool optional); + bool optional, bool acquired); void reset_control_put(struct reset_control *rstc); int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, - bool optional); + bool optional, bool acquired); struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); @@ -56,6 +58,15 @@ static inline int reset_control_status(struct reset_control *rstc) return 0; } +static inline int reset_control_acquire(struct reset_control *rstc) +{ + return 0; +} + +static inline void reset_control_release(struct reset_control *rstc) +{ +} + static inline void reset_control_put(struct reset_control *rstc) { } @@ -68,21 +79,23 @@ static inline int __device_reset(struct device *dev, bool optional) static inline struct reset_control *__of_reset_control_get( struct device_node *node, const char *id, int index, bool shared, - bool optional) + bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__reset_control_get( struct device *dev, const char *id, - int index, bool shared, bool optional) + int index, bool shared, bool optional, + bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__devm_reset_control_get( struct device *dev, const char *id, - int index, bool shared, bool optional) + int index, bool shared, bool optional, + bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } @@ -134,7 +147,28 @@ static inline int device_reset_optional(struct device *dev) static inline struct reset_control * __must_check reset_control_get_exclusive(struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, false, false); + return __reset_control_get(dev, id, 0, false, false, true); +} + +/** + * reset_control_get_exclusive_released - Lookup and obtain a temoprarily + * exclusive reference to a reset + * controller. + * @dev: device to be reset by the controller + * @id: reset line name + * + * Returns a struct reset_control or IS_ERR() condition containing errno. + * reset-controls returned by this function must be acquired via + * reset_control_acquire() before they can be used and should be released + * via reset_control_release() afterwards. + * + * Use of id names is optional. + */ +static inline struct reset_control * +__must_check reset_control_get_exclusive_released(struct device *dev, + const char *id) +{ + return __reset_control_get(dev, id, 0, false, false, false); } /** @@ -162,19 +196,19 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) static inline struct reset_control *reset_control_get_shared( struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, true, false); + return __reset_control_get(dev, id, 0, true, false, false); } static inline struct reset_control *reset_control_get_optional_exclusive( struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, false, true); + return __reset_control_get(dev, id, 0, false, true, true); } static inline struct reset_control *reset_control_get_optional_shared( struct device *dev, const char *id) { - return __reset_control_get(dev, id, 0, true, true); + return __reset_control_get(dev, id, 0, true, true, false); } /** @@ -190,7 +224,7 @@ static inline struct reset_control *reset_control_get_optional_shared( static inline struct reset_control *of_reset_control_get_exclusive( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, false, false); + return __of_reset_control_get(node, id, 0, false, false, true); } /** @@ -215,7 +249,7 @@ static inline struct reset_control *of_reset_control_get_exclusive( static inline struct reset_control *of_reset_control_get_shared( struct device_node *node, const char *id) { - return __of_reset_control_get(node, id, 0, true, false); + return __of_reset_control_get(node, id, 0, true, false, false); } /** @@ -232,7 +266,7 @@ static inline struct reset_control *of_reset_control_get_shared( static inline struct reset_control *of_reset_control_get_exclusive_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index, false, false); + return __of_reset_control_get(node, NULL, index, false, false, true); } /** @@ -260,7 +294,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( static inline struct reset_control *of_reset_control_get_shared_by_index( struct device_node *node, int index) { - return __of_reset_control_get(node, NULL, index, true, false); + return __of_reset_control_get(node, NULL, index, true, false, false); } /** @@ -279,7 +313,26 @@ static inline struct reset_control * __must_check devm_reset_control_get_exclusive(struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, false, false); + return __devm_reset_control_get(dev, id, 0, false, false, true); +} + +/** + * devm_reset_control_get_exclusive_released - resource managed + * reset_control_get_exclusive_released() + * @dev: device to be reset by the controller + * @id: reset line name + * + * Managed reset_control_get_exclusive_released(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_get_exclusive_released() for more information. + */ +static inline struct reset_control * +__must_check devm_reset_control_get_exclusive_released(struct device *dev, + const char *id) +{ + return __devm_reset_control_get(dev, id, 0, false, false, false); } /** @@ -294,19 +347,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, static inline struct reset_control *devm_reset_control_get_shared( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, true, false); + return __devm_reset_control_get(dev, id, 0, true, false, false); } static inline struct reset_control *devm_reset_control_get_optional_exclusive( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, false, true); + return __devm_reset_control_get(dev, id, 0, false, true, true); } static inline struct reset_control *devm_reset_control_get_optional_shared( struct device *dev, const char *id) { - return __devm_reset_control_get(dev, id, 0, true, true); + return __devm_reset_control_get(dev, id, 0, true, true, false); } /** @@ -324,7 +377,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( static inline struct reset_control * devm_reset_control_get_exclusive_by_index(struct device *dev, int index) { - return __devm_reset_control_get(dev, NULL, index, false, false); + return __devm_reset_control_get(dev, NULL, index, false, false, true); } /** @@ -340,7 +393,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index) static inline struct reset_control * devm_reset_control_get_shared_by_index(struct device *dev, int index) { - return __devm_reset_control_get(dev, NULL, index, true, false); + return __devm_reset_control_get(dev, NULL, index, true, false, false); } /* From patchwork Thu Feb 21 15:25:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1046209 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ZbzA/zCl"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 444yxL4n5Hz9sBF for ; Fri, 22 Feb 2019 02:26:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728194AbfBUP0E (ORCPT ); Thu, 21 Feb 2019 10:26:04 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:41331 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725858AbfBUP0D (ORCPT ); Thu, 21 Feb 2019 10:26:03 -0500 Received: by mail-wr1-f65.google.com with SMTP id n2so18828627wrw.8; Thu, 21 Feb 2019 07:26:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=a/kMhZeaVVw1leKshC6LSw8+0RsVdtfnkg3LU9kcxgM=; b=ZbzA/zClhl8m0H+joiR9M1gAFGiE9EzaPIb8Re70ZUssdFul6ZuyD1kDpDFqWZTrLw EqxVvS7y3Oc5PU5jr33iyrOL8GUIw6ww3tvcCQgX1O2ShdLQwJmzj1STSYZyxGTc0E71 hdZp8GqzPr8CIVofE9ZlM5dCnjTaUVvincZpGe3R2ylGnzbbfXGpM9VGg/OjGL2Ohv7J L4tIbZFFSAEXMhSNE5TXcP+GRvM7lpIY84H+XRvr1L9C55PqSzvIDzZxZblXggoQnG2U cf+kyQ61vknm7+VcFc3iYOnrlGQDMJ67aOoNqA4nQGs/KTlmlchc5AOnx6iAM+ABJ/wu 88xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=a/kMhZeaVVw1leKshC6LSw8+0RsVdtfnkg3LU9kcxgM=; b=WVQ/F2UqyMdanJCRwS6AjF8ENSvPbdE6RziVdspv40YYjuDixKkDwT+Q0OwPLmdlBn qlAsCfkv5sxB0ugfvITRhKOJnuiXxkqSiBIUsOCSYjZWL6VeMl3b4CfmoXfCxqazEsOy Iz+uu8SUcCJQu2vy6FlkKFssitGfWXW3N+8iN+hVD8TGf/v90Zx2J5ubWl53CIXR+kvP 7zDzMKGWhZt6JWcpRdGoTKnWdjwS/kaKO7LpKKMKsARLFHuSVz/jzblnnAgwRqQRziOy ALjrbsS0uTGdQmAGqKKS9Q9HflFIOSZdjzhnV5F5mPivO0GP6VE9PKw49St4L78JnwcG Chmw== X-Gm-Message-State: AHQUAubJunI24g3FzxJLSeo1/3FN0Q2Ahk5gLfQNxh55k1bCr/NtFQln hmU36Xqm4mgesaLEv/yqnqU= X-Google-Smtp-Source: AHgI3IZvpR+6HqzFnM7Ca+7bPWv5SAy0Dx5lUe+3n1xSMl0ZDhxvoUjtlcDWpj2/Ug7apms79CH8eA== X-Received: by 2002:a5d:54cc:: with SMTP id x12mr19665749wrv.323.1550762760655; Thu, 21 Feb 2019 07:26:00 -0800 (PST) Received: from localhost (pD9E51D2D.dip0.t-ipconnect.de. [217.229.29.45]) by smtp.gmail.com with ESMTPSA id d24sm70587132wrb.47.2019.02.21.07.25.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 21 Feb 2019 07:26:00 -0800 (PST) From: Thierry Reding To: Philipp Zabel Cc: Jonathan Hunter , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org, Felipe Balbi , Greg Kroah-Hartman , linux-usb@vger.kernel.org Subject: [PATCH 2/5] reset: Add acquired flag to of_reset_control_array_get() Date: Thu, 21 Feb 2019 16:25:54 +0100 Message-Id: <20190221152557.8534-2-thierry.reding@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190221152557.8534-1-thierry.reding@gmail.com> References: <20190221152557.8534-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Thierry Reding In order to be able to request an array of reset controls in acquired or released mode, add the acquired flag to of_reset_control_array_get() and pass the flag to subsequent calls of __of_reset_control_get(). Signed-off-by: Thierry Reding Acked-by: Felipe Balbi --- drivers/reset/core.c | 9 ++++++--- drivers/usb/dwc3/dwc3-of-simple.c | 3 ++- include/linux/reset.h | 14 ++++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 1e8a42b16f23..f94da91c22af 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -830,12 +830,15 @@ static int of_reset_control_get_count(struct device_node *node) * @np: device node for the device that requests the reset controls array * @shared: whether reset controls are shared or not * @optional: whether it is optional to get the reset controls + * @acquired: only one reset control may be acquired for a given controller + * and ID * * Returns pointer to allocated reset_control_array on success or * error on failure */ struct reset_control * -of_reset_control_array_get(struct device_node *np, bool shared, bool optional) +of_reset_control_array_get(struct device_node *np, bool shared, bool optional, + bool acquired) { struct reset_control_array *resets; struct reset_control *rstc; @@ -851,7 +854,7 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) for (i = 0; i < num; i++) { rstc = __of_reset_control_get(np, NULL, i, shared, optional, - true); + acquired); if (IS_ERR(rstc)) goto err_rst; resets->rstc[i] = rstc; @@ -898,7 +901,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) if (!devres) return ERR_PTR(-ENOMEM); - rstc = of_reset_control_array_get(dev->of_node, shared, optional); + rstc = of_reset_control_array_get(dev->of_node, shared, optional, true); if (IS_ERR(rstc)) { devres_free(devres); return rstc; diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 4c2771c5e727..67ce2037472d 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -107,7 +107,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) simple->pulse_resets = true; } - simple->resets = of_reset_control_array_get(np, shared_resets, true); + simple->resets = of_reset_control_array_get(np, shared_resets, true, + true); if (IS_ERR(simple->resets)) { ret = PTR_ERR(simple->resets); dev_err(dev, "failed to get device resets, err=%d\n", ret); diff --git a/include/linux/reset.h b/include/linux/reset.h index ea9a8a1ce4b1..a01b32bf51d4 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -32,7 +32,8 @@ struct reset_control *__devm_reset_control_get(struct device *dev, struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); struct reset_control *of_reset_control_array_get(struct device_node *np, - bool shared, bool optional); + bool shared, bool optional, + bool acquired); int reset_control_get_count(struct device *dev); @@ -107,7 +108,8 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) } static inline struct reset_control * -of_reset_control_array_get(struct device_node *np, bool shared, bool optional) +of_reset_control_array_get(struct device_node *np, bool shared, bool optional, + bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } @@ -465,24 +467,24 @@ devm_reset_control_array_get_optional_shared(struct device *dev) static inline struct reset_control * of_reset_control_array_get_exclusive(struct device_node *node) { - return of_reset_control_array_get(node, false, false); + return of_reset_control_array_get(node, false, false, true); } static inline struct reset_control * of_reset_control_array_get_shared(struct device_node *node) { - return of_reset_control_array_get(node, true, false); + return of_reset_control_array_get(node, true, false, true); } static inline struct reset_control * of_reset_control_array_get_optional_exclusive(struct device_node *node) { - return of_reset_control_array_get(node, false, true); + return of_reset_control_array_get(node, false, true, true); } static inline struct reset_control * of_reset_control_array_get_optional_shared(struct device_node *node) { - return of_reset_control_array_get(node, true, true); + return of_reset_control_array_get(node, true, true, true); } #endif From patchwork Thu Feb 21 15:25:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1046210 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="eRAuvmU6"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 444yxR4ss7z9sBF for ; Fri, 22 Feb 2019 02:26:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728248AbfBUP0a (ORCPT ); Thu, 21 Feb 2019 10:26:30 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:36760 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726413AbfBUP0E (ORCPT ); Thu, 21 Feb 2019 10:26:04 -0500 Received: by mail-wr1-f68.google.com with SMTP id o17so31015217wrw.3; Thu, 21 Feb 2019 07:26:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fEjER1QD2Tnm8PA8oEKeSor0Ppgc9jB1pMOYk91Kf9w=; b=eRAuvmU6wHfCWERjzw5d4lpj0sp0an9YXnPTTSHLnXzMQMC6r58jC/3bB6GjKhIK7R h2i9UO1RBDe2mvk+rtG7wFB928xzDZB/06kFDAJw/f44EjySs0oRbdvZjC8rVzV7HmU6 sWxwKED99Ywy60KA/KqWU186BL6bAeX9Y5tpvQXQNCqbWS0lsICagA0FuFxEgt0VIngk 8JYBqFPcWVbdxdVQ70/r78hcpaKAWW7OXm8RjzzFZzlphnbCX7tf/BfWMIygDHzHdKMy 3K2HhMMz0wgPJY5pjQBws7leR+YHt8Lbwj9mRzGvTWf8uVCmO5dNmOEaP3alLHlsk3Fc BmGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fEjER1QD2Tnm8PA8oEKeSor0Ppgc9jB1pMOYk91Kf9w=; b=ftGUhZFcx/3mCni9kSfdpHxG9BMNbUQPqtzcQHG1hh9o/Jjpc4KVMSyW1ahoxqiEQq JmN4MkRIyGdfJ9RPfLWGqYZhTSvMEGLj5YXtfWbsN9EfvlplP/swsTrwj0ZzrU12r9QZ k57GZ4yNrn1wy/4ledy8B2bJVONNt0FPratMseLeCT3g3MZeemwTGa87RRivoc3bJbaW /mrdeyF/uOz3Ly1/ay7MIr2CmyGF3HpSwBrwUkYFQigB4HXgtmC8QZH1MKIevFBRekOV f1IT2x6Lhff3ZotEzpjpsK4jOHT+kyWnGiHbGuhN4uiPVx/YFrEpwDCYWW2N61VmvGe0 S4sg== X-Gm-Message-State: AHQUAub+MnwwFw7GRiD0ysD35y1gmEJiKmYHA0O/eikZr/e6ZgoiYQSN oayutNT9nQkpVjDKhg+L5pE= X-Google-Smtp-Source: AHgI3Ib/veyvOT3rzYEj5iqeAJ2bTEImkZyesLVX3RmAlVyvjMFef5IOddjFb7Db5IpNOadzltxC/Q== X-Received: by 2002:a1c:96c5:: with SMTP id y188mr11081548wmd.103.1550762762096; Thu, 21 Feb 2019 07:26:02 -0800 (PST) Received: from localhost (pD9E51D2D.dip0.t-ipconnect.de. [217.229.29.45]) by smtp.gmail.com with ESMTPSA id z14sm16074786wrv.91.2019.02.21.07.26.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 21 Feb 2019 07:26:01 -0800 (PST) From: Thierry Reding To: Philipp Zabel Cc: Jonathan Hunter , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/5] reset: Add acquire/release support for arrays Date: Thu, 21 Feb 2019 16:25:55 +0100 Message-Id: <20190221152557.8534-3-thierry.reding@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190221152557.8534-1-thierry.reding@gmail.com> References: <20190221152557.8534-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Thierry Reding Add implementations that apply acquire and release operations to all reset controls part of a reset control array. Signed-off-by: Thierry Reding Reviewed-by: Philipp Zabel --- drivers/reset/core.c | 36 +++++++++++++++++++++++++++++++++++- include/linux/reset.h | 6 ++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index f94da91c22af..81ea77cba123 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -245,6 +245,34 @@ static int reset_control_array_deassert(struct reset_control_array *resets) return ret; } +static int reset_control_array_acquire(struct reset_control_array *resets) +{ + unsigned int i; + int err; + + for (i = 0; i < resets->num_rstcs; i++) { + err = reset_control_acquire(resets->rstc[i]); + if (err < 0) + goto release; + } + + return 0; + +release: + while (i--) + reset_control_release(resets->rstc[i]); + + return err; +} + +static void reset_control_array_release(struct reset_control_array *resets) +{ + unsigned int i; + + for (i = 0; i < resets->num_rstcs; i++) + reset_control_release(resets->rstc[i]); +} + static inline bool reset_control_is_array(struct reset_control *rstc) { return rstc->array; @@ -464,6 +492,9 @@ int reset_control_acquire(struct reset_control *rstc) if (WARN_ON(IS_ERR(rstc))) return -EINVAL; + if (reset_control_is_array(rstc)) + return reset_control_array_acquire(rstc_to_array(rstc)); + mutex_lock(&reset_list_mutex); if (rstc->acquired) { @@ -502,7 +533,10 @@ void reset_control_release(struct reset_control *rstc) if (!rstc || WARN_ON(IS_ERR(rstc))) return; - rstc->acquired = false; + if (reset_control_is_array(rstc)) + reset_control_array_release(rstc_to_array(rstc)); + else + rstc->acquired = false; } EXPORT_SYMBOL_GPL(reset_control_release); diff --git a/include/linux/reset.h b/include/linux/reset.h index a01b32bf51d4..95d555c2130a 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -470,6 +470,12 @@ of_reset_control_array_get_exclusive(struct device_node *node) return of_reset_control_array_get(node, false, false, true); } +static inline struct reset_control * +of_reset_control_array_get_exclusive_released(struct device_node *node) +{ + return of_reset_control_array_get(node, false, false, false); +} + static inline struct reset_control * of_reset_control_array_get_shared(struct device_node *node) { From patchwork Thu Feb 21 15:25:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1046208 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="dGM/tt4A"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 444yx51rwHz9sBF for ; Fri, 22 Feb 2019 02:26:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728336AbfBUP0G (ORCPT ); Thu, 21 Feb 2019 10:26:06 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:42998 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728197AbfBUP0G (ORCPT ); Thu, 21 Feb 2019 10:26:06 -0500 Received: by mail-wr1-f68.google.com with SMTP id r5so17638032wrg.9; Thu, 21 Feb 2019 07:26:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0sjfQnYXYiI3H9SALD+ZGbevOhgIf9me4QKE275k6Zw=; b=dGM/tt4A9aNQooAojyjRDirO2w5BTcsIzSabfvoja8JYUALg60Or5hATl4pKLSyW51 laJhSQ8lUcVIYDXL3J1yclcLSxWbx0ISozv9IFuVov6Bz3SmH48kapTrZ+QeCpx281tA CZiIIdiOPFWBCMZZviSq6MUviVf6CmHzP6yFRzA1/8gWd3orHkrdp3RnTriDePv0bMmP Vef7XbR7/IhqFTwepVPzh2HKZhlBqZ9bp357HqDp4mWdWw1WPiNHgfi1VMjjYpi/OFN2 zU9WyIHfoyB4kRj58mqJrLrErFacJeBXlE6nKPa04QBFLUdNsMHWaalxKtKleCGnI+yf Gr+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0sjfQnYXYiI3H9SALD+ZGbevOhgIf9me4QKE275k6Zw=; b=LJ1gYwlTeYn71tGrlTV3tZ1wvrNUcM74Rl5dsOs5AJf4iQbB/54gREEtN3XSf5hBZw VADedBqZbrAs/gJt4Mfl8KuS0eunNcWG0Qew/7BmVXDNTcuxqudDaTm2tpU6YMDv1y91 ptEOZI4jtieIusucGNB5SE20JEc2ScOWRu4bLY+S281tdLDGQRQvQQ3plbRrCQEExOin GsuFtgrQvHZ/MZlq7ASE7FeIsfPno5K4prbgsaJGEgbknU2oQ649Vzb4sTAxAAy1nn+L htcCev775eldY7RfGLFhVG966mY9OTlwjqFJnGLErJGBo/iMzZitzSGV6Xc3MDTmr+oa eYSw== X-Gm-Message-State: AHQUAuY+pyxwjruv3j4FBRAJBjrGyEjyF7iM2xsQAR3tI0Iydxg41H67 svK3MMcyp+/qYkcMs6uvn64= X-Google-Smtp-Source: AHgI3IbMBw1yJWZsmd3MINZVKFgIEAi/Dst1YBn9771LtrCDtHIRn6nlCigmF9KOgbQ1G2xR3FMExQ== X-Received: by 2002:a1c:96c5:: with SMTP id y188mr11081630wmd.103.1550762763649; Thu, 21 Feb 2019 07:26:03 -0800 (PST) Received: from localhost (pD9E51D2D.dip0.t-ipconnect.de. [217.229.29.45]) by smtp.gmail.com with ESMTPSA id u134sm9154227wmf.21.2019.02.21.07.26.02 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 21 Feb 2019 07:26:03 -0800 (PST) From: Thierry Reding To: Philipp Zabel Cc: Jonathan Hunter , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/5] soc/tegra: pmc: Implement acquire/release for resets Date: Thu, 21 Feb 2019 16:25:56 +0100 Message-Id: <20190221152557.8534-4-thierry.reding@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190221152557.8534-1-thierry.reding@gmail.com> References: <20190221152557.8534-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Thierry Reding By implementing the acquire/release protocol, the resets can be shared with other drivers that also adhere to this protocol. This will be used for example by the SOR driver to put hardware into a known good state, irrespective of whether or not the power domain can be reset. Signed-off-by: Thierry Reding Reviewed-by: Philipp Zabel --- drivers/soc/tegra/pmc.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 0df258518693..0c5f79528e5f 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -656,10 +656,15 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain) int err; err = tegra_powergate_power_up(pg, true); - if (err) + if (err) { dev_err(dev, "failed to turn on PM domain %s: %d\n", pg->genpd.name, err); + goto out; + } + reset_control_release(pg->reset); + +out: return err; } @@ -669,10 +674,18 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain) struct device *dev = pg->pmc->dev; int err; + err = reset_control_acquire(pg->reset); + if (err < 0) { + pr_err("failed to acquire resets: %d\n", err); + return err; + } + err = tegra_powergate_power_down(pg); - if (err) + if (err) { dev_err(dev, "failed to turn off PM domain %s: %d\n", pg->genpd.name, err); + reset_control_release(pg->reset); + } return err; } @@ -937,20 +950,34 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, struct device *dev = pg->pmc->dev; int err; - pg->reset = of_reset_control_array_get_exclusive(np); + pg->reset = of_reset_control_array_get_exclusive_released(np); if (IS_ERR(pg->reset)) { err = PTR_ERR(pg->reset); dev_err(dev, "failed to get device resets: %d\n", err); return err; } - if (off) + err = reset_control_acquire(pg->reset); + if (err < 0) { + pr_err("failed to acquire resets: %d\n", err); + goto out; + } + + if (off) { err = reset_control_assert(pg->reset); - else + } else { err = reset_control_deassert(pg->reset); + if (err < 0) + goto out; - if (err) + reset_control_release(pg->reset); + } + +out: + if (err) { + reset_control_release(pg->reset); reset_control_put(pg->reset); + } return err; } From patchwork Thu Feb 21 15:25:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1046207 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="saVlx+jS"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 444yx349PJz9sBr for ; Fri, 22 Feb 2019 02:26:15 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728197AbfBUP0J (ORCPT ); Thu, 21 Feb 2019 10:26:09 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:37389 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728273AbfBUP0H (ORCPT ); Thu, 21 Feb 2019 10:26:07 -0500 Received: by mail-wr1-f67.google.com with SMTP id c8so30991207wrs.4; Thu, 21 Feb 2019 07:26:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=QaXaNTZnl4LT0GvNQL4ryRi6cnfcXOGXncEBEL7o+PY=; b=saVlx+jSkeWUsFy1OQY3QUWnrMXEJ/0RcnYvrxtBHDD0XgM7n9q7SRLtBjG0qsNtCW utW746Zc1ZZ92vMwAexqMhLXdYzMkcFoGoctDKOXtIqzK8snilw3MyjfzbT7mLFjNoGO o+ncyf7yZqRInRljrcj5a7tam/0sqgId5g/jzkBN3dijK4qCqVeFfDCsF2dypi+a6XGr voTD5WurPsmeeckESq0PPrkg/ubKmunsKU5b0wlHr4DRJRDjHj69o6tQxq4Q5BlVdgCy E43c2AJtjpk8y7qFm05q8cTPceN19TNHdMW7VfmG8cE+F1RABWxHBgckUbfdkdkDsGpN hWSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QaXaNTZnl4LT0GvNQL4ryRi6cnfcXOGXncEBEL7o+PY=; b=SSlQBdRkLqCk7ea3ZvlSNM5YqcjM1bhWP8qmFbfcaXALcW4B1TPSzk+dep4WpzC0rF AtWti9RzDMtk4ATcXZXDZEfyMQpshQvWLhYCc7MwulCzX44Muuiw+shFKGwqRH+ZSwg/ nbyuDMkHXn5dgiUCYv6VVbXB01S10n1vkvFYN9KkzaecWJldhl28v2Ika4yzMQRYENKq YdGywqTwC8jsmixP0Ahvg2C/ZYuFKkpIPiQSXn47Jcf9tfIYvH5AJ1m5dTJ+v2V5c68d EGpuoX7nsk+arynOL3NjdtxN0wkAgjTOpe8jIm/tqqckMtBHtUkGD+bkuAzrkemvvwAB IUdw== X-Gm-Message-State: AHQUAubT8EeBYzK70omGt0PsyyB+Q65GMHQhpMQKDB5PruqiIhogSB09 UKjuMzYAf2Ki9XSYkovRPQ4= X-Google-Smtp-Source: AHgI3IZ9goUs/jn1S2BkdCfWELpYNm4Ns8anNTPb3uY2ef7Sb/rudZSEwwDzVCWscNrvlG4Opk+v5Q== X-Received: by 2002:a1c:9d92:: with SMTP id g140mr10690726wme.35.1550762765377; Thu, 21 Feb 2019 07:26:05 -0800 (PST) Received: from localhost (pD9E51D2D.dip0.t-ipconnect.de. [217.229.29.45]) by smtp.gmail.com with ESMTPSA id z8sm6943928wmi.28.2019.02.21.07.26.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 21 Feb 2019 07:26:04 -0800 (PST) From: Thierry Reding To: Philipp Zabel Cc: Jonathan Hunter , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/5] drm/tegra: sor: Implement acquire/release for reset Date: Thu, 21 Feb 2019 16:25:57 +0100 Message-Id: <20190221152557.8534-5-thierry.reding@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190221152557.8534-1-thierry.reding@gmail.com> References: <20190221152557.8534-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Thierry Reding By implementing the acquire/release protocol, the SOR reset can be shared with other drivers that also adhere to this protocol, such as the PMC driver that uses the same reset as part of the powergate and -ungate implementation using generic power domains. Runtime PM makes sure that the operations are executed in the right order, and the reset core has error handling and WARNs in place to make sure the acquire/release protocol is followed. Signed-off-by: Thierry Reding Reviewed-by: Philipp Zabel --- drivers/gpu/drm/tegra/sor.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 40057106f5f3..5be5a0817dfe 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -2871,6 +2871,13 @@ static int tegra_sor_init(struct host1x_client *client) * kernel is possible. */ if (sor->rst) { + err = reset_control_acquire(sor->rst); + if (err < 0) { + dev_err(sor->dev, "failed to acquire SOR reset: %d\n", + err); + return err; + } + err = reset_control_assert(sor->rst); if (err < 0) { dev_err(sor->dev, "failed to assert SOR reset: %d\n", @@ -2894,6 +2901,8 @@ static int tegra_sor_init(struct host1x_client *client) err); return err; } + + reset_control_release(sor->rst); } err = clk_prepare_enable(sor->clk_safe); @@ -3331,7 +3340,7 @@ static int tegra_sor_probe(struct platform_device *pdev) goto remove; } - sor->rst = devm_reset_control_get(&pdev->dev, "sor"); + sor->rst = devm_reset_control_get_exclusive_released(&pdev->dev, "sor"); if (IS_ERR(sor->rst)) { err = PTR_ERR(sor->rst); @@ -3519,6 +3528,8 @@ static int tegra_sor_suspend(struct device *dev) dev_err(dev, "failed to assert reset: %d\n", err); return err; } + + reset_control_release(sor->rst); } usleep_range(1000, 2000); @@ -3542,9 +3553,17 @@ static int tegra_sor_resume(struct device *dev) usleep_range(1000, 2000); if (sor->rst) { + err = reset_control_acquire(sor->rst); + if (err < 0) { + dev_err(dev, "failed to acquire reset: %d\n", err); + clk_disable_unprepare(sor->clk); + return err; + } + err = reset_control_deassert(sor->rst); if (err < 0) { dev_err(dev, "failed to deassert reset: %d\n", err); + reset_control_release(sor->rst); clk_disable_unprepare(sor->clk); return err; }