From patchwork Sun Jan 1 17:57:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 2597 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-ed1-f70.google.com (mail-ed1-f70.google.com [209.85.208.70]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 7618B3F9E8 for ; Sun, 1 Jan 2023 18:57:54 +0100 (CET) Received: by mail-ed1-f70.google.com with SMTP id h18-20020a05640250d200b004758e655ebesf16951849edb.11 for ; Sun, 01 Jan 2023 09:57:54 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1672595874; cv=pass; d=google.com; s=arc-20160816; b=ufZfCm6qfhlLbhGsXlWBI2qddQNADB9/BlHLAkbtKu3kczGekCCdyklPP9KMaRTMLY eqbfLvnAhE/99KcXkDITHXkvBcPxN1umxbTJ6CG6tdbntLSgC77Fx5HhpFtVjFz+Iybr 36LLM17RV2vd1QYP6t/JxZZH4Bm0ykH079tncqCfsKgYCJrKxIIKWh/MP/T0AbX3nAUk FDGEjeABXnd3wslwCCyafbpjOze2BwO3R6DcXL7zjPT4fbFFV+jINCOD/7Fffu26DYn3 Z2nExyDSxOpdIgmf2clc7m+wG37XJ9hHEPEs1Daf1j/lDTztZUnjti7rsrlunJQcIGNb iKVw== 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=Lq8ZOvcJD0vpf2QIhcomosXDaNqkIbpypT6E56JfVQk=; b=sRGSFz4ANrickJ6+067jjK8jipmBUnXF1kVoK07jbdHwCxAX4Dm3T5eU4iQSSuSVA1 nw3DW6chCAsNDbll71UVY4Hv/dgWVlgM277QxRunEGTUN6REZePBdTbShGZ7212XaqdZ UfcwicTkln64G81dOtnsug20dV6OnOwIfHwObXdIb/NzeoXxFkfZOl569TL0TdH5fnwZ Xw2jjqwkojOupRcbndjZynF3ccNYxfwerSCrUq08bIc3l/M+52uvd9kB8hpsXFGexegC 4KhfhJMyS9w9SSQZjTs8N+CfH5dsH+bMYj37dU7DbzIo7HUUwvAZBLuEQfslMoqK6ixb 3Hwg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b="EM/uGHg2"; 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=Lq8ZOvcJD0vpf2QIhcomosXDaNqkIbpypT6E56JfVQk=; b=j8aXVxKt/rmjdVxWLlHWJU5F6hsUZSZi20s+wt0+JZ6uXSU8HOPu7BbCLmUHTho4FK uqoOjhYWxpHqXNrPMBmmZ9byQyxjOTLL4ZLQRjisbVB0Ou63NB/v+nMjyaafLE8o8ben dTg/zPRIBPzLYih/I7KDUSv9khw9oduRWfE2s= 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=Lq8ZOvcJD0vpf2QIhcomosXDaNqkIbpypT6E56JfVQk=; b=oiWsv3xnGMZY3dxacExmMMHfN2V7Vx9LkBsyHC/dZeqLPz8KbDrw3qi7/h6l9QPLYu V7aTHjMTXubD1CX5NXBYk3u7WgdWOnvnFPPDFqf+6/Hw8fhJdIpVURHrjyhu7HjjuBBg 5//1J0yF8M5Xjn4jJVCZvLVXkji/UFRcZ15Jhl96XhbT5RNC/XM/FOZAs/ZejxIv7YPo ljgXCuSB/FkUGyzJ1wUcRdqJenmzcy5gkYbmLlDIq8CT7x4GAxMiDvgBIgBYW2RH4hDy 8IJtTzIxbyCUXZGhjgDVAVt1s2QOQmri6yIpJKrvjLm8hhILWsI5RgrhlTz/54bUUamw sgaQ== X-Gm-Message-State: AFqh2kqOYvDpWyBodNkRsBfBs8ZjCAPs8/0WStXSuaTiCMRbL7rFpQKT Xh9WTqNz5zkW4iMaouhBTZTPLIak X-Google-Smtp-Source: AMrXdXt7iOkHfIjeHyT69Ikv1JOgymlFW4DO5M9osHn05HRM027N7Gfov04KFpuAmo81Jpn+T39pqg== X-Received: by 2002:a17:906:c0a:b0:7bb:52b2:4162 with SMTP id s10-20020a1709060c0a00b007bb52b24162mr3519471ejf.608.1672595874189; Sun, 01 Jan 2023 09:57:54 -0800 (PST) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a17:906:55c1:b0:7c1:2050:cc5f with SMTP id z1-20020a17090655c100b007c12050cc5fls2016702ejp.0.-pod-prod-gmail; Sun, 01 Jan 2023 09:57:53 -0800 (PST) X-Received: by 2002:a17:906:9616:b0:78d:f457:108f with SMTP id s22-20020a170906961600b0078df457108fmr33036280ejx.76.1672595873028; Sun, 01 Jan 2023 09:57:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1672595873; cv=none; d=google.com; s=arc-20160816; b=eORilK6ousTyxMl3yLx20Vdqi3RU4xC5bvxWo2OoVi+S302jeQCpZL0I1dxLxZGed7 Fs1J4jlvf6o//t6vyotpNA3sFpUx4IJrF0ynh088dEeVv7tzpIXPMG05hGpHqtCMasIh +Moz8no8Qn99aBEz76npbeomMqiYR0QjytAvYEe6d25yiwEGfYozU6H6eGyUliB8G03f 3IEqMb7fr7ilPcHk8O4PEOzBa0fgpzvsSUPUSrO0jLTnTZq/hJGSS8ELmU+4M6TGcudn BRZi3PmftoG/0e7OpFv7wkeSMpqTJg/qsqvzD9ucHfh1ViHpXU1QiMeQHdS/6N4VNv4g kkug== 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=SzWgtinayzWqOkE2ijmFHmqOXIKDSib2Is7Zd5a35gQ=; b=oTNdHHb8Icw30zHXqQGB7nQX1LXRbK3KIHI/+2rHXIBAKUgKY8Raox6canmxnKInYe 7/+6I34Rh6GxhjGGq3gWk79KUubTvKzJ7OGgrcxkopL4cPd6ID+8WklJJdjQY7gqxVVl nRcrcDdkMZZqFnf24KI0JTgR0q/Xou/HXlrENX/5ZgvPBJnitzGr4CxrER0jqL/KHYFh OlhLJ5esTA0ra68WHVj3T6/G1+WZeiOrSE4VIR8u+ER9tQ8vwa8YAtebN5ayAdq4qOm0 KiKJGbPDZqNIP1ge61yuTQBTSZdIjwWDropiDkpI1uaZaeZztx5f4rpAiAc+7FL+Gu3c NI4g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b="EM/uGHg2"; 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 ku6-20020a170907788600b007c0fa91134fsor11603960ejc.79.2023.01.01.09.57.52 for (Google Transport Security); Sun, 01 Jan 2023 09:57:53 -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:906:38d9:b0:84b:8885:9868 with SMTP id r25-20020a17090638d900b0084b88859868mr31536688ejd.58.1672595872816; Sun, 01 Jan 2023 09:57:52 -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 q2-20020a1709063d4200b0082ddfb47d06sm12273018ejf.148.2023.01.01.09.57.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Jan 2023 09:57:52 -0800 (PST) From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: angelo@amarulasolutions.com, michael@amarulasolutions.com, tommaso.merciai@amarulasolutions.com, Chen-Yu Tsai , linux-amarula@amarulasolutions.com, anthony@amarulasolutions.com, jagan@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 v2 04/11] clk: imx8mn: add mux driver Date: Sun, 1 Jan 2023 18:57:33 +0100 Message-Id: <20230101175740.1010258-5-dario.binacchi@amarulasolutions.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20230101175740.1010258-1-dario.binacchi@amarulasolutions.com> References: <20230101175740.1010258-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="EM/uGHg2"; 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 mux clocks to be initialized directly from the device tree. Currently all i.MX mux clocks are initialized by legacy code with hardwired parameters. This approach has generated setup functions with unclear names: git grep "#define imx_clk_hw_mux" drivers/clk/imx/clk.h drivers/clk/imx/clk.h:#define imx_clk_hw_mux2(name, reg, shift, width, parents, num_parents) \ drivers/clk/imx/clk.h:#define imx_clk_hw_mux(name, reg, shift, width, parents, num_parents) \ drivers/clk/imx/clk.h:#define imx_clk_hw_mux_flags(name, reg, shift, width, parents, num_parents, flags) \ drivers/clk/imx/clk.h:#define imx_clk_hw_mux_ldb(name, reg, shift, width, parents, num_parents) \ drivers/clk/imx/clk.h:#define imx_clk_hw_mux2_flags(name, reg, shift, width, parents, num_parents, flags) \ 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 --- (no changes since v1) drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-mux.c | 258 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 drivers/clk/imx/clk-mux.c diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 72e1f08d49dc..1cffc5bebbe1 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -15,6 +15,7 @@ mxc-clk-objs += clk-gate.o mxc-clk-objs += clk-gate2.o mxc-clk-objs += clk-gate-93.o mxc-clk-objs += clk-gate-exclusive.o +mxc-clk-objs += clk-mux.o mxc-clk-objs += clk-pfd.o mxc-clk-objs += clk-pfdv2.o mxc-clk-objs += clk-pllv1.o diff --git a/drivers/clk/imx/clk-mux.c b/drivers/clk/imx/clk-mux.c new file mode 100644 index 000000000000..426738d25582 --- /dev/null +++ b/drivers/clk/imx/clk-mux.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Amarula Solutions + * + * Dario Binacchi + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +#undef pr_fmt +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#define to_clk_imx_mux(_hw) container_of(_hw, struct clk_imx_mux, hw) + +struct clk_imx_mux { + struct clk_hw hw; + struct imx_clk_reg reg; + u32 mask; + u8 shift; + u8 saved_parent; +}; + +static int imx_clk_mux_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_mux_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 u8 imx_clk_mux_get_parent(struct clk_hw *hw) +{ + + struct clk_imx_mux *mux = to_clk_imx_mux(hw); + int num_parents = clk_hw_get_num_parents(hw); + unsigned int val; + int ret; + + ret = imx_clk_mux_read(&mux->reg, &val); + if (ret) + return ret; + + val = (val >> mux->shift) && mux->mask; + + if (val >= num_parents) + return -EINVAL; + + return val; +} + +static int imx_clk_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_imx_mux *mux = to_clk_imx_mux(hw); + unsigned int val; + int ret; + + ret = imx_clk_mux_read(&mux->reg, &val); + if (ret) + return ret; + + val &= ~(mux->mask << mux->shift); + val |= index << mux->shift; + return imx_clk_mux_write(&mux->reg, val); +} + +/** + * imx_clk_mux_save_context - Save the parent selcted in the mux + * @hw: pointer struct clk_hw + * + * Save the parent mux value. + */ +static int imx_clk_mux_save_context(struct clk_hw *hw) +{ + struct clk_imx_mux *mux = to_clk_imx_mux(hw); + + mux->saved_parent = imx_clk_mux_get_parent(hw); + return 0; +} + +/** + * imx_clk_mux_restore_context - Restore the parent in the mux + * @hw: pointer struct clk_hw + * + * Restore the saved parent mux value. + */ +static void imx_clk_mux_restore_context(struct clk_hw *hw) +{ + struct clk_imx_mux *mux = to_clk_imx_mux(hw); + + imx_clk_mux_set_parent(hw, mux->saved_parent); +} + +const struct clk_ops imx_clk_mux_ops = { + .get_parent = imx_clk_mux_get_parent, + .set_parent = imx_clk_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, + .save_context = imx_clk_mux_save_context, + .restore_context = imx_clk_mux_restore_context, +}; + +static void imx_clk_hw_unregister_mux(struct clk_hw *hw) +{ + struct clk_imx_mux *mux = to_clk_imx_mux(hw); + + clk_hw_unregister(hw); + kfree(mux); +} + +static struct clk_hw *imx_clk_hw_register_mux(struct device_node *node, + const char *name, + const char * const *parent_names, + u8 num_parents, + unsigned long flags, + struct imx_clk_reg *reg, u8 shift, + u32 mask) +{ + struct clk_init_data init = { NULL }; + struct clk_imx_mux *mux; + struct clk_hw *hw; + + int ret; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = flags; + init.ops = &imx_clk_mux_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + + /* struct clk_mux assignments */ + memcpy(&mux->reg, reg, sizeof(*reg)); + mux->hw.init = &init; + + hw = &mux->hw; + ret = of_clk_hw_register(node, hw); + if (ret) { + kfree(mux); + return ERR_PTR(ret); + } + + return hw; +} + +/** + * of_imx_mux_clk_setup() - Setup function for imx mux clock + * @node: device node for the clock + */ +static void __init of_imx_mux_clk_setup(struct device_node *node) +{ + struct clk_hw *hw; + unsigned int num_parents; + const char **parent_names; + const char *name = node->name; + struct imx_clk_reg reg = {}; + u32 shift = 0; + u32 flags = CLK_SET_RATE_NO_REPARENT; + u32 val; + u32 mask; + + 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; + } + } + + num_parents = of_clk_get_parent_count(node); + if (num_parents < 2) { + pr_err("%pOFn must have parents\n", node); + return; + } + + parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL); + if (!parent_names) + return; + + of_clk_parent_fill(node, parent_names, num_parents); + + of_property_read_u32(node, "fsl,bit-shift", &shift); + + if (of_property_read_bool(node, "fsl,is-critical")) + flags |= CLK_IS_CRITICAL; + + 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; + + /* Generate bit-mask based on parent info */ + mask = num_parents - 1; + mask = (1 << fls(mask)) - 1; + + of_property_read_string(node, "clock-output-names", &name); + + hw = imx_clk_hw_register_mux(node, name, parent_names, num_parents, + flags, ®, shift, mask); + if (IS_ERR(hw)) + goto free_parent_names; + + if (of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw)) { + imx_clk_hw_unregister_mux(hw); + goto free_parent_names; + } + + pr_debug("name: %s, offset: 0x%x, shift: %d, mask: 0x%x\n", name, + reg.offset, shift, mask); + +free_parent_names: + kfree(parent_names); +} +CLK_OF_DECLARE(fsl_imx8mn_mux_clk, "fsl,imx8mn-mux-clock", + of_imx_mux_clk_setup);