From patchwork Tue Apr 3 09:44:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 894490 X-Patchwork-Delegate: trini@ti.com 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="HFfSiJZG"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40Fkk646cFz9s1p for ; Tue, 3 Apr 2018 19:46:05 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3D082C21DFA; Tue, 3 Apr 2018 09:44:43 +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_H2, 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 C1B44C21E39; Tue, 3 Apr 2018 09:44:26 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 873AAC21EC2; Tue, 3 Apr 2018 09:44:24 +0000 (UTC) Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com [209.85.128.196]) by lists.denx.de (Postfix) with ESMTPS id 7D313C21C50 for ; Tue, 3 Apr 2018 09:44:23 +0000 (UTC) Received: by mail-wr0-f196.google.com with SMTP id d17so2549453wre.1 for ; Tue, 03 Apr 2018 02:44:23 -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:in-reply-to:references; bh=qQMYIUk5WWmwJic7Er04/VpYVJfJ7mVR3AweEjjKe8Y=; b=HFfSiJZGvuIR0MUoSGRQ/5qv3UYFAImRDzUZ0F+ivPAbt851CESl36wMSWi4g85Srg h8BXue5hQLtqtWb6OaQ5TL+7ikjbUcJeLOD3dvJq90TUHuUVqfhBt1lTdhvkvH2zucBS 58QEu3cOJb4+ZPoz+jViKxC7KnddObmcL5VUbBZ8FCRhyjroOcI3zifo0BjMJmgRbBNN woZ0Zia2dUBt/0P/U9TuvZp+URUdi94XeiHIQTlXc6ZKhaaRs5cHvQwum59e+qATq1A3 bUFN1GIFAD71/2A6wQ03HZ/IiCyALNOU8FzBe4jZX6adKE1+uSKY6vveHgS+bHQvJRgP 4HdA== 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; bh=qQMYIUk5WWmwJic7Er04/VpYVJfJ7mVR3AweEjjKe8Y=; b=LZRtJc9QKtnzo1Zm1TddSzU0ckTFToU7rBi/BN3AYcdYpTOzpcu35bfe9/D75YuxX+ 6H28UOo9fovAWQogA2D/9Ie5wpP7eNm+pRaagLzCQHnljoeHY+aawiPycfOJ2RsFT7mK 9cTlqodLWkADAvZ6LTdbLEr2e8TL74o9pu1fAT/SebQhvl+G31gFM4epBrkIhRIsSdfN B4Uz1JjeyChGtTepCMriA3rW0+YtBF7tHs+DP+Wn6OD4uwJcss+VsyzRsoJqGMREg78v fas8CDoze/cOruKy2Ze2IwRIVosSFFYgdK6NGC5vrstYJ8CQrf3VRBxeIn8ANftZnGXy 2OKg== X-Gm-Message-State: AElRT7HMuXOpl66B7GORjHYS040yp6l9PMBaj3a8z5xG8J4STBr7hJqR 1Fa1J4M2lXRzVNUxf9hsPkkp0g== X-Google-Smtp-Source: AIpwx48lxUHE2EJX1gQV5QNf58uAqWTVdMP+SoPRLJuG9JA8GbKvt93tjCeW+pX8Z1MtaL6loOsWdQ== X-Received: by 10.223.128.98 with SMTP id 89mr9100562wrk.141.1522748662957; Tue, 03 Apr 2018 02:44:22 -0700 (PDT) Received: from bender.baylibre.local ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id q21sm1513565wra.24.2018.04.03.02.44.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 03 Apr 2018 02:44:22 -0700 (PDT) From: Neil Armstrong To: sjg@chromium.org, u-boot@lists.denx.de Date: Tue, 3 Apr 2018 11:44:18 +0200 Message-Id: <1522748659-21622-2-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1522748659-21622-1-git-send-email-narmstrong@baylibre.com> References: <1522748659-21622-1-git-send-email-narmstrong@baylibre.com> Cc: marex@denx.de, linux-amlogic@lists.infradead.org Subject: [U-Boot] [PATCH v2 u-boot 1/2] clk: Add get/enable/disable/release for a bulk of clocks 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 clock API in order to get/enable/disable /release a group of clocks associated with a device. This bulk API will avoid adding a copy of the same code to manage a group of clocks in drivers. Signed-off-by: Neil Armstrong Reviewed-by: Simon Glass --- drivers/clk/clk-uclass.c | 59 +++++++++++++++++++++++++++++++++++++++ include/clk.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index ad76379..6e99b3b 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -104,6 +104,39 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) return clk_get_by_indexed_prop(dev, "clocks", index, clk); } +int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk) +{ + int i, ret, err, count; + + bulk->count = 0; + + count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + if (!count) + return 0; + + bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL); + if (!bulk->clks) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = clk_get_by_index(dev, i, &bulk->clks[i]); + if (ret < 0) + goto bulk_get_err; + + ++bulk->count; + } + + return 0; + +bulk_get_err: + err = clk_release_all(bulk->clks, bulk->count); + if (err) + debug("%s: could release all clocks for %p\n", + __func__, dev); + + return ret; +} + static int clk_set_default_parents(struct udevice *dev) { struct clk clk, parent_clk; @@ -336,6 +369,19 @@ int clk_enable(struct clk *clk) return ops->enable(clk); } +int clk_enable_bulk(struct clk_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = clk_enable(&bulk->clks[i]); + if (ret < 0 && ret != -ENOSYS) + return ret; + } + + return 0; +} + int clk_disable(struct clk *clk) { const struct clk_ops *ops = clk_dev_ops(clk->dev); @@ -348,6 +394,19 @@ int clk_disable(struct clk *clk) return ops->disable(clk); } +int clk_disable_bulk(struct clk_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = clk_disable(&bulk->clks[i]); + if (ret < 0 && ret != -ENOSYS) + return ret; + } + + return 0; +} + UCLASS_DRIVER(clk) = { .id = UCLASS_CLK, .name = "clk", diff --git a/include/clk.h b/include/clk.h index a7d95d3..b3a9fce 100644 --- a/include/clk.h +++ b/include/clk.h @@ -60,6 +60,23 @@ struct clk { unsigned long id; }; +/** + * struct clk_bulk - A handle to (allowing control of) a bulk of clocks. + * + * Clients provide storage for the clock bulk. The content of the structure is + * managed solely by the clock API. A clock bulk struct is + * initialized by "get"ing the clock bulk struct. + * The clock bulk struct is passed to all other bulk clock APIs to apply + * the API to all the clock in the bulk struct. + * + * @clks: An array of clock handles. + * @count: The number of clock handles in the clks array. + */ +struct clk_bulk { + struct clk *clks; + unsigned int count; +}; + #if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK) struct phandle_1_arg; int clk_get_by_index_platdata(struct udevice *dev, int index, @@ -83,6 +100,21 @@ int clk_get_by_index_platdata(struct udevice *dev, int index, int clk_get_by_index(struct udevice *dev, int index, struct clk *clk); /** + * clock_get_bulk - Get/request all clocks of a device. + * + * This looks up and requests all clocks of the client device; each device is + * assumed to have n clocks associated with it somehow, and this function finds + * and requests all of them in a separate structure. The mapping of client + * device clock indices to provider clocks may be via device-tree properties, + * board-provided mapping tables, or some other mechanism. + * + * @dev: The client device. + * @bulk A pointer to a clock bulk struct to initialize. + * @return 0 if OK, or a negative error code. + */ +int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk); + +/** * clock_get_by_name - Get/request a clock by name. * * This looks up and requests a clock. The name is relative to the client @@ -120,6 +152,11 @@ static inline int clk_get_by_index(struct udevice *dev, int index, return -ENOSYS; } +static inline int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk) +{ + return -ENOSYS; +} + static inline int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk) { @@ -130,7 +167,6 @@ static inline int clk_release_all(struct clk *clk, int count) { return -ENOSYS; } - #endif #if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \ @@ -151,6 +187,22 @@ static inline int clk_set_defaults(struct udevice *dev) #endif /** + * clk_release_bulk() - Disable (turn off)/Free an array of previously + * requested clocks in a clock bulk struct. + * + * For each clock contained in the clock bulk struct, this function will check + * if clock has been previously requested and then will disable and free it. + * + * @clk: A clock bulk struct that was previously successfully + * requested by clk_get_bulk(). + * @return zero on success, or -ve error code. + */ +static inline int clk_release_bulk(struct clk_bulk *bulk) +{ + return clk_release_all(bulk->clks, bulk->count); +} + +/** * clk_request - Request a clock by provider-specific ID. * * This requests a clock using a provider-specific ID. Generally, this function @@ -215,6 +267,15 @@ int clk_set_parent(struct clk *clk, struct clk *parent); int clk_enable(struct clk *clk); /** + * clk_enable_bulk() - Enable (turn on) all clocks in a clock bulk struct. + * + * @bulk: A clock bulk struct that was previously successfully requested + * by clk_get_bulk(). + * @return zero on success, or -ve error code. + */ +int clk_enable_bulk(struct clk_bulk *bulk); + +/** * clk_disable() - Disable (turn off) a clock. * * @clk: A clock struct that was previously successfully requested by @@ -223,6 +284,15 @@ int clk_enable(struct clk *clk); */ int clk_disable(struct clk *clk); +/** + * clk_disable_bulk() - Disable (turn off) all clocks in a clock bulk struct. + * + * @bulk: A clock bulk struct that was previously successfully requested + * by clk_get_bulk(). + * @return zero on success, or -ve error code. + */ +int clk_disable_bulk(struct clk_bulk *bulk); + int soc_clk_dump(void); #endif