From patchwork Sat Dec 31 10:47:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 2586 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-ej1-f70.google.com (mail-ej1-f70.google.com [209.85.218.70]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 31EFB40F4F for ; Sat, 31 Dec 2022 11:47:59 +0100 (CET) Received: by mail-ej1-f70.google.com with SMTP id hd17-20020a170907969100b007c117851c81sf15180610ejc.10 for ; Sat, 31 Dec 2022 02:47:59 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1672483679; cv=pass; d=google.com; s=arc-20160816; b=iJ+UtVGLqLG5mTqQFTvlmliI8kc1XIXPMGkHA8M/nY9UmNi2KsmmyDtZE3t5c/dvvK GyeP0jPIm3S6acjjxwKq+Q89jCpderDiriHJ3HWixH88A+h6Z9mUEaK0bv1GXzs4pA4N EUHUIgvyAVETDtyETMtGZlJ+GnTj8SShhJ0lKSr3YOYkSG+LRPt0eOuE9QgogSHNnUA3 0e+zlVDJ1KTTunHGZusK99FO0BWYQTSf2wZjIze+kqtnMiqzdswEXOJt0qhsOM/c8Oug ec+l9rEaDl5OQvKCfGGmGiTKe70k4NSSgEtOJeTIX18yb4l0n1p+tWvQuKTNgFaAC6Z5 ryQQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=fx+bjI/+k9JMrD6792m969aIIpY3E65hZzPxyyn8354=; b=LkLcUSckF5IJPN0j5faY1VJz9XnqkstcX/woghf0VaDVfMJB3YBFJHPsud0ZSHDexq zFaF2FKNL7DXcpKkGNbNa7H1cLR8+GXJkoXl4xusoJwV+hGPm5Q4FwP9vxWuqm6CTcsg KxTQo2blrGGHrJwXtX6mpQ6MDbb/OMRNFKteDsgUelvGRhbgFXS8aNx1vIO5i6f++QZj jqryByl8r2+fyotICAygNxfVcc/p/WbFAL7VwEGGl+WWqMOfNGq0sCLxIJATMEty5p5i ElwUKBl0qKj0VE6o/Tf9zS897A73EOrHNgVR/7P+AiGBwT8v+Uc9hxSWLhS9v5N40kxD puUQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=faGsjlnu; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=dario.binacchi@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:x-original-authentication-results :x-original-sender:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=fx+bjI/+k9JMrD6792m969aIIpY3E65hZzPxyyn8354=; b=iQaYLbm5X3qzfWYSsTUSnIbVFawzAeE2nULSfy3517M3niIekXSSqKoqsd+p97f7vs DuiIyzf4QPeaR9b481+jSfnUFauggkjKmxIi4CNiZeojUvGKHUjoqLblOSPkBuOGplyL R+qFQn3LrB7cEnQ1JFb2BH0mpTop9vxbksLx8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=list-unsubscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence :x-original-authentication-results:x-original-sender:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=fx+bjI/+k9JMrD6792m969aIIpY3E65hZzPxyyn8354=; b=lkallXvOn+Bsu0ABvsufDmNlPueu7Ru3+QyKJgarwrQr0h2X1HU4XbbPCdJcCJ+6/3 9FyAXeYPQ+VTpqCPqEX73pt62aOacPok3pCVblVWIfmfgU9dUuc8mR/KoBQnSfIBivjI VxoIAWRzUaOexo6pXmWDMBEi8Mzsh3K+R8UCCnm3CJt/TD0BM2wFhuBm/TYPJhH6DUwi u4Ug220fhtGpgHkEuXbz1JiSk8yem9Z5Ja81izp9zwpePnA3gltNis5MJRAG3T6ZtjST 3OafOhvkF51o3qLDKV0girlpLF3gfxXiAJd7WafJKl+btf91F7fkTiwAgT35RtnOGaDW mztw== X-Gm-Message-State: AFqh2koox1MbVam3GVgIiXMmUK1lXSuCB5DYu47GrnomFM205qaHBDAf O8tmGph/3r1PhmzQWKJJ/ooFA3G4 X-Google-Smtp-Source: AMrXdXtcpHMbZf3jxpLOvmFrSApJDUFKV8OLzI6GDf2TgS4IBywHhBs9nXUB/yV807RIXJ6n8LXnPw== X-Received: by 2002:a05:6402:4487:b0:483:8c1:9098 with SMTP id er7-20020a056402448700b0048308c19098mr2173056edb.274.1672483678897; Sat, 31 Dec 2022 02:47:58 -0800 (PST) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a17:906:3db1:b0:7a7:f2a:d325 with SMTP id y17-20020a1709063db100b007a70f2ad325ls949198ejh.10.-pod-prod-gmail; Sat, 31 Dec 2022 02:47:57 -0800 (PST) X-Received: by 2002:a17:906:d216:b0:7c1:2529:2760 with SMTP id w22-20020a170906d21600b007c125292760mr29173529ejz.27.1672483677635; Sat, 31 Dec 2022 02:47:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1672483677; cv=none; d=google.com; s=arc-20160816; b=RSQbl2zAEQVMe547+t/gUuytYi953j4Itjt7NAo78SUVRr+AN9OvEse1Xz58+XjhVk /E5YHVD9IpYhtvnUOHmiU+Kl13BakB/uVAcdYlPyTaJuctr+STEYIuN9IDcDz3I6fc1w MsGF1l1ODyGCOue2rL8SpdOKe6V1pUlwN0qYL7y8/Z6mrxGWEO7MX9U8nWCvCQuM0N0H yrto9DiOYVSlMXGJTXeG4rjN5OH8wEPUHLp7hb44Rg8Nm4BkZkpZLVS2pzKOO9g9htMC sG/ANwt3ueiK56TkuFuDneLY1d0Arg3hFiCXGVf7PjWBwHjnZ8Z8hN9/y5iVY40Pf7x0 eNcA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=d8WEj9/C0OhSqYwiG2nnUMjHUoH+KTqQswi/Eb48WWY=; b=EeJ40fhyijaAB79u4cccBveJ/7IYpZe4G+OztaIEncHbl9bI0EJVJMR6Lw0mOMnk97 DYOE6PblJMSN8B67kedXQ2aK5y6co51FD6PVknRcJSdQpIiA+uJ53xoZqJHGe4a6eJAq 63ZVGJW2mZFNXJItCrktizCxWsntbwKFE0HZ2lVsEMQuVxIjW3kvP7O2ky6OqjX4FEnh LdG+OvPH22a6XkLQJ6FgNb3EBeYFcUk5avemiWn8yw3+AAIiuBRLMVn634fui8hVcckl ytV3t+/CQ1C0V+MqNrRZPJu8OnrQ3Q9PQcJIksPfa3f32lDZmU4RMg42vSw2AWmKO4LZ Zh+Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=faGsjlnu; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=dario.binacchi@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id m11-20020a170906580b00b007c0c1e1df71sor10625069ejq.110.2022.12.31.02.47.57 for (Google Transport Security); Sat, 31 Dec 2022 02:47:57 -0800 (PST) Received-SPF: pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; X-Received: by 2002:a17:907:80cb:b0:7c0:deb1:bb8a with SMTP id io11-20020a17090780cb00b007c0deb1bb8amr35195077ejc.28.1672483677349; Sat, 31 Dec 2022 02:47:57 -0800 (PST) Received: from dario-ThinkPad-T14s-Gen-2i.homenet.telecomitalia.it (host-80-180-23-57.retail.telecomitalia.it. [80.180.23.57]) by smtp.gmail.com with ESMTPSA id z4-20020a17090655c400b0083ffb81f01esm10765438ejp.136.2022.12.31.02.47.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 31 Dec 2022 02:47:57 -0800 (PST) From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: tommaso.merciai@amarulasolutions.com, linux-amarula@amarulasolutions.com, Chen-Yu Tsai , jagan@amarulasolutions.com, angelo@amarulasolutions.com, anthony@amarulasolutions.com, michael@amarulasolutions.com, Dario Binacchi , Abel Vesa , Fabio Estevam , Michael Turquette , NXP Linux Team , Pengutronix Kernel Team , Sascha Hauer , Shawn Guo , Stephen Boyd , linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [RFC PATCH 05/11] clk: imx8mn: add divider driver Date: Sat, 31 Dec 2022 11:47:30 +0100 Message-Id: <20221231104736.12635-6-dario.binacchi@amarulasolutions.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20221231104736.12635-1-dario.binacchi@amarulasolutions.com> References: <20221231104736.12635-1-dario.binacchi@amarulasolutions.com> MIME-Version: 1.0 X-Original-Sender: dario.binacchi@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=faGsjlnu; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=dario.binacchi@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The patch adds support for imx8mn divider clocks to be initialized directly from the device tree. Currently all i.MX divider clocks are initialized by legacy code with hardwired parameters. So, let's start with this specific clock driver and hope that other variants can be handled in the future, causing the legacy code to be removed. Signed-off-by: Dario Binacchi --- drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-divider.c | 235 ++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 drivers/clk/imx/clk-divider.c diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 1cffc5bebbe1..0e4337f0a020 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -7,6 +7,7 @@ mxc-clk-objs += clk-composite-8m.o mxc-clk-objs += clk-composite-93.o mxc-clk-objs += clk-fracn-gppll.o mxc-clk-objs += clk-cpu.o +mxc-clk-objs += clk-divider.o mxc-clk-objs += clk-divider-gate.o mxc-clk-objs += clk-fixup-div.o mxc-clk-objs += clk-fixup-mux.o diff --git a/drivers/clk/imx/clk-divider.c b/drivers/clk/imx/clk-divider.c new file mode 100644 index 000000000000..4617aa906de4 --- /dev/null +++ b/drivers/clk/imx/clk-divider.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Amarula Solutions + * + * Dario Binacchi + */ + +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +#undef pr_fmt +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#define to_clk_imx_divider(_hw) container_of(_hw, struct clk_imx_divider, hw) + +struct clk_imx_divider { + struct clk_hw hw; + struct imx_clk_reg reg; + u8 shift; + u8 width; +}; + +static int imx_clk_divider_write(const struct imx_clk_reg *reg, u32 val) +{ + int ret = 0; + + if (reg->base) { + writel(val, reg->base + reg->offset); + } else if (reg->regmap) { + ret = regmap_write(reg->regmap, reg->offset, val); + } else { + pr_err("memory address not set\n"); + ret = -EIO; + } + + return ret; +} + +static int imx_clk_divider_read(const struct imx_clk_reg *reg, u32 *val) +{ + int ret = 0; + + if (reg->base) { + *val = readl(reg->base + reg->offset); + } else if (reg->regmap) { + ret = regmap_read(reg->regmap, reg->offset, val); + } else { + pr_err("memory address not set\n"); + ret = -EIO; + } + + return ret; +} + +static unsigned long imx_clk_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_imx_divider *divider = to_clk_imx_divider(hw); + unsigned int val; + int ret; + + ret = imx_clk_divider_read(÷r->reg, &val); + if (ret) + return 0; + + val >>= divider->shift; + val &= clk_div_mask(divider->width); + + return divider_recalc_rate(hw, parent_rate, val, NULL, 0, + divider->width); +} + +static long imx_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_imx_divider *divider = to_clk_imx_divider(hw); + + return divider_round_rate(hw, rate, prate, NULL, divider->width, 0); +} + +static int imx_clk_divider_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_imx_divider *divider = to_clk_imx_divider(hw); + + return divider_determine_rate(hw, req, NULL, divider->width, 0); +} + +static int imx_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_imx_divider *divider = to_clk_imx_divider(hw); + unsigned int val; + int div, ret; + + div = divider_get_val(rate, parent_rate, NULL, divider->width, 0); + if (div < 0) + return div; + + ret = imx_clk_divider_read(÷r->reg, &val); + if (ret) + return ret; + + val &= ~(clk_div_mask(divider->width) << divider->shift); + val |= div << divider->shift; + return imx_clk_divider_write(÷r->reg, val); +} + +const struct clk_ops imx_clk_divider_ops = { + .recalc_rate = imx_clk_divider_recalc_rate, + .round_rate = imx_clk_divider_round_rate, + .determine_rate = imx_clk_divider_determine_rate, + .set_rate = imx_clk_divider_set_rate, +}; + +static void imx_clk_hw_unregister_divider(struct clk_hw *hw) +{ + struct clk_imx_divider *divider = to_clk_imx_divider(hw); + + clk_hw_unregister(hw); + kfree(divider); +} + +static struct clk_hw *imx_clk_hw_register_divider(struct device_node *node, + const char *name, + unsigned long flags, + struct imx_clk_reg *reg, + u8 shift, u8 width) +{ + struct clk_parent_data pdata = { .index = 0 }; + struct clk_init_data init = { NULL }; + struct clk_imx_divider *divider; + struct clk_hw *hw; + int ret; + + divider = kzalloc(sizeof(*divider), GFP_KERNEL); + if (!divider) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = flags; + init.ops = &imx_clk_divider_ops; + init.parent_data = &pdata; + init.num_parents = 1; + + memcpy(÷r->reg, reg, sizeof(*reg)); + divider->shift = shift; + divider->width = width; + divider->hw.init = &init; + + hw = ÷r->hw; + ret = of_clk_hw_register(node, hw); + if (ret) { + kfree(divider); + return ERR_PTR(ret); + } + + return hw; +} + +/** + * of_imx_divider_clk_setup() - Setup function for imx gate clock + * @node: device node for the clock + */ +static void __init of_imx_divider_clk_setup(struct device_node *node) +{ + struct clk_hw *hw; + struct imx_clk_reg reg = {}; + const char *name = node->name; + u8 shift = 0; + u8 width; + u32 flags = 0; + u32 val; + + reg.regmap = syscon_regmap_lookup_by_phandle(node, "fsl,anatop"); + if (!IS_ERR(reg.regmap)) { + if (of_property_read_u32_index(node, "fsl,anatop", 1, &val)) { + pr_err("missing register offset for %pOFn\n", node); + return; + } + + reg.offset = val; + } else { + reg.base = of_iomap(node, 0); + if (IS_ERR(reg.base)) { + pr_err("failed to get register address for %pOFn\n", + node); + return; + } + } + + if (!of_property_read_u32(node, "fsl,bit-shift", &val)) + shift = val; + + if (of_property_read_u32(node, "fsl,width", &val)) { + pr_err("missing width for %pOFn\n", node); + return; + + } + + width = val; + + if (of_property_read_bool(node, "fsl,ops-parent-enable")) + flags |= CLK_OPS_PARENT_ENABLE; + + if (of_property_read_bool(node, "fsl,set-rate-parent")) + flags |= CLK_SET_RATE_PARENT; + + if (of_clk_get_parent_count(node) != 1) { + pr_err("%pOFn must have 1 parent clock\n", node); + return; + } + + of_property_read_string(node, "clock-output-names", &name); + + hw = imx_clk_hw_register_divider(node, name, flags, ®, shift, width); + if (IS_ERR(hw)) + return; + + if (of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw)) { + imx_clk_hw_unregister_divider(hw); + return; + } + + pr_debug("name: %s, offset: 0x%x, shift: %d, width: %d\n", name, + reg.offset, shift, width); +} +CLK_OF_DECLARE(fsl_imx8mn_divider_clk, "fsl,imx8mn-divider-clock", + of_imx_divider_clk_setup);