From patchwork Fri Mar 30 08:54:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 893184 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=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="sWhB1NVs"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40CFn75tC5z9s1S for ; Fri, 30 Mar 2018 19:55:07 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 5B712C2216C; Fri, 30 Mar 2018 08:54:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 6B825C22194; Fri, 30 Mar 2018 08:54:55 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D313FC2217B; Fri, 30 Mar 2018 08:54:54 +0000 (UTC) Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by lists.denx.de (Postfix) with ESMTPS id 80A38C2210E for ; Fri, 30 Mar 2018 08:54:54 +0000 (UTC) Received: by mail-wm0-f65.google.com with SMTP id r82so15801678wme.0 for ; Fri, 30 Mar 2018 01:54:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=2+8K+7aw0GE/bjwlNcHj/hEof5T29DQAeZeWmOGitCw=; b=sWhB1NVsYjdzpB4OKToqZbllmSvjyAReayzgHFplP1qPAx3mcBNwGqfvHP44cnz7l6 bPrqxFYSo0xJTkV7pRAqRU91q6wzhE/WDQZLNDQW4ybLMNG1aQT9QRL+78X/sM7Ycb60 dCbwSoqRcgvDZEQKp8C0aX0guc9JjQbpb/XSoxa8EmQUGWN5BISRWvvf/7Xz4z/JYcYl Ztb5LzUH12x7uVH81epY0iF4nKM+tKWiBI8qbEfTjcgfBLHZCIwlbXddygWjqppL5rCn Lf5ehGOWUHHLOC6fm5QcUTRPkwuDEtpKBBIlfuFegV7V3cZ4U41PT6kDJcoHwNtRABS/ zqYw== 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; bh=2+8K+7aw0GE/bjwlNcHj/hEof5T29DQAeZeWmOGitCw=; b=ByCqA03tQgmEArnS+UhD+rvDshve4QxR6ambPZ6hw0RQgEjekHnLUlPscNT2Cv22Z1 i272+ZPHqkoMlTHcgVOIytQl+rKryHGbIz03qvIZ6AM4i+UgMCoROKS8yjqTBDBpf0gG cSe4x0waOYDspBD/Bu4s79256TGNgVlInO6fNzxL/C1NUKwB6f5LaDulVdpijUr2UL7X xllfOGJkL0D5lUbWoyZv/Rs30XOp2yM8Qlkp7vYGZGi4/aIiOUWrhwYXDZjkcvLv9d9I sYljry1j2hNwwvI7pNzAyLjOqb/PtFZFmqY0mFH51cWSisO3JIlpfkHq+OTf38xyHLlC EMSg== X-Gm-Message-State: AElRT7F6/pmFAiyRojl1fr01BU5djtWTwWq8TupVZs2ABXlRLqg4TfEl XEPQ8jwUO6TK8qTNJCAY09MB7g== X-Google-Smtp-Source: AIpwx4/yD3l6xrVsUS9lhzIbX04pLyz3tYMOb/GqNiiHwvzDukAuO+rfFmqZdWnZPzuIfRYn1j2ciA== X-Received: by 10.28.212.196 with SMTP id l187mr1758709wmg.52.1522400093994; Fri, 30 Mar 2018 01:54:53 -0700 (PDT) Received: from bender.baylibre.local ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id b38sm9611528wrg.81.2018.03.30.01.54.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 30 Mar 2018 01:54:53 -0700 (PDT) From: Neil Armstrong To: sjg@chromium.org, u-boot@lists.denx.de Date: Fri, 30 Mar 2018 10:54:50 +0200 Message-Id: <1522400090-13501-1-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 2.7.4 Cc: marex@denx.de, linux-amlogic@lists.infradead.org Subject: [U-Boot] [PATCH u-boot] reset: Add get/assert/deassert/release for bulk of reset signals X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds a "bulk" API to the reset API in order to get/deassert/ assert/release a group of reset signals associated with a device. This bulk API will avoid adding a copy of the same code to manage a group of reset signals in drivers. Signed-off-by: Neil Armstrong --- This serie and the "clk bulk" serie is necessary and suggested by Marek Vasut for the "Add USB Support for Amlogic Meson GXL SoCs" to avoid adding the same code to manage a bulk of clocks and resets in another driver. I will push a RFC code to update the other drivers having a similar code pattern when these patches are merged. drivers/reset/reset-uclass.c | 60 +++++++++++++++++++++++++++ include/reset.h | 99 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index 307a297..9a5c9c9 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -81,6 +81,40 @@ int reset_get_by_index(struct udevice *dev, int index, return 0; } +int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk) +{ + int i, ret, err, count; + + bulk->count = 0; + + count = dev_count_phandle_with_args(dev, "resets", "#reset-cells"); + if (!count) + return 0; + + bulk->resets = devm_kcalloc(dev, count, sizeof(struct reset_ctl), + GFP_KERNEL); + if (!bulk->resets) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = reset_get_by_index(dev, i, &bulk->resets[i]); + if (ret < 0) + goto bulk_get_err; + + ++bulk->count; + } + + return 0; + +bulk_get_err: + err = reset_release_all(bulk->resets, bulk->count); + if (err) + debug("%s: could release all resets for %p\n", + __func__, dev); + + return ret; +} + int reset_get_by_name(struct udevice *dev, const char *name, struct reset_ctl *reset_ctl) { @@ -126,6 +160,19 @@ int reset_assert(struct reset_ctl *reset_ctl) return ops->rst_assert(reset_ctl); } +int reset_assert_bulk(struct reset_ctl_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = reset_assert(&bulk->resets[i]); + if (ret < 0) + return ret; + } + + return 0; +} + int reset_deassert(struct reset_ctl *reset_ctl) { struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); @@ -135,6 +182,19 @@ int reset_deassert(struct reset_ctl *reset_ctl) return ops->rst_deassert(reset_ctl); } +int reset_deassert_bulk(struct reset_ctl_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = reset_deassert(&bulk->resets[i]); + if (ret < 0) + return ret; + } + + return 0; +} + int reset_release_all(struct reset_ctl *reset_ctl, int count) { int i, ret; diff --git a/include/reset.h b/include/reset.h index 7185ade..d38f176 100644 --- a/include/reset.h +++ b/include/reset.h @@ -60,6 +60,24 @@ struct reset_ctl { unsigned long id; }; +/** + * struct reset_ctl_bulk - A handle to (allowing control of) a bulk of reset + * signals. + * + * Clients provide storage for the reset control bulk. The content of the + * structure is managed solely by the reset API. A reset control bulk struct is + * initialized by "get"ing the reset control bulk struct. + * The reset control bulk struct is passed to all other bulk reset APIs to apply + * the API to all the reset signals in the bulk struct. + * + * @resets: An array of reset signal handles handles. + * @count: The number of reset signal handles in the reset array. + */ +struct reset_ctl_bulk { + struct reset_ctl *resets; + unsigned int count; +}; + #ifdef CONFIG_DM_RESET /** * reset_get_by_index - Get/request a reset signal by integer index. @@ -81,6 +99,22 @@ int reset_get_by_index(struct udevice *dev, int index, struct reset_ctl *reset_ctl); /** + * reset_get_bulk - Get/request all reset signals of a device. + * + * This looks up and requests all reset signals of the client device; each + * device is assumed to have n reset signals associated with it somehow, + * and this function finds and requests all of them in a separate structure. + * The mapping of client device reset signals indices to provider reset signals + * may be via device-tree properties, board-provided mapping tables, or some + * other mechanism. + * + * @dev: The client device. + * @bulk A pointer to a reset control bulk struct to initialize. + * @return 0 if OK, or a negative error code. + */ +int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk); + +/** * reset_get_by_name - Get/request a reset signal by name. * * This looks up and requests a reset signal. The name is relative to the @@ -132,6 +166,21 @@ int reset_free(struct reset_ctl *reset_ctl); int reset_assert(struct reset_ctl *reset_ctl); /** + * reset_assert_bulk - Assert all reset signals in a reset control bulk struct. + * + * This function will assert the specified reset signals in a reset control + * bulk struct, thus resetting the affected HW module(s). Depending on the + * reset controller hardware, the reset signals will either stay asserted + * until reset_deassert_bulk() is called, or the hardware may autonomously + * clear the reset signals itself. + * + * @bulk: A reset control bulk struct that was previously successfully + * requested by reset_get_bulk(). + * @return 0 if OK, or a negative error code. + */ +int reset_assert_bulk(struct reset_ctl_bulk *bulk); + +/** * reset_deassert - Deassert a reset signal. * * This function will deassert the specified reset signal, thus releasing the @@ -145,6 +194,20 @@ int reset_assert(struct reset_ctl *reset_ctl); int reset_deassert(struct reset_ctl *reset_ctl); /** + * reset_deassert_bulk - Deassert all reset signals in a reset control bulk + * struct. + * + * This function will deassert the specified reset signals in a reset control + * bulk struct, thus releasing the affected HW modules() from reset, and + * allowing them to continue normal operation. + * + * @bulk: A reset control bulk struct that was previously successfully + * requested by reset_get_bulk(). + * @return 0 if OK, or a negative error code. + */ +int reset_deassert_bulk(struct reset_ctl_bulk *bulk); + +/** * reset_release_all - Assert/Free an array of previously requested resets. * * For each reset contained in the reset array, this function will check if @@ -156,6 +219,23 @@ int reset_deassert(struct reset_ctl *reset_ctl); * @return 0 if OK, or a negative error code. */ int reset_release_all(struct reset_ctl *reset_ctl, int count); + +/** + * reset_release_bulk - Assert/Free an array of previously requested reset + * signals in a reset control bulk struct. + * + * For each reset contained in the reset control bulk struct, this function + * will check if reset has been previously requested and then will assert + * and free it. + * + * @bulk: A reset control bulk struct that was previously successfully + * requested by reset_get_bulk(). + * @return 0 if OK, or a negative error code. + */ +static inline int reset_release_bulk(struct reset_ctl_bulk *bulk) +{ + return reset_release_all(bulk->resets, bulk->count); +} #else static inline int reset_get_by_index(struct udevice *dev, int index, struct reset_ctl *reset_ctl) @@ -163,6 +243,11 @@ static inline int reset_get_by_index(struct udevice *dev, int index, return -ENOTSUPP; } +static inline int reset_get_bulk(struct udevice *dev, struct clk_bulk *bulk) +{ + return -ENOTSUPP; +} + static inline int reset_get_by_name(struct udevice *dev, const char *name, struct reset_ctl *reset_ctl) { @@ -179,16 +264,30 @@ static inline int reset_assert(struct reset_ctl *reset_ctl) return 0; } +static inline int reset_assert_bulk(struct reset_ctl_bulk *bulk) +{ + return 0; +} + static inline int reset_deassert(struct reset_ctl *reset_ctl) { return 0; } +static inline int reset_deassert_bulk(struct reset_ctl_bulk *bulk) +{ + return 0; +} + static inline int reset_release_all(struct reset_ctl *reset_ctl, int count) { return 0; } +static inline int reset_release_bulk(struct clk_bulk *bulk) +{ + return 0; +} #endif #endif