From: Dmitry Rokosov <ddrokosov@sberdevices.ru>
To: <neil.armstrong@linaro.org>, <jbrunet@baylibre.com>,
<mturquette@baylibre.com>, <sboyd@kernel.org>,
<robh+dt@kernel.org>, <krzysztof.kozlowski+dt@linaro.org>,
<khilman@baylibre.com>, <martin.blumenstingl@googlemail.com>
Cc: <jian.hu@amlogic.com>, <kernel@sberdevices.ru>,
<rockosov@gmail.com>, <linux-amlogic@lists.infradead.org>,
<linux-clk@vger.kernel.org>, <devicetree@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
Dmitry Rokosov <ddrokosov@sberdevices.ru>
Subject: [PATCH v8 07/11] clk: meson: a1: redesign Amlogic A1 PLL clock controller
Date: Fri, 2 Dec 2022 01:56:59 +0300 [thread overview]
Message-ID: <20221201225703.6507-8-ddrokosov@sberdevices.ru> (raw)
In-Reply-To: <20221201225703.6507-1-ddrokosov@sberdevices.ru>
Summary changes:
- supported meson-a1-clkc common driver
- inherited from the base clk-pll driver, implemented own version of
init/enable/disable/enabled routines; rate calculating logic is
fully the same
- aligned CLKID-related definitions with CLKID list from order
perspective to remove holes and permutations
- corrected Kconfig dependencies and types
- provided correct MODULE_AUTHORs() and MODULE_LICENSE()
- optimized and fix up some clock relationships
- removed unused register offset definitions (ANACTRL_* group)
Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru>
---
drivers/clk/meson/Kconfig | 5 +-
drivers/clk/meson/a1-pll.c | 267 +++++++++++++++++++++++++------------
drivers/clk/meson/a1-pll.h | 37 ++---
3 files changed, 202 insertions(+), 107 deletions(-)
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 1c885541c3a9..deb273673ec1 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -104,10 +104,11 @@ config COMMON_CLK_AXG_AUDIO
aka axg, Say Y if you want audio subsystem to work.
config COMMON_CLK_A1_PLL
- bool
- depends on ARCH_MESON
+ tristate "Meson A1 SoC PLL controller support"
+ depends on ARM64
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_PLL
+ select COMMON_CLK_MESON_A1_CLKC
help
Support for the PLL clock controller on Amlogic A113L device,
aka a1. Say Y if you want PLL to work.
diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c
index 69c1ca07d041..23487ca797b3 100644
--- a/drivers/clk/meson/a1-pll.c
+++ b/drivers/clk/meson/a1-pll.c
@@ -2,15 +2,133 @@
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
* Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2022, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
*/
#include <linux/clk-provider.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include "meson-a1-clkc.h"
#include "a1-pll.h"
-#include "clk-pll.h"
#include "clk-regmap.h"
+static inline
+struct meson_a1_pll_data *meson_a1_pll_data(struct clk_regmap *clk)
+{
+ return (struct meson_a1_pll_data *)clk->data;
+}
+
+static int meson_a1_pll_init(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_a1_pll_data *pll = meson_a1_pll_data(clk);
+
+ regmap_multi_reg_write(clk->map, pll->base.init_regs,
+ pll->base.init_count);
+
+ return 0;
+}
+
+static int meson_a1_pll_is_enabled(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_a1_pll_data *pll = meson_a1_pll_data(clk);
+
+ if (MESON_PARM_APPLICABLE(&pll->base.rst) &&
+ meson_parm_read(clk->map, &pll->base.rst))
+ return 0;
+
+ if (!meson_parm_read(clk->map, &pll->base.en) ||
+ !meson_parm_read(clk->map, &pll->base.l))
+ return 0;
+
+ return 1;
+}
+
+static int meson_a1_pll_enable(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_a1_pll_data *pll = meson_a1_pll_data(clk);
+
+ /* Do nothing if the PLL is already enabled */
+ if (clk_hw_is_enabled(hw))
+ return 0;
+
+ /* Enable the pll */
+ meson_parm_write(clk->map, &pll->base.en, 1);
+
+ /*
+ * Compared with the previous SoCs, self-adaption current module
+ * is newly added for A1, keep the new power-on sequence to enable the
+ * PLL. The sequence is:
+ * 1. enable the pll, delay for 10us
+ * 2. enable the pll self-adaption current module, delay for 40us
+ * 3. enable the lock detect module
+ */
+ usleep_range(10, 20);
+ meson_parm_write(clk->map, &pll->current_en, 1);
+ usleep_range(40, 50);
+
+ meson_parm_write(clk->map, &pll->l_detect, 1);
+ meson_parm_write(clk->map, &pll->l_detect, 0);
+
+ if (meson_clk_pll_wait_lock(hw))
+ return -EIO;
+
+ return 0;
+}
+
+static void meson_a1_pll_disable(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_a1_pll_data *pll = meson_a1_pll_data(clk);
+
+ /* Disable the pll */
+ meson_parm_write(clk->map, &pll->base.en, 0);
+
+ /* Disable PLL internal self-adaption current module */
+ meson_parm_write(clk->map, &pll->current_en, 0);
+}
+
+/*
+ * A1 PLL clock controller driver is based on meson clk_pll driver,
+ * so some rate calculating routines are reused
+ */
+static unsigned long meson_a1_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return meson_clk_pll_ops.recalc_rate(hw, parent_rate);
+}
+
+static int meson_a1_pll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return meson_clk_pll_ops.determine_rate(hw, req);
+}
+
+static int meson_a1_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return meson_clk_pll_ops.set_rate(hw, rate, parent_rate);
+}
+
+static const struct clk_ops meson_a1_pll_ops = {
+ .init = meson_a1_pll_init,
+ .recalc_rate = meson_a1_pll_recalc_rate,
+ .determine_rate = meson_a1_pll_determine_rate,
+ .set_rate = meson_a1_pll_set_rate,
+ .is_enabled = meson_a1_pll_is_enabled,
+ .enable = meson_a1_pll_enable,
+ .disable = meson_a1_pll_disable
+};
+
+static const struct clk_ops meson_a1_pll_ro_ops = {
+ .recalc_rate = meson_a1_pll_recalc_rate,
+ .is_enabled = meson_a1_pll_is_enabled,
+};
+
static struct clk_regmap a1_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
@@ -46,7 +164,7 @@ static struct clk_regmap a1_fixed_pll_dco = {
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
- .ops = &meson_clk_pll_ro_ops,
+ .ops = &meson_a1_pll_ro_ops,
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal_fixpll",
},
@@ -87,31 +205,36 @@ static const struct reg_sequence a1_hifi_init_regs[] = {
};
static struct clk_regmap a1_hifi_pll = {
- .data = &(struct meson_clk_pll_data){
- .en = {
- .reg_off = ANACTRL_HIFIPLL_CTRL0,
- .shift = 28,
- .width = 1,
- },
- .m = {
- .reg_off = ANACTRL_HIFIPLL_CTRL0,
- .shift = 0,
- .width = 8,
- },
- .n = {
- .reg_off = ANACTRL_HIFIPLL_CTRL0,
- .shift = 10,
- .width = 5,
- },
- .frac = {
- .reg_off = ANACTRL_HIFIPLL_CTRL1,
- .shift = 0,
- .width = 19,
- },
- .l = {
- .reg_off = ANACTRL_HIFIPLL_STS,
- .shift = 31,
- .width = 1,
+ .data = &(struct meson_a1_pll_data){
+ .base = {
+ .en = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .frac = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL1,
+ .shift = 0,
+ .width = 19,
+ },
+ .l = {
+ .reg_off = ANACTRL_HIFIPLL_STS,
+ .shift = 31,
+ .width = 1,
+ },
+ .range = &a1_hifi_pll_mult_range,
+ .init_regs = a1_hifi_init_regs,
+ .init_count = ARRAY_SIZE(a1_hifi_init_regs),
},
.current_en = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
@@ -123,13 +246,10 @@ static struct clk_regmap a1_hifi_pll = {
.shift = 6,
.width = 1,
},
- .range = &a1_hifi_pll_mult_range,
- .init_regs = a1_hifi_init_regs,
- .init_count = ARRAY_SIZE(a1_hifi_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
- .ops = &meson_clk_pll_ops,
+ .ops = &meson_a1_pll_ops,
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal_hifipll",
},
@@ -276,15 +396,15 @@ static struct clk_hw_onecell_data a1_pll_hw_onecell_data = {
.hws = {
[CLKID_FIXED_PLL_DCO] = &a1_fixed_pll_dco.hw,
[CLKID_FIXED_PLL] = &a1_fixed_pll.hw,
- [CLKID_HIFI_PLL] = &a1_hifi_pll.hw,
- [CLKID_FCLK_DIV2] = &a1_fclk_div2.hw,
- [CLKID_FCLK_DIV3] = &a1_fclk_div3.hw,
- [CLKID_FCLK_DIV5] = &a1_fclk_div5.hw,
- [CLKID_FCLK_DIV7] = &a1_fclk_div7.hw,
[CLKID_FCLK_DIV2_DIV] = &a1_fclk_div2_div.hw,
[CLKID_FCLK_DIV3_DIV] = &a1_fclk_div3_div.hw,
[CLKID_FCLK_DIV5_DIV] = &a1_fclk_div5_div.hw,
[CLKID_FCLK_DIV7_DIV] = &a1_fclk_div7_div.hw,
+ [CLKID_FCLK_DIV2] = &a1_fclk_div2.hw,
+ [CLKID_FCLK_DIV3] = &a1_fclk_div3.hw,
+ [CLKID_FCLK_DIV5] = &a1_fclk_div5.hw,
+ [CLKID_FCLK_DIV7] = &a1_fclk_div7.hw,
+ [CLKID_HIFI_PLL] = &a1_hifi_pll.hw,
[NR_PLL_CLKS] = NULL,
},
.num = NR_PLL_CLKS,
@@ -293,68 +413,39 @@ static struct clk_hw_onecell_data a1_pll_hw_onecell_data = {
static struct clk_regmap *const a1_pll_regmaps[] = {
&a1_fixed_pll_dco,
&a1_fixed_pll,
- &a1_hifi_pll,
&a1_fclk_div2,
&a1_fclk_div3,
&a1_fclk_div5,
&a1_fclk_div7,
+ &a1_hifi_pll,
};
-static struct regmap_config clkc_regmap_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
+static const struct meson_a1_clkc_data a1_pll_clkc __maybe_unused = {
+ .hw = &a1_pll_hw_onecell_data,
+ .regs = a1_pll_regmaps,
+ .num_regs = ARRAY_SIZE(a1_pll_regmaps),
};
-static int meson_a1_pll_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- void __iomem *base;
- struct regmap *map;
- int ret, i;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- map = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
- if (IS_ERR(map))
- return PTR_ERR(map);
-
- /* Populate regmap for the regmap backed clocks */
- for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++)
- a1_pll_regmaps[i]->map = map;
-
- for (i = 0; i < a1_pll_hw_onecell_data.num; i++) {
- /* array might be sparse */
- if (!a1_pll_hw_onecell_data.hws[i])
- continue;
-
- ret = devm_clk_hw_register(dev, a1_pll_hw_onecell_data.hws[i]);
- if (ret) {
- dev_err(dev, "Clock registration failed\n");
- return ret;
- }
- }
-
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
- &a1_pll_hw_onecell_data);
-}
-
-static const struct of_device_id clkc_match_table[] = {
- { .compatible = "amlogic,a1-pll-clkc", },
- {}
+#ifdef CONFIG_OF
+static const struct of_device_id a1_pll_clkc_match_table[] = {
+ {
+ .compatible = "amlogic,a1-pll-clkc",
+ .data = &a1_pll_clkc,
+ },
+ {},
};
+MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table);
+#endif /* CONFIG_OF */
-static struct platform_driver a1_pll_driver = {
- .probe = meson_a1_pll_probe,
- .driver = {
- .name = "a1-pll-clkc",
- .of_match_table = clkc_match_table,
+static struct platform_driver a1_pll_clkc_driver = {
+ .probe = meson_a1_clkc_probe,
+ .driver = {
+ .name = "a1-pll-clkc",
+ .of_match_table = of_match_ptr(a1_pll_clkc_match_table),
},
};
-builtin_platform_driver(a1_pll_driver);
+module_platform_driver(a1_pll_clkc_driver);
+MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
+MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h
index 8ded267061ad..2ff5a2042a97 100644
--- a/drivers/clk/meson/a1-pll.h
+++ b/drivers/clk/meson/a1-pll.h
@@ -1,38 +1,29 @@
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
+ * Amlogic Meson-A1 PLL Clock Controller internals
+ *
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2022, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
*/
#ifndef __A1_PLL_H
#define __A1_PLL_H
+#include "clk-pll.h"
+
/* PLL register offset */
#define ANACTRL_FIXPLL_CTRL0 0x0
#define ANACTRL_FIXPLL_CTRL1 0x4
-#define ANACTRL_FIXPLL_CTRL2 0x8
-#define ANACTRL_FIXPLL_CTRL3 0xc
-#define ANACTRL_FIXPLL_CTRL4 0x10
#define ANACTRL_FIXPLL_STS 0x14
-#define ANACTRL_SYSPLL_CTRL0 0x80
-#define ANACTRL_SYSPLL_CTRL1 0x84
-#define ANACTRL_SYSPLL_CTRL2 0x88
-#define ANACTRL_SYSPLL_CTRL3 0x8c
-#define ANACTRL_SYSPLL_CTRL4 0x90
-#define ANACTRL_SYSPLL_STS 0x94
#define ANACTRL_HIFIPLL_CTRL0 0xc0
#define ANACTRL_HIFIPLL_CTRL1 0xc4
#define ANACTRL_HIFIPLL_CTRL2 0xc8
#define ANACTRL_HIFIPLL_CTRL3 0xcc
#define ANACTRL_HIFIPLL_CTRL4 0xd0
#define ANACTRL_HIFIPLL_STS 0xd4
-#define ANACTRL_AUDDDS_CTRL0 0x100
-#define ANACTRL_AUDDDS_CTRL1 0x104
-#define ANACTRL_AUDDDS_CTRL2 0x108
-#define ANACTRL_AUDDDS_CTRL3 0x10c
-#define ANACTRL_AUDDDS_CTRL4 0x110
-#define ANACTRL_AUDDDS_STS 0x114
-#define ANACTRL_MISCTOP_CTRL0 0x140
-#define ANACTRL_POR_CNTL 0x188
/*
* CLKID index values
@@ -53,4 +44,16 @@
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/a1-pll-clkc.h>
+/**
+ * struct meson_a1_pll_data - A1 PLL state
+ * @base: Basic CLK PLL state
+ * @current_en: Enable or disable the PLL self-adaption current module
+ * @l_detect: Enable or disable the lock detect module
+ */
+struct meson_a1_pll_data {
+ struct meson_clk_pll_data base;
+ struct parm current_en;
+ struct parm l_detect;
+};
+
#endif /* __A1_PLL_H */
--
2.36.0
next prev parent reply other threads:[~2022-12-01 22:57 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-01 22:56 [PATCH v8 00/11] add Amlogic A1 clock controller drivers Dmitry Rokosov
2022-12-01 22:56 ` [PATCH v8 01/11] dt-bindings: clock: meson: add A1 PLL clock controller bindings Dmitry Rokosov
2022-12-02 4:10 ` Rob Herring
2022-12-02 9:51 ` Dmitry Rokosov
2022-12-02 10:39 ` Krzysztof Kozlowski
2022-12-02 11:04 ` Jerome Brunet
2022-12-02 11:16 ` Krzysztof Kozlowski
2022-12-02 11:28 ` Dmitry Rokosov
2022-12-02 13:36 ` neil.armstrong
2022-12-02 10:42 ` Krzysztof Kozlowski
2022-12-02 11:18 ` Dmitry Rokosov
2022-12-02 11:11 ` Jerome Brunet
2022-12-02 12:26 ` Dmitry Rokosov
2022-12-01 22:56 ` [PATCH v8 02/11] clk: meson: a1: add support for Amlogic A1 PLL clock driver Dmitry Rokosov
2022-12-02 11:16 ` Jerome Brunet
2022-12-02 11:31 ` Dmitry Rokosov
2022-12-01 22:56 ` [PATCH v8 03/11] dt-bindings: clock: meson: add A1 peripheral clock controller bindings Dmitry Rokosov
2022-12-02 4:10 ` Rob Herring
2022-12-02 9:49 ` Dmitry Rokosov
2022-12-02 10:39 ` Krzysztof Kozlowski
2022-12-02 10:58 ` Dmitry Rokosov
2022-12-02 10:43 ` Krzysztof Kozlowski
2022-12-01 22:56 ` [PATCH v8 04/11] clk: meson: a1: add support for Amlogic A1 Peripheral clock driver Dmitry Rokosov
2022-12-02 11:19 ` Jerome Brunet
2022-12-02 12:33 ` Dmitry Rokosov
2022-12-01 22:56 ` [PATCH v8 05/11] clk: meson: pll: export meson_clk_pll_wait_lock symbol Dmitry Rokosov
2022-12-01 22:56 ` [PATCH v8 06/11] clk: meson: introduce a1-clkc common driver for all A1 clock controllers Dmitry Rokosov
2022-12-02 11:36 ` Jerome Brunet
2022-12-02 11:58 ` Dmitry Rokosov
2022-12-01 22:56 ` Dmitry Rokosov [this message]
2022-12-02 11:42 ` [PATCH v8 07/11] clk: meson: a1: redesign Amlogic A1 PLL clock controller Jerome Brunet
2022-12-02 12:47 ` Dmitry Rokosov
2022-12-02 12:49 ` Jerome Brunet
2022-12-02 18:20 ` Dmitry Rokosov
2022-12-01 22:57 ` [PATCH v8 08/11] dt-bindings: clock: meson: fixup A1 PLL clkc dtb_check errors Dmitry Rokosov
2022-12-02 10:40 ` Krzysztof Kozlowski
2022-12-01 22:57 ` [PATCH v8 09/11] clk: meson: redesign A1 Peripherals CLK controller Dmitry Rokosov
2022-12-02 12:01 ` Jerome Brunet
2022-12-02 12:10 ` Dmitry Rokosov
2022-12-01 22:57 ` [PATCH v8 10/11] dt-bindings: clock: meson: fixup A1 peripherals clkc dtb_check errors Dmitry Rokosov
2022-12-02 10:40 ` Krzysztof Kozlowski
2022-12-01 22:57 ` [PATCH v8 11/11] arm64: dts: meson: a1: introduce PLL and Peripherals clk controllers Dmitry Rokosov
2022-12-02 10:43 ` Krzysztof Kozlowski
2022-12-02 12:03 ` Jerome Brunet
2022-12-02 13:37 ` neil.armstrong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221201225703.6507-8-ddrokosov@sberdevices.ru \
--to=ddrokosov@sberdevices.ru \
--cc=devicetree@vger.kernel.org \
--cc=jbrunet@baylibre.com \
--cc=jian.hu@amlogic.com \
--cc=kernel@sberdevices.ru \
--cc=khilman@baylibre.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-amlogic@lists.infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.blumenstingl@googlemail.com \
--cc=mturquette@baylibre.com \
--cc=neil.armstrong@linaro.org \
--cc=robh+dt@kernel.org \
--cc=rockosov@gmail.com \
--cc=sboyd@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).