diff mbox series

[v4,3/6] clk: qcom: Add IPQ8074 APSS clock controller

Message ID 20220515204540.477711-3-robimarko@gmail.com (mailing list archive)
State Superseded, archived
Headers show
Series [v4,1/6] clk: qcom: clk-alpha-pll: add support for APSS PLL | expand

Commit Message

Robert Marko May 15, 2022, 8:45 p.m. UTC
IPQ8074 APSS clock controller provides the clock for the IPQ8074 CPU
cores, thus also providing support for CPU frequency scaling.

It looks like they are clocked by the XO and a custom APSS type PLL.

Co-developed-by: Ansuel Smith <ansuelsmth@gmail.com>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
Changes in v2:
* Convert to using parent-data instead of parent-names
---
 drivers/clk/qcom/Kconfig        |  11 +++
 drivers/clk/qcom/Makefile       |   1 +
 drivers/clk/qcom/apss-ipq8074.c | 170 ++++++++++++++++++++++++++++++++
 3 files changed, 182 insertions(+)
 create mode 100644 drivers/clk/qcom/apss-ipq8074.c

Comments

Krzysztof Kozlowski May 17, 2022, 8:14 a.m. UTC | #1
On 15/05/2022 22:45, Robert Marko wrote:
> IPQ8074 APSS clock controller provides the clock for the IPQ8074 CPU
> cores, thus also providing support for CPU frequency scaling.
> 
> It looks like they are clocked by the XO and a custom APSS type PLL.
> 
> Co-developed-by: Ansuel Smith <ansuelsmth@gmail.com>
> Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
> Signed-off-by: Robert Marko <robimarko@gmail.com>
> ---
> Changes in v2:
> * Convert to using parent-data instead of parent-names
> ---
>  drivers/clk/qcom/Kconfig        |  11 +++
>  drivers/clk/qcom/Makefile       |   1 +
>  drivers/clk/qcom/apss-ipq8074.c | 170 ++++++++++++++++++++++++++++++++
>  3 files changed, 182 insertions(+)
>  create mode 100644 drivers/clk/qcom/apss-ipq8074.c
> 
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index 00fe5f066de5..9494eb74374a 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -134,6 +134,17 @@ config IPQ_APSS_6018
>  	  Say Y if you want to support CPU frequency scaling on
>  	  ipq based devices.
>  
> +config IPQ_APSS_8074
> +	tristate "IPQ8074 APSS Clock Controller"
> +	select IPQ_GCC_8074
> +	depends on QCOM_APCS_IPC || COMPILE_TEST
> +	help
> +	  Support for APSS clock controller on IPQ8074 platforms. The
> +	  APSS clock controller manages the Mux and enable block that feeds the
> +	  CPUs.
> +	  Say Y if you want to support CPU frequency scaling on
> +	  IPQ8074 based devices.
> +
>  config IPQ_GCC_4019
>  	tristate "IPQ4019 Global Clock Controller"
>  	help
> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 671cf5821af1..7b2da6dd570c 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
>  obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
>  obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
>  obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
> +obj-$(CONFIG_IPQ_APSS_8074) += apss-ipq8074.o
>  obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
>  obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
>  obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
> diff --git a/drivers/clk/qcom/apss-ipq8074.c b/drivers/clk/qcom/apss-ipq8074.c
> new file mode 100644
> index 000000000000..38d03cd0ff76
> --- /dev/null
> +++ b/drivers/clk/qcom/apss-ipq8074.c
> @@ -0,0 +1,170 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022, The Linux Foundation. All rights reserved.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/clock/qcom,apss-ipq8074.h>
> +
> +#include "common.h"
> +#include "clk-regmap.h"
> +#include "clk-pll.h"
> +#include "clk-rcg.h"
> +#include "clk-branch.h"
> +#include "clk-alpha-pll.h"
> +#include "clk-regmap-divider.h"
> +#include "clk-regmap-mux.h"
> +
> +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
> +
> +enum {
> +	P_XO,
> +	P_GPLL0,
> +	P_GPLL2,
> +	P_GPLL4,
> +	P_APSS_PLL_EARLY,
> +	P_APSS_PLL
> +};
> +
> +static struct clk_alpha_pll apss_pll_early = {
> +	.offset = 0x5000,
> +	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
> +	.clkr = {
> +		.enable_reg = 0x5000,
> +		.enable_mask = BIT(0),
> +		.hw.init = &(struct clk_init_data){
> +			.name = "apss_pll_early",
> +			.parent_data = &(const struct clk_parent_data) {
> +				.fw_name = "xo", .name = "xo"
> +			},
> +			.num_parents = 1,
> +			.ops = &clk_alpha_pll_huayra_ops,
> +		},
> +	},
> +};
> +
> +static struct clk_alpha_pll_postdiv apss_pll = {
> +	.offset = 0x5000,
> +	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
> +	.width = 2,
> +	.clkr.hw.init = &(struct clk_init_data){
> +		.name = "apss_pll",
> +		.parent_hws = (const struct clk_hw *[]){
> +			&apss_pll_early.clkr.hw },
> +		.num_parents = 1,
> +		.ops = &clk_alpha_pll_postdiv_ro_ops,
> +	},
> +};
> +
> +static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
> +	{ .fw_name = "xo", .name = "xo" },
> +	{ .fw_name = "gpll0", .name = "gpll0" },
> +	{ .fw_name = "gpll2", .name = "gpll2" },
> +	{ .fw_name = "gpll4", .name = "gpll4" },
> +	{ .hw = &apss_pll.clkr.hw },
> +	{ .hw = &apss_pll_early.clkr.hw },
> +};
> +
> +static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
> +	{ P_XO, 0 },
> +	{ P_GPLL0, 4 },
> +	{ P_GPLL2, 2 },
> +	{ P_GPLL4, 1 },
> +	{ P_APSS_PLL, 3 },
> +	{ P_APSS_PLL_EARLY, 5 },
> +};
> +
> +struct freq_tbl ftbl_apcs_alias0_clk_src[] = {
> +	F(19200000, P_XO, 1, 0, 0),
> +	F(403200000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(806400000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1017600000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1382400000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1651200000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1843200000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1920000000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(2208000000UL, P_APSS_PLL_EARLY, 1, 0, 0),
> +	{ }
> +};
> +
> +struct clk_rcg2 apcs_alias0_clk_src = {
> +	.cmd_rcgr = 0x0050,
> +	.freq_tbl = ftbl_apcs_alias0_clk_src,
> +	.hid_width = 5,
> +	.parent_map = parents_apcs_alias0_clk_src_map,
> +	.clkr.hw.init = &(struct clk_init_data){
> +		.name = "apcs_alias0_clk_src",
> +		.parent_data = parents_apcs_alias0_clk_src,
> +		.num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src),
> +		.ops = &clk_rcg2_ops,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_branch apcs_alias0_core_clk = {
> +	.halt_reg = 0x0058,
> +	.halt_bit = 31,
> +	.clkr = {
> +		.enable_reg = 0x0058,
> +		.enable_mask = BIT(0),
> +		.hw.init = &(struct clk_init_data){
> +			.name = "apcs_alias0_core_clk",
> +			.parent_hws = (const struct clk_hw *[]){
> +				&apcs_alias0_clk_src.clkr.hw },
> +			.num_parents = 1,
> +			.flags = CLK_SET_RATE_PARENT |
> +				CLK_IS_CRITICAL,
> +			.ops = &clk_branch2_ops,
> +		},
> +	},
> +};
> +
> +static struct clk_regmap *apss_ipq8074_clks[] = {
> +	[APSS_PLL_EARLY] = &apss_pll_early.clkr,
> +	[APSS_PLL] = &apss_pll.clkr,
> +	[APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr,
> +	[APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr,
> +};
> +
> +static const struct regmap_config apss_ipq8074_regmap_config = {
> +	.reg_bits       = 32,
> +	.reg_stride     = 4,
> +	.val_bits       = 32,
> +	.max_register   = 0x5ffc,
> +	.fast_io	= true,
> +};
> +
> +static const struct qcom_cc_desc apss_ipq8074_desc = {
> +	.config = &apss_ipq8074_regmap_config,
> +	.clks = apss_ipq8074_clks,
> +	.num_clks = ARRAY_SIZE(apss_ipq8074_clks),
> +};
> +
> +static int apss_ipq8074_probe(struct platform_device *pdev)
> +{
> +	struct regmap *regmap;
> +
> +	regmap = dev_get_regmap(pdev->dev.parent, NULL);
> +	if (!regmap)
> +		return -ENODEV;
> +
> +	return qcom_cc_really_probe(pdev, &apss_ipq8074_desc, regmap);
> +}
> +
> +static struct platform_driver apss_ipq8074_driver = {
> +	.probe = apss_ipq8074_probe,
> +	.driver = {
> +		.name   = "qcom,apss-ipq8074-clk",

That's not the correct name of a driver - commas should not be there.
You need of_device_id instead.


Best regards,
Krzysztof
Bjorn Andersson June 30, 2022, 11:03 p.m. UTC | #2
On Sun 15 May 15:45 CDT 2022, Robert Marko wrote:

> IPQ8074 APSS clock controller provides the clock for the IPQ8074 CPU
> cores, thus also providing support for CPU frequency scaling.
> 
> It looks like they are clocked by the XO and a custom APSS type PLL.
> 
> Co-developed-by: Ansuel Smith <ansuelsmth@gmail.com>
> Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
> Signed-off-by: Robert Marko <robimarko@gmail.com>
> ---
> Changes in v2:
> * Convert to using parent-data instead of parent-names
> ---
>  drivers/clk/qcom/Kconfig        |  11 +++
>  drivers/clk/qcom/Makefile       |   1 +
>  drivers/clk/qcom/apss-ipq8074.c | 170 ++++++++++++++++++++++++++++++++
>  3 files changed, 182 insertions(+)
>  create mode 100644 drivers/clk/qcom/apss-ipq8074.c
> 
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index 00fe5f066de5..9494eb74374a 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -134,6 +134,17 @@ config IPQ_APSS_6018
>  	  Say Y if you want to support CPU frequency scaling on
>  	  ipq based devices.
>  
> +config IPQ_APSS_8074
> +	tristate "IPQ8074 APSS Clock Controller"
> +	select IPQ_GCC_8074
> +	depends on QCOM_APCS_IPC || COMPILE_TEST
> +	help
> +	  Support for APSS clock controller on IPQ8074 platforms. The
> +	  APSS clock controller manages the Mux and enable block that feeds the
> +	  CPUs.
> +	  Say Y if you want to support CPU frequency scaling on
> +	  IPQ8074 based devices.
> +
>  config IPQ_GCC_4019
>  	tristate "IPQ4019 Global Clock Controller"
>  	help
> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 671cf5821af1..7b2da6dd570c 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
>  obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
>  obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
>  obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
> +obj-$(CONFIG_IPQ_APSS_8074) += apss-ipq8074.o
>  obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
>  obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
>  obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
> diff --git a/drivers/clk/qcom/apss-ipq8074.c b/drivers/clk/qcom/apss-ipq8074.c
> new file mode 100644
> index 000000000000..38d03cd0ff76
> --- /dev/null
> +++ b/drivers/clk/qcom/apss-ipq8074.c
> @@ -0,0 +1,170 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022, The Linux Foundation. All rights reserved.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/clock/qcom,apss-ipq8074.h>
> +
> +#include "common.h"
> +#include "clk-regmap.h"
> +#include "clk-pll.h"
> +#include "clk-rcg.h"
> +#include "clk-branch.h"
> +#include "clk-alpha-pll.h"
> +#include "clk-regmap-divider.h"
> +#include "clk-regmap-mux.h"
> +
> +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
> +
> +enum {
> +	P_XO,
> +	P_GPLL0,
> +	P_GPLL2,
> +	P_GPLL4,
> +	P_APSS_PLL_EARLY,
> +	P_APSS_PLL
> +};
> +
> +static struct clk_alpha_pll apss_pll_early = {
> +	.offset = 0x5000,
> +	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
> +	.clkr = {
> +		.enable_reg = 0x5000,
> +		.enable_mask = BIT(0),
> +		.hw.init = &(struct clk_init_data){
> +			.name = "apss_pll_early",
> +			.parent_data = &(const struct clk_parent_data) {
> +				.fw_name = "xo", .name = "xo"
> +			},
> +			.num_parents = 1,
> +			.ops = &clk_alpha_pll_huayra_ops,
> +		},
> +	},
> +};
> +
> +static struct clk_alpha_pll_postdiv apss_pll = {
> +	.offset = 0x5000,
> +	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
> +	.width = 2,
> +	.clkr.hw.init = &(struct clk_init_data){
> +		.name = "apss_pll",
> +		.parent_hws = (const struct clk_hw *[]){
> +			&apss_pll_early.clkr.hw },
> +		.num_parents = 1,
> +		.ops = &clk_alpha_pll_postdiv_ro_ops,
> +	},
> +};
> +
> +static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
> +	{ .fw_name = "xo", .name = "xo" },
> +	{ .fw_name = "gpll0", .name = "gpll0" },
> +	{ .fw_name = "gpll2", .name = "gpll2" },
> +	{ .fw_name = "gpll4", .name = "gpll4" },
> +	{ .hw = &apss_pll.clkr.hw },
> +	{ .hw = &apss_pll_early.clkr.hw },
> +};
> +
> +static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
> +	{ P_XO, 0 },
> +	{ P_GPLL0, 4 },
> +	{ P_GPLL2, 2 },
> +	{ P_GPLL4, 1 },
> +	{ P_APSS_PLL, 3 },
> +	{ P_APSS_PLL_EARLY, 5 },
> +};
> +
> +struct freq_tbl ftbl_apcs_alias0_clk_src[] = {
> +	F(19200000, P_XO, 1, 0, 0),
> +	F(403200000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(806400000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1017600000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1382400000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1651200000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1843200000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(1920000000, P_APSS_PLL_EARLY, 1, 0, 0),
> +	F(2208000000UL, P_APSS_PLL_EARLY, 1, 0, 0),
> +	{ }
> +};
> +
> +struct clk_rcg2 apcs_alias0_clk_src = {
> +	.cmd_rcgr = 0x0050,
> +	.freq_tbl = ftbl_apcs_alias0_clk_src,
> +	.hid_width = 5,
> +	.parent_map = parents_apcs_alias0_clk_src_map,
> +	.clkr.hw.init = &(struct clk_init_data){
> +		.name = "apcs_alias0_clk_src",
> +		.parent_data = parents_apcs_alias0_clk_src,
> +		.num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src),
> +		.ops = &clk_rcg2_ops,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_branch apcs_alias0_core_clk = {
> +	.halt_reg = 0x0058,
> +	.halt_bit = 31,
> +	.clkr = {
> +		.enable_reg = 0x0058,
> +		.enable_mask = BIT(0),
> +		.hw.init = &(struct clk_init_data){
> +			.name = "apcs_alias0_core_clk",
> +			.parent_hws = (const struct clk_hw *[]){
> +				&apcs_alias0_clk_src.clkr.hw },
> +			.num_parents = 1,
> +			.flags = CLK_SET_RATE_PARENT |
> +				CLK_IS_CRITICAL,
> +			.ops = &clk_branch2_ops,
> +		},
> +	},
> +};
> +
> +static struct clk_regmap *apss_ipq8074_clks[] = {
> +	[APSS_PLL_EARLY] = &apss_pll_early.clkr,
> +	[APSS_PLL] = &apss_pll.clkr,
> +	[APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr,
> +	[APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr,
> +};
> +
> +static const struct regmap_config apss_ipq8074_regmap_config = {
> +	.reg_bits       = 32,
> +	.reg_stride     = 4,
> +	.val_bits       = 32,
> +	.max_register   = 0x5ffc,
> +	.fast_io	= true,
> +};
> +
> +static const struct qcom_cc_desc apss_ipq8074_desc = {
> +	.config = &apss_ipq8074_regmap_config,
> +	.clks = apss_ipq8074_clks,
> +	.num_clks = ARRAY_SIZE(apss_ipq8074_clks),
> +};
> +
> +static int apss_ipq8074_probe(struct platform_device *pdev)
> +{
> +	struct regmap *regmap;
> +
> +	regmap = dev_get_regmap(pdev->dev.parent, NULL);
> +	if (!regmap)
> +		return -ENODEV;
> +
> +	return qcom_cc_really_probe(pdev, &apss_ipq8074_desc, regmap);
> +}
> +
> +static struct platform_driver apss_ipq8074_driver = {
> +	.probe = apss_ipq8074_probe,
> +	.driver = {
> +		.name   = "qcom,apss-ipq8074-clk",

As pointed out by Krzysztof, this shouldn't have a ',' in there and if
you look at msm8916 it uses "qcom-apcs-msm8916-clk", so please follow
that.

I don't know if you intend to actually build this as a module, but if
so, wouldn't you also need
MODULE_ALIAS("platform:qcom-apss-ipq8074-clk"); to make module loading
pick this thing up?

Regards,
Bjorn

> +	},
> +};
> +
> +module_platform_driver(apss_ipq8074_driver);
> +
> +MODULE_DESCRIPTION("Qualcomm IPQ8074 APSS clock driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.36.1
>
Robert Marko July 4, 2022, 12:14 p.m. UTC | #3
On Fri, 1 Jul 2022 at 01:03, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>
> On Sun 15 May 15:45 CDT 2022, Robert Marko wrote:
>
> > IPQ8074 APSS clock controller provides the clock for the IPQ8074 CPU
> > cores, thus also providing support for CPU frequency scaling.
> >
> > It looks like they are clocked by the XO and a custom APSS type PLL.
> >
> > Co-developed-by: Ansuel Smith <ansuelsmth@gmail.com>
> > Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
> > Signed-off-by: Robert Marko <robimarko@gmail.com>
> > ---
> > Changes in v2:
> > * Convert to using parent-data instead of parent-names
> > ---
> >  drivers/clk/qcom/Kconfig        |  11 +++
> >  drivers/clk/qcom/Makefile       |   1 +
> >  drivers/clk/qcom/apss-ipq8074.c | 170 ++++++++++++++++++++++++++++++++
> >  3 files changed, 182 insertions(+)
> >  create mode 100644 drivers/clk/qcom/apss-ipq8074.c
> >
> > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> > index 00fe5f066de5..9494eb74374a 100644
> > --- a/drivers/clk/qcom/Kconfig
> > +++ b/drivers/clk/qcom/Kconfig
> > @@ -134,6 +134,17 @@ config IPQ_APSS_6018
> >         Say Y if you want to support CPU frequency scaling on
> >         ipq based devices.
> >
> > +config IPQ_APSS_8074
> > +     tristate "IPQ8074 APSS Clock Controller"
> > +     select IPQ_GCC_8074
> > +     depends on QCOM_APCS_IPC || COMPILE_TEST
> > +     help
> > +       Support for APSS clock controller on IPQ8074 platforms. The
> > +       APSS clock controller manages the Mux and enable block that feeds the
> > +       CPUs.
> > +       Say Y if you want to support CPU frequency scaling on
> > +       IPQ8074 based devices.
> > +
> >  config IPQ_GCC_4019
> >       tristate "IPQ4019 Global Clock Controller"
> >       help
> > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> > index 671cf5821af1..7b2da6dd570c 100644
> > --- a/drivers/clk/qcom/Makefile
> > +++ b/drivers/clk/qcom/Makefile
> > @@ -22,6 +22,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
> >  obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
> >  obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
> >  obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
> > +obj-$(CONFIG_IPQ_APSS_8074) += apss-ipq8074.o
> >  obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
> >  obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
> >  obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
> > diff --git a/drivers/clk/qcom/apss-ipq8074.c b/drivers/clk/qcom/apss-ipq8074.c
> > new file mode 100644
> > index 000000000000..38d03cd0ff76
> > --- /dev/null
> > +++ b/drivers/clk/qcom/apss-ipq8074.c
> > @@ -0,0 +1,170 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2022, The Linux Foundation. All rights reserved.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/err.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <dt-bindings/clock/qcom,apss-ipq8074.h>
> > +
> > +#include "common.h"
> > +#include "clk-regmap.h"
> > +#include "clk-pll.h"
> > +#include "clk-rcg.h"
> > +#include "clk-branch.h"
> > +#include "clk-alpha-pll.h"
> > +#include "clk-regmap-divider.h"
> > +#include "clk-regmap-mux.h"
> > +
> > +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
> > +
> > +enum {
> > +     P_XO,
> > +     P_GPLL0,
> > +     P_GPLL2,
> > +     P_GPLL4,
> > +     P_APSS_PLL_EARLY,
> > +     P_APSS_PLL
> > +};
> > +
> > +static struct clk_alpha_pll apss_pll_early = {
> > +     .offset = 0x5000,
> > +     .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
> > +     .clkr = {
> > +             .enable_reg = 0x5000,
> > +             .enable_mask = BIT(0),
> > +             .hw.init = &(struct clk_init_data){
> > +                     .name = "apss_pll_early",
> > +                     .parent_data = &(const struct clk_parent_data) {
> > +                             .fw_name = "xo", .name = "xo"
> > +                     },
> > +                     .num_parents = 1,
> > +                     .ops = &clk_alpha_pll_huayra_ops,
> > +             },
> > +     },
> > +};
> > +
> > +static struct clk_alpha_pll_postdiv apss_pll = {
> > +     .offset = 0x5000,
> > +     .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
> > +     .width = 2,
> > +     .clkr.hw.init = &(struct clk_init_data){
> > +             .name = "apss_pll",
> > +             .parent_hws = (const struct clk_hw *[]){
> > +                     &apss_pll_early.clkr.hw },
> > +             .num_parents = 1,
> > +             .ops = &clk_alpha_pll_postdiv_ro_ops,
> > +     },
> > +};
> > +
> > +static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
> > +     { .fw_name = "xo", .name = "xo" },
> > +     { .fw_name = "gpll0", .name = "gpll0" },
> > +     { .fw_name = "gpll2", .name = "gpll2" },
> > +     { .fw_name = "gpll4", .name = "gpll4" },
> > +     { .hw = &apss_pll.clkr.hw },
> > +     { .hw = &apss_pll_early.clkr.hw },
> > +};
> > +
> > +static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
> > +     { P_XO, 0 },
> > +     { P_GPLL0, 4 },
> > +     { P_GPLL2, 2 },
> > +     { P_GPLL4, 1 },
> > +     { P_APSS_PLL, 3 },
> > +     { P_APSS_PLL_EARLY, 5 },
> > +};
> > +
> > +struct freq_tbl ftbl_apcs_alias0_clk_src[] = {
> > +     F(19200000, P_XO, 1, 0, 0),
> > +     F(403200000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(806400000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(1017600000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(1382400000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(1651200000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(1843200000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(1920000000, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     F(2208000000UL, P_APSS_PLL_EARLY, 1, 0, 0),
> > +     { }
> > +};
> > +
> > +struct clk_rcg2 apcs_alias0_clk_src = {
> > +     .cmd_rcgr = 0x0050,
> > +     .freq_tbl = ftbl_apcs_alias0_clk_src,
> > +     .hid_width = 5,
> > +     .parent_map = parents_apcs_alias0_clk_src_map,
> > +     .clkr.hw.init = &(struct clk_init_data){
> > +             .name = "apcs_alias0_clk_src",
> > +             .parent_data = parents_apcs_alias0_clk_src,
> > +             .num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src),
> > +             .ops = &clk_rcg2_ops,
> > +             .flags = CLK_SET_RATE_PARENT,
> > +     },
> > +};
> > +
> > +static struct clk_branch apcs_alias0_core_clk = {
> > +     .halt_reg = 0x0058,
> > +     .halt_bit = 31,
> > +     .clkr = {
> > +             .enable_reg = 0x0058,
> > +             .enable_mask = BIT(0),
> > +             .hw.init = &(struct clk_init_data){
> > +                     .name = "apcs_alias0_core_clk",
> > +                     .parent_hws = (const struct clk_hw *[]){
> > +                             &apcs_alias0_clk_src.clkr.hw },
> > +                     .num_parents = 1,
> > +                     .flags = CLK_SET_RATE_PARENT |
> > +                             CLK_IS_CRITICAL,
> > +                     .ops = &clk_branch2_ops,
> > +             },
> > +     },
> > +};
> > +
> > +static struct clk_regmap *apss_ipq8074_clks[] = {
> > +     [APSS_PLL_EARLY] = &apss_pll_early.clkr,
> > +     [APSS_PLL] = &apss_pll.clkr,
> > +     [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr,
> > +     [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr,
> > +};
> > +
> > +static const struct regmap_config apss_ipq8074_regmap_config = {
> > +     .reg_bits       = 32,
> > +     .reg_stride     = 4,
> > +     .val_bits       = 32,
> > +     .max_register   = 0x5ffc,
> > +     .fast_io        = true,
> > +};
> > +
> > +static const struct qcom_cc_desc apss_ipq8074_desc = {
> > +     .config = &apss_ipq8074_regmap_config,
> > +     .clks = apss_ipq8074_clks,
> > +     .num_clks = ARRAY_SIZE(apss_ipq8074_clks),
> > +};
> > +
> > +static int apss_ipq8074_probe(struct platform_device *pdev)
> > +{
> > +     struct regmap *regmap;
> > +
> > +     regmap = dev_get_regmap(pdev->dev.parent, NULL);
> > +     if (!regmap)
> > +             return -ENODEV;
> > +
> > +     return qcom_cc_really_probe(pdev, &apss_ipq8074_desc, regmap);
> > +}
> > +
> > +static struct platform_driver apss_ipq8074_driver = {
> > +     .probe = apss_ipq8074_probe,
> > +     .driver = {
> > +             .name   = "qcom,apss-ipq8074-clk",
>
> As pointed out by Krzysztof, this shouldn't have a ',' in there and if
> you look at msm8916 it uses "qcom-apcs-msm8916-clk", so please follow
> that.

Hi,
Sorry for the late reply.

Will fix it up in v5.

>
> I don't know if you intend to actually build this as a module, but if
> so, wouldn't you also need
> MODULE_ALIAS("platform:qcom-apss-ipq8074-clk"); to make module loading
> pick this thing up?

I never tried it as a module, however, there is nothing special here that would
require it to be boolean.

It works fine as a module, but like you stated MODULE_ALIAS is required so it
gets autoloaded, I will add it in v5.

Regards,
Robert
>
> Regards,
> Bjorn
>
> > +     },
> > +};
> > +
> > +module_platform_driver(apss_ipq8074_driver);
> > +
> > +MODULE_DESCRIPTION("Qualcomm IPQ8074 APSS clock driver");
> > +MODULE_LICENSE("GPL");
> > --
> > 2.36.1
> >
diff mbox series

Patch

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 00fe5f066de5..9494eb74374a 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -134,6 +134,17 @@  config IPQ_APSS_6018
 	  Say Y if you want to support CPU frequency scaling on
 	  ipq based devices.
 
+config IPQ_APSS_8074
+	tristate "IPQ8074 APSS Clock Controller"
+	select IPQ_GCC_8074
+	depends on QCOM_APCS_IPC || COMPILE_TEST
+	help
+	  Support for APSS clock controller on IPQ8074 platforms. The
+	  APSS clock controller manages the Mux and enable block that feeds the
+	  CPUs.
+	  Say Y if you want to support CPU frequency scaling on
+	  IPQ8074 based devices.
+
 config IPQ_GCC_4019
 	tristate "IPQ4019 Global Clock Controller"
 	help
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 671cf5821af1..7b2da6dd570c 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -22,6 +22,7 @@  obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
 obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
 obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
 obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
+obj-$(CONFIG_IPQ_APSS_8074) += apss-ipq8074.o
 obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
 obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
 obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
diff --git a/drivers/clk/qcom/apss-ipq8074.c b/drivers/clk/qcom/apss-ipq8074.c
new file mode 100644
index 000000000000..38d03cd0ff76
--- /dev/null
+++ b/drivers/clk/qcom/apss-ipq8074.c
@@ -0,0 +1,170 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,apss-ipq8074.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "clk-alpha-pll.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+	P_XO,
+	P_GPLL0,
+	P_GPLL2,
+	P_GPLL4,
+	P_APSS_PLL_EARLY,
+	P_APSS_PLL
+};
+
+static struct clk_alpha_pll apss_pll_early = {
+	.offset = 0x5000,
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
+	.clkr = {
+		.enable_reg = 0x5000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "apss_pll_early",
+			.parent_data = &(const struct clk_parent_data) {
+				.fw_name = "xo", .name = "xo"
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_huayra_ops,
+		},
+	},
+};
+
+static struct clk_alpha_pll_postdiv apss_pll = {
+	.offset = 0x5000,
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS],
+	.width = 2,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "apss_pll",
+		.parent_hws = (const struct clk_hw *[]){
+			&apss_pll_early.clkr.hw },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ro_ops,
+	},
+};
+
+static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
+	{ .fw_name = "xo", .name = "xo" },
+	{ .fw_name = "gpll0", .name = "gpll0" },
+	{ .fw_name = "gpll2", .name = "gpll2" },
+	{ .fw_name = "gpll4", .name = "gpll4" },
+	{ .hw = &apss_pll.clkr.hw },
+	{ .hw = &apss_pll_early.clkr.hw },
+};
+
+static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 4 },
+	{ P_GPLL2, 2 },
+	{ P_GPLL4, 1 },
+	{ P_APSS_PLL, 3 },
+	{ P_APSS_PLL_EARLY, 5 },
+};
+
+struct freq_tbl ftbl_apcs_alias0_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(403200000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(806400000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(1017600000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(1382400000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(1651200000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(1843200000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(1920000000, P_APSS_PLL_EARLY, 1, 0, 0),
+	F(2208000000UL, P_APSS_PLL_EARLY, 1, 0, 0),
+	{ }
+};
+
+struct clk_rcg2 apcs_alias0_clk_src = {
+	.cmd_rcgr = 0x0050,
+	.freq_tbl = ftbl_apcs_alias0_clk_src,
+	.hid_width = 5,
+	.parent_map = parents_apcs_alias0_clk_src_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "apcs_alias0_clk_src",
+		.parent_data = parents_apcs_alias0_clk_src,
+		.num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src),
+		.ops = &clk_rcg2_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_branch apcs_alias0_core_clk = {
+	.halt_reg = 0x0058,
+	.halt_bit = 31,
+	.clkr = {
+		.enable_reg = 0x0058,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "apcs_alias0_core_clk",
+			.parent_hws = (const struct clk_hw *[]){
+				&apcs_alias0_clk_src.clkr.hw },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT |
+				CLK_IS_CRITICAL,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_regmap *apss_ipq8074_clks[] = {
+	[APSS_PLL_EARLY] = &apss_pll_early.clkr,
+	[APSS_PLL] = &apss_pll.clkr,
+	[APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr,
+	[APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr,
+};
+
+static const struct regmap_config apss_ipq8074_regmap_config = {
+	.reg_bits       = 32,
+	.reg_stride     = 4,
+	.val_bits       = 32,
+	.max_register   = 0x5ffc,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc apss_ipq8074_desc = {
+	.config = &apss_ipq8074_regmap_config,
+	.clks = apss_ipq8074_clks,
+	.num_clks = ARRAY_SIZE(apss_ipq8074_clks),
+};
+
+static int apss_ipq8074_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+
+	regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!regmap)
+		return -ENODEV;
+
+	return qcom_cc_really_probe(pdev, &apss_ipq8074_desc, regmap);
+}
+
+static struct platform_driver apss_ipq8074_driver = {
+	.probe = apss_ipq8074_probe,
+	.driver = {
+		.name   = "qcom,apss-ipq8074-clk",
+	},
+};
+
+module_platform_driver(apss_ipq8074_driver);
+
+MODULE_DESCRIPTION("Qualcomm IPQ8074 APSS clock driver");
+MODULE_LICENSE("GPL");