From 699690ba51cff2af19840b4722f6a05b4be087c6 Mon Sep 17 00:00:00 2001 From: Mihaela Martinas Date: Wed, 16 Oct 2019 15:48:24 +0300 Subject: [PATCH 1/9] arm64: Introduce config for S32 Add configuration option for the NXP S32 platform family in Kconfig.platforms. For starters, the only SoC supported will be Treerunner (S32V234), with a single execution target: the S32V234-EVB (rev 29288) board. Signed-off-by: Mihaela Martinas Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Stefan-Gabriel Mirea Signed-off-by: Shawn Guo (cherry picked from commit 3d4e0158c1db518a3a0c4ada5b5a2b1539ce5643) --- arch/arm64/Kconfig.platforms | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 16d761475a86..17f1c34ec750 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -212,6 +212,11 @@ config ARCH_ROCKCHIP This enables support for the ARMv8 based Rockchip chipsets, like the RK3368. +config ARCH_S32 + bool "NXP S32 SoC Family" + help + This enables support for the NXP S32 family of processors. + config ARCH_SEATTLE bool "AMD Seattle SoC Family" help From 46fe72556efe672c53fd593c44036550a91ce0c3 Mon Sep 17 00:00:00 2001 From: Stefan-Gabriel Mirea Date: Wed, 16 Aug 2017 14:53:25 +0100 Subject: [PATCH 2/9] dt-bindings: clock: Document S32V234 MC_CGM and MC_ME Add DT bindings documentation for the upcoming S32V234 clk driver. Add s32v234-clock.h header, which is referred in MC_CGM documentation. Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Stefan-Gabriel Mirea --- .../bindings/clock/s32v234-mc_cgm.txt | 31 +++++++++++++++++++ .../bindings/clock/s32v234-mc_me.txt | 16 ++++++++++ include/dt-bindings/clock/s32v234-clock.h | 22 +++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/s32v234-mc_cgm.txt create mode 100644 Documentation/devicetree/bindings/clock/s32v234-mc_me.txt create mode 100644 include/dt-bindings/clock/s32v234-clock.h diff --git a/Documentation/devicetree/bindings/clock/s32v234-mc_cgm.txt b/Documentation/devicetree/bindings/clock/s32v234-mc_cgm.txt new file mode 100644 index 000000000000..d0d43e6ae597 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/s32v234-mc_cgm.txt @@ -0,0 +1,31 @@ +* NXP S32V234 Clock Generation Modules (MC_CGMs) + +The SoC supports four Clock Generation Modules, which provide registers for +system and peripherals clock source selection and division. See chapters 22 +("Clocking"), 23 ("Clock Generation Module (MC_CGM)") and 69 ("Mode Entry +Module (MC_ME)") in the reference manual[1]. + +This binding uses the common clock binding: + Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible: + Should be: + - "fsl,s32v234-mc_cgm0" for MC_CGM_0 + - "fsl,s32v234-mc_cgm1" for MC_CGM_1 + - "fsl,s32v234-mc_cgm2" for MC_CGM_2 + - "fsl,s32v234-mc_cgm3" for MC_CGM_3 +- reg: + Location and length of the register set +- #clock-cells (only for MC_CGM_0): + Should be <1>. See dt-bindings/clock/s32v234-clock.h for the clock + specifiers allowed in the clocks property of consumers. + +Example: +clks: mc_cgm0@4003c000 { + compatible = "fsl,s32v234-mc_cgm0"; + reg = <0x0 0x4003C000 0x0 0x1000>; + #clock-cells = <1>; +}; + +[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM diff --git a/Documentation/devicetree/bindings/clock/s32v234-mc_me.txt b/Documentation/devicetree/bindings/clock/s32v234-mc_me.txt new file mode 100644 index 000000000000..e9f4dcc3a257 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/s32v234-mc_me.txt @@ -0,0 +1,16 @@ +* NXP S32V234 Mode Entry Module (MC_ME) + +See chapters 22 ("Clocking") and 69 ("Mode Entry Module (MC_ME)") in the +reference manual[1]. + +Required properties: +- compatible: Should be "fsl,s32v234-mc_me" +- reg: Location and length of the register set + +Example: +mc_me: mc_me@4004a000 { + compatible = "fsl,s32v234-mc_me"; + reg = <0x0 0x4004A000 0x0 0x1000>; +}; + +[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM diff --git a/include/dt-bindings/clock/s32v234-clock.h b/include/dt-bindings/clock/s32v234-clock.h new file mode 100644 index 000000000000..c0ce57f9471a --- /dev/null +++ b/include/dt-bindings/clock/s32v234-clock.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright (C) 2017 NXP + */ + +#ifndef __DT_BINDINGS_CLOCK_S32V234_H +#define __DT_BINDINGS_CLOCK_S32V234_H + +#define S32V234_CLK_DUMMY 0 +#define S32V234_CLK_FXOSC 1 +#define S32V234_CLK_FIRC 2 +/* PERIPH PLL */ +#define S32V234_CLK_PERIPHPLL_SRC_SEL 3 +#define S32V234_CLK_PERIPHPLL_VCO 4 +#define S32V234_CLK_PERIPHPLL_PHI0 5 +#define S32V234_CLK_PERIPHPLL_PHI0_DIV3 6 +#define S32V234_CLK_PERIPHPLL_PHI0_DIV5 7 +#define S32V234_CLK_PERIPHPLL_PHI1 8 + +#define S32V234_CLK_END 9 +#endif /* __DT_BINDINGS_CLOCK_S32V234_H */ From 457bcf4d5d802c2b4076e58a18dabff31cce763c Mon Sep 17 00:00:00 2001 From: Stoica Cosmin-Stefan Date: Mon, 8 Jun 2015 18:55:18 +0300 Subject: [PATCH 3/9] clk: Add clk support for S32V234 Add clock framework for Treerunner (S32V234), based on code from the i.MX 3.10.17 codebase[1]. Add clock definitions that are used in the clocks vector (tree). At this point, the only PLL enabled is PERIPH-PLL. [1] https://source.codeaurora.org/external/imx/linux-imx/tree/?h=imx_3.10.17_1.0.0_ga_caf Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Larisa Grigore Signed-off-by: Stefan-Gabriel Mirea --- arch/arm64/Kconfig.platforms | 1 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/s32/Kconfig | 4 + drivers/clk/s32/Makefile | 2 + drivers/clk/s32/clk-core.c | 53 ++++++ drivers/clk/s32/clk.h | 55 ++++++ drivers/clk/s32/s32v234/Makefile | 1 + drivers/clk/s32/s32v234/clk-plldig.c | 240 +++++++++++++++++++++++++++ drivers/clk/s32/s32v234/clk.c | 109 ++++++++++++ drivers/clk/s32/s32v234/clk.h | 27 +++ drivers/clk/s32/s32v234/mc_cgm.h | 49 ++++++ drivers/clk/s32/s32v234/mc_me.h | 110 ++++++++++++ drivers/clk/s32/s32v234/pll.h | 78 +++++++++ drivers/clk/s32/s32v234/src.h | 17 ++ 15 files changed, 748 insertions(+) create mode 100644 drivers/clk/s32/Kconfig create mode 100644 drivers/clk/s32/Makefile create mode 100644 drivers/clk/s32/clk-core.c create mode 100644 drivers/clk/s32/clk.h create mode 100644 drivers/clk/s32/s32v234/Makefile create mode 100644 drivers/clk/s32/s32v234/clk-plldig.c create mode 100644 drivers/clk/s32/s32v234/clk.c create mode 100644 drivers/clk/s32/s32v234/clk.h create mode 100644 drivers/clk/s32/s32v234/mc_cgm.h create mode 100644 drivers/clk/s32/s32v234/mc_me.h create mode 100644 drivers/clk/s32/s32v234/pll.h create mode 100644 drivers/clk/s32/s32v234/src.h diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 17f1c34ec750..a94a14bd4e22 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -214,6 +214,7 @@ config ARCH_ROCKCHIP config ARCH_S32 bool "NXP S32 SoC Family" + select ARCH_S32_CLK help This enables support for the NXP S32 family of processors. diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c44247d0b83e..580828299b2c 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -318,6 +318,7 @@ source "drivers/clk/meson/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" +source "drivers/clk/s32/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/sprd/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 0138fb14e6f8..0fa07e17db98 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_COMMON_CLK_PXA) += pxa/ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ obj-y += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ +obj-$(CONFIG_ARCH_S32) += s32/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_ARCH_SIRF) += sirf/ diff --git a/drivers/clk/s32/Kconfig b/drivers/clk/s32/Kconfig new file mode 100644 index 000000000000..c28bdbbfaa3a --- /dev/null +++ b/drivers/clk/s32/Kconfig @@ -0,0 +1,4 @@ +config ARCH_S32_CLK + bool "Enable S32 CLK Framework" + help + Support for the Clock Framework on S32 SoCs. diff --git a/drivers/clk/s32/Makefile b/drivers/clk/s32/Makefile new file mode 100644 index 000000000000..169b8b5900f9 --- /dev/null +++ b/drivers/clk/s32/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ARCH_S32_CLK) += clk-core.o +obj-$(CONFIG_ARCH_S32_CLK) += s32v234/ diff --git a/drivers/clk/s32/clk-core.c b/drivers/clk/s32/clk-core.c new file mode 100644 index 000000000000..a8cca66f7959 --- /dev/null +++ b/drivers/clk/s32/clk-core.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + */ + +#include +#include +#include +#include +#include +#include "clk.h" + +void __init s32_check_clocks(struct clk *clks[], unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + if (IS_ERR(clks[i])) + pr_err("S32 clk %u: register failed with %ld\n", + i, PTR_ERR(clks[i])); +} + +static struct clk * __init s32_obtain_fixed_clock_from_dt(const char *name) +{ + struct of_phandle_args phandle; + struct clk *clk = ERR_PTR(-ENODEV); + char *path; + + path = kasprintf(GFP_KERNEL, "/clocks/%s", name); + if (!path) + return ERR_PTR(-ENOMEM); + + phandle.np = of_find_node_by_path(path); + kfree(path); + + if (phandle.np) { + clk = of_clk_get_from_provider(&phandle); + of_node_put(phandle.np); + } + return clk; +} + +struct clk * __init s32_obtain_fixed_clock( + const char *name, unsigned long rate) +{ + struct clk *clk; + + clk = s32_obtain_fixed_clock_from_dt(name); + if (IS_ERR(clk)) + clk = s32_clk_fixed(name, rate); + return clk; +} diff --git a/drivers/clk/s32/clk.h b/drivers/clk/s32/clk.h new file mode 100644 index 000000000000..83100641158f --- /dev/null +++ b/drivers/clk/s32/clk.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + */ + +#ifndef __MACH_S32_CLK_H +#define __MACH_S32_CLK_H + +#include +#include + +#define PNAME(x) \ + static const char *x[] __initconst + +void s32_check_clocks(struct clk *clks[], unsigned int count); + +struct clk *s32_obtain_fixed_clock( + const char *name, unsigned long rate); + +static inline struct clk *s32_clk_fixed(const char *name, unsigned long rate) +{ + return clk_register_fixed_rate(NULL, name, NULL, 0, rate); +} + +static inline struct clk *s32_clk_divider(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, + spinlock_t *lock) +{ + struct clk *tmp_clk = clk_register_divider(NULL, name, parent, + CLK_SET_RATE_PARENT, + reg, shift, width, 0, lock); + + return tmp_clk; +} + +static inline struct clk *s32_clk_mux(const char *name, void __iomem *reg, + u8 shift, u8 width, const char **parents, + u8 num_parents, spinlock_t *lock) +{ + return clk_register_mux(NULL, name, parents, num_parents, + CLK_SET_RATE_NO_REPARENT, reg, shift, + width, 0, lock); +} + +static inline struct clk *s32_clk_fixed_factor(const char *name, + const char *parent, + unsigned int mult, + unsigned int div) +{ + return clk_register_fixed_factor(NULL, name, parent, + CLK_SET_RATE_PARENT, mult, div); +} + +#endif diff --git a/drivers/clk/s32/s32v234/Makefile b/drivers/clk/s32/s32v234/Makefile new file mode 100644 index 000000000000..54f77523dbcd --- /dev/null +++ b/drivers/clk/s32/s32v234/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_S32_CLK) += clk.o clk-plldig.o diff --git a/drivers/clk/s32/s32v234/clk-plldig.c b/drivers/clk/s32/s32v234/clk-plldig.c new file mode 100644 index 000000000000..6ed23974ee63 --- /dev/null +++ b/drivers/clk/s32/s32v234/clk-plldig.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" + +/* + * struct clk_plldig - S32 PLLDIG clock + * @clk_hw: clock source + * @base: base address of PLL registers + * @plldv_mfd: multiplication loop factor divider + * @plldv_rfdphi: PHI reduced frequency divider + * @plldv_rfdphi1: PHI reduced frequency divider + * + * PLLDIG clock version 1, found on S32 series. + */ +struct clk_plldig { + struct clk_hw hw; + void __iomem *base; + enum s32v234_plldig_type type; + u32 plldv_mfd; + u32 pllfd_mfn; + u32 plldv_rfdphi; + u32 plldv_rfdphi1; +}; + +#define to_clk_plldig(_hw) container_of(_hw, struct clk_plldig, hw) + +static unsigned long get_pllx_max_vco_rate(enum s32v234_plldig_type plltype) +{ + switch (plltype) { + case S32_PLLDIG_PERIPH: + return PERIPHPLL_MAX_VCO_RATE; + default: + pr_warn("Unsupported PLL.\n"); + return -EINVAL; + } +} + +static unsigned long get_pllx_phiy_max_rate(enum s32v234_plldig_type plltype, + unsigned int phino) +{ + switch (plltype) { + case S32_PLLDIG_PERIPH: + switch (phino) { + case 0: + return PERIPHPLL_MAX_PHI0_MAX_RATE; + case 1: + return PERIPHPLL_MAX_PHI1_MAX_RATE; + default: + break; + } + break; + default: + pr_warn("Unsupported PLL.\n"); + break; + } + return -EINVAL; +} + +static int clk_plldig_prepare(struct clk_hw *hw) +{ + return 0; +} + +static void clk_plldig_unprepare(struct clk_hw *hw) +{ +} + +static unsigned long clk_plldig_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_plldig *pll = to_clk_plldig(hw); + u32 plldv = readl_relaxed(PLLDIG_PLLDV(pll->base)); + u32 pllfd = readl_relaxed(PLLDIG_PLLFD(pll->base)); + u32 prediv, mfd, mfn, vco; + + prediv = (plldv & PLLDIG_PLLDV_PREDIV_MASK) + >> PLLDIG_PLLDV_PREDIV_OFFSET; + mfd = (plldv & PLLDIG_PLLDV_MFD_MASK); + + mfn = (pllfd & PLLDIG_PLLFD_MFN_MASK); + + if (prediv == 0) + prediv = 1; + + /* + * This formula is from platform reference manual + * (Rev. 1, 6/2015), PLLDIG chapter. + */ + vco = (parent_rate / prediv) * (mfd + mfn / 20480); + + return vco; +} + +static long clk_plldig_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_plldig *pll = to_clk_plldig(hw); + unsigned long max_allowed_rate = get_pllx_max_vco_rate(pll->type); + + if (rate > max_allowed_rate) + rate = max_allowed_rate; + else if (rate < MIN_VCO_RATE) + rate = MIN_VCO_RATE; + + return rate; +} + +static int clk_plldig_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_plldig *pll = to_clk_plldig(hw); + u32 pllfd, prediv; + + unsigned long max_allowed_rate = get_pllx_max_vco_rate(pll->type); + unsigned long phi0_max_rate = get_pllx_phiy_max_rate(pll->type, 0); + unsigned long phi1_max_rate = get_pllx_phiy_max_rate(pll->type, 1); + + if (rate < MIN_VCO_RATE || rate > max_allowed_rate) + return -EINVAL; + + if (((rate / pll->plldv_rfdphi) > phi0_max_rate) || + ((rate / pll->plldv_rfdphi) > phi1_max_rate)) + return -EINVAL; + + pllfd = readl_relaxed(PLLDIG_PLLFD(pll->base)); + prediv = (parent_rate / rate) * + (pll->plldv_mfd + pll->pllfd_mfn / 20480); + + writel_relaxed(PLLDIG_PLLDV_RFDPHI1_SET(pll->plldv_rfdphi1) | + PLLDIG_PLLDV_RFDPHI_SET(pll->plldv_rfdphi) | + PLLDIG_PLLDV_PREDIV_SET(prediv) | + PLLDIG_PLLDV_MFD_SET(pll->plldv_mfd), + PLLDIG_PLLDV(pll->base)); + + writel_relaxed(pllfd | PLLDIG_PLLFD_MFN_SET(pll->pllfd_mfn), + PLLDIG_PLLFD(pll->base)); + + /* + * To be implemented the wait_lock or an equivalent state + * return clk_plldig_wait_lock(pll); + */ + return 0; +} + +static const struct clk_ops clk_plldig_ops = { + .prepare = clk_plldig_prepare, + .unprepare = clk_plldig_unprepare, + .recalc_rate = clk_plldig_recalc_rate, + .round_rate = clk_plldig_round_rate, + .set_rate = clk_plldig_set_rate, +}; + +struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type, + const char *name, const char *parent, + void __iomem *base, u32 phi) +{ + u32 plldv, rfd_phi; + + if (!base) + return ERR_PTR(-ENOMEM); + + plldv = readl_relaxed(PLLDIG_PLLDV(base)); + + switch (phi) { + /* PHI0 */ + case 0: + rfd_phi = (plldv & PLLDIG_PLLDV_RFDPHI_MASK) + >> PLLDIG_PLLDV_RFDPHI_OFFSET; + break; + /* PHI1 */ + case 1: + rfd_phi = (plldv & PLLDIG_PLLDV_RFDPHI1_MASK) + >> PLLDIG_PLLDV_RFDPHI1_OFFSET; + + if (rfd_phi == 0) + rfd_phi = 1; + + break; + default: + return ERR_PTR(-EINVAL); + } + + return clk_register_fixed_factor(NULL, name, parent, + CLK_SET_RATE_PARENT, 1, rfd_phi); +} + +struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name, + const char *parent_name, void __iomem *base, + u32 plldv_mfd, u32 pllfd_mfn, + u32 plldv_rfdphi, u32 plldv_rfdphi1) +{ + struct clk_plldig *pll; + const struct clk_ops *ops; + struct clk *clk; + struct clk_init_data init; + + if (plldv_rfdphi > PLLDIG_PLLDV_RFDPHI_MAXVALUE) + return ERR_PTR(-EINVAL); + + if (plldv_rfdphi1 > PLLDIG_PLLDV_RFDPHI1_MAXVALUE) + return ERR_PTR(-EINVAL); + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + ops = &clk_plldig_ops; + + pll->base = base; + pll->type = type; + pll->plldv_mfd = plldv_mfd; + pll->pllfd_mfn = pllfd_mfn; + pll->plldv_rfdphi = plldv_rfdphi; + pll->plldv_rfdphi1 = plldv_rfdphi1; + + init.name = name; + init.ops = ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll->hw.init = &init; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c new file mode 100644 index 000000000000..2fd325d92a5d --- /dev/null +++ b/drivers/clk/s32/s32v234/clk.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + */ + +#include +#include +#include + +#include "clk.h" + +static void __iomem *mc_cgm0_base; +static void __iomem *mc_me_base; +static void __iomem *src_base; + +DEFINE_SPINLOCK(s32v234_lock); + +/* sources for multiplexer clocks, this is used multiple times */ +PNAME(osc_sels) = {"firc", "fxosc", }; + +static struct clk *clk[S32V234_CLK_END]; +static struct clk_onecell_data clk_data; + +static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) +{ + struct device_node *np; + + clk[S32V234_CLK_DUMMY] = s32_clk_fixed("dummy", 0); + clk[S32V234_CLK_FXOSC] = s32_obtain_fixed_clock("fxosc", 0); + clk[S32V234_CLK_FIRC] = s32_obtain_fixed_clock("firc", 0); + + np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_me"); + mc_me_base = of_iomap(np, 0); + if (WARN_ON(!mc_me_base)) + return; + + np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-src"); + src_base = of_iomap(np, 0); + if (WARN_ON(!src_base)) + return; + + np = mc_cgm0_node; + mc_cgm0_base = of_iomap(np, 0); + if (WARN_ON(!mc_cgm0_base)) + return; + + enable_cpumodes_onperipheralconfig(mc_me_base, MC_ME_RUN_PCn_DRUN | + MC_ME_RUN_PCn_RUN0 | + MC_ME_RUN_PCn_RUN1 | + MC_ME_RUN_PCn_RUN2 | + MC_ME_RUN_PCn_RUN3, + 0); + + /* turn on XOSC and FIRC */ + enable_clocks_sources(MC_ME_MODE_MC_MVRON, MC_ME_MODE_MC_XOSCON | + MC_ME_MODE_MC_FIRCON, + MC_ME_RUNn_MC(mc_me_base, 0)); + + /* transition the core to RUN0 mode */ + entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0); + + clk[S32V234_CLK_PERIPHPLL_SRC_SEL] = s32_clk_mux("periphpll_sel", + SRC_GPR1, SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET, + SRC_GPR1_XPLL_SRC_SEL_SIZE, + osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); + + /* PERIPH_PLL */ + clk[S32V234_CLK_PERIPHPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_PERIPH, + "periphpll_vco", "periphpll_sel", + PERIPHPLL_PLLDIG(mc_cgm0_base), + PERIPHPLL_PLLDIG_PLLDV_MFD, PERIPHPLL_PLLDIG_PLLDV_MFN, + PERIPHPLL_PLLDIG_PLLDV_RFDPHI0, + PERIPHPLL_PLLDIG_PLLDV_RFDPHI1); + + clk[S32V234_CLK_PERIPHPLL_PHI0] = + s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH, + "periphpll_phi0", "periphpll_vco", + PERIPHPLL_PLLDIG(mc_cgm0_base), 0); + + clk[S32V234_CLK_PERIPHPLL_PHI1] = + s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH, + "periphpll_phi1", "periphpll_vco", + PERIPHPLL_PLLDIG(mc_cgm0_base), 1); + + clk[S32V234_CLK_PERIPHPLL_PHI0_DIV3] = s32_clk_fixed_factor( + "periphpll_phi0_div3", "periphpll_phi0", 1, 3); + + clk[S32V234_CLK_PERIPHPLL_PHI0_DIV5] = s32_clk_fixed_factor( + "periphpll_phi0_div5", "periphpll_phi0", 1, 5); + + /* enable PERIPHPLL */ + enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL, + MC_ME_RUNn_MC(mc_me_base, 0)); + + /* set the system clock */ + enable_sysclock(MC_ME_MODE_MC_SYSCLK(0x2), + MC_ME_RUNn_MC(mc_me_base, 0)); + + /* transition the core to RUN0 mode */ + entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0); + + /* Add the clocks to provider list */ + clk_data.clks = clk; + clk_data.clk_num = ARRAY_SIZE(clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} + +CLK_OF_DECLARE(S32V234, "fsl,s32v234-mc_cgm0", s32v234_clocks_init); diff --git a/drivers/clk/s32/s32v234/clk.h b/drivers/clk/s32/s32v234/clk.h new file mode 100644 index 000000000000..ea69d13a90b5 --- /dev/null +++ b/drivers/clk/s32/s32v234/clk.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + */ + +#ifndef __MACH_S32V234_CLK_H +#define __MACH_S32V234_CLK_H + +#include +#include +#include "mc_cgm.h" +#include "mc_me.h" +#include "pll.h" +#include "src.h" +#include "../clk.h" + +struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name, + const char *parent_name, void __iomem *base, + u32 plldv_mfd, u32 plldv_mfn, + u32 plldv_rfdphi, u32 plldv_rfdphi1); + +struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type, + const char *name, const char *parent, + void __iomem *base, u32 phi); + +#endif diff --git a/drivers/clk/s32/s32v234/mc_cgm.h b/drivers/clk/s32/s32v234/mc_cgm.h new file mode 100644 index 000000000000..61a5fe61b2d1 --- /dev/null +++ b/drivers/clk/s32/s32v234/mc_cgm.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright (C) 2017 NXP + */ +#ifndef _MC_CGM_H +#define _MC_CGM_H + +#define PERIPHPLL_PLLDIG(mc_cgm) ((mc_cgm) + 0x80) +#define PERIPHPLL_PLLDIG_PLLDV_MFD (30) +#define PERIPHPLL_PLLDIG_PLLDV_MFN (0) +#define PERIPHPLL_PLLDIG_PLLDV_RFDPHI0 (0x1) +#define PERIPHPLL_PLLDIG_PLLDV_RFDPHI1 (0x1) + +/* MC_CGM_SC_SS */ +#define CGM_SC_SS(mc_cgm) (((mc_cgm) + 0x7E4)) + +/* MC_CGM_SC_DCn */ +#define CGM_SC_DCn(mc_cgm, dc) (((mc_cgm) + 0x7E8) + ((dc) * 0x4)) + +#define MC_CGM_SC_DCn_PREDIV_OFFSET (16) +#define MC_CGM_SC_DCn_PREDIV_SIZE (3) +#define MC_CGM_SC_DCn_DE (1 << 31) +#define MC_CGM_SC_SEL_OFFSET (24) +#define MC_CGM_SC_SEL_SIZE (4) + +/* MC_CGM_ACn_DCm */ +#define CGM_ACn_DCm(mc_cgm, ac, dc) (((mc_cgm) + 0x808) + ((ac) * 0x20)\ + + ((dc) * 0x4)) + +#define MC_CGM_ACn_DCm_PREDIV(val) (MC_CGM_ACn_DCm_PREDIV_MASK & \ + ((val) \ + << MC_CGM_ACn_DCm_PREDIV_OFFSET)) +#define MC_CGM_ACn_DCm_PREDIV_MASK (0x001F0000) +#define MC_CGM_ACn_DCm_PREDIV_OFFSET (16) +#define MC_CGM_ACn_DCm_PREDIV_SIZE (5) +#define MC_CGM_ACn_DCm_DE (1 << 31) + +/* MC_CGM_ACn_SC/MC_CGM_ACn_SS */ +#define CGM_ACn_SC(mc_cgm, ac) (((mc_cgm) + 0x800) + ((ac) * 0x20)) +#define CGM_ACn_SS(mc_cgm, ac) (((mc_cgm) + 0x804) + ((ac) * 0x24)) +#define MC_CGM_ACn_SEL_MASK (0x07000000) +#define MC_CGM_ACn_SEL_SET(source) (MC_CGM_ACn_SEL_MASK & \ + (((source) & 0x7) \ + << MC_CGM_ACn_SEL_OFFSET)) +#define MC_CGM_ACn_SEL_OFFSET (24) +#define MC_CGM_ACn_SEL_SIZE (4) + +#endif diff --git a/drivers/clk/s32/s32v234/mc_me.h b/drivers/clk/s32/s32v234/mc_me.h new file mode 100644 index 000000000000..718f1d1a0c30 --- /dev/null +++ b/drivers/clk/s32/s32v234/mc_me.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright (C) 2017 NXP + */ + +#ifndef _MC_ME_H +#define _MC_ME_H + +/* MC_ME registers definitions */ +/* MC_ME_GS */ + #define MC_ME_GS(mc_me) ((mc_me) + 0x00000000) + +/* MC_ME_MCTL */ +#define MC_ME_MCTL(mc_me) ((mc_me) + 0x00000004) +#define MC_ME_MCTL_RESET (0x0 << 28) +#define MC_ME_MCTL_TEST (0x1 << 28) +#define MC_ME_MCTL_DRUN (0x3 << 28) +#define MC_ME_MCTL_RUN0 (0x4 << 28) +#define MC_ME_MCTL_RUN1 (0x5 << 28) +#define MC_ME_MCTL_RUN2 (0x6 << 28) +#define MC_ME_MCTL_RUN3 (0x7 << 28) + +#define MC_ME_GS_S_MTRANS (1 << 27) + +#define MC_ME_MCTL_KEY (0x00005AF0) +#define MC_ME_MCTL_INVERTEDKEY (0x0000A50F) + +/* + * MC_ME_RESET_MC/MC_ME_TEST_MC + * MC_ME_DRUN_MC + * MC_ME_RUNn_MC + */ +#define MC_ME_RESET_MC(mc_me) ((mc_me) + 0x00000020) +#define MC_ME_TEST_MC(mc_me) ((mc_me) + 0x00000024) +#define MC_ME_DRUN_MC(mc_me) ((mc_me) + 0x0000002C) +#define MC_ME_RUNn_MC(mc_me, n) ((mc_me) + 0x00000030 + 0x4 * (n)) +#define MC_ME_MODE_MC_SYSCLK_OFFSET (0) +#define MC_ME_MODE_MC_SYSCLK_SIZE (0x3) +#define MC_ME_MODE_MC_SYSCLK(val) (MC_ME_MODE_MC_SYSCLK_MASK & (val)) +#define MC_ME_MODE_MC_SYSCLK_MASK (0x0000000F) +#define MC_ME_MODE_MC_FIRCON (1 << 4) +#define MC_ME_MODE_MC_XOSCON (1 << 5) +#define MC_ME_MODE_MC_ARMPLL (1 << 6) +#define MC_ME_MODE_MC_PERIPHPLL (1 << 7) +#define MC_ME_MODE_MC_ENETPLL (1 << 8) +#define MC_ME_MODE_MC_DDRPLL (1 << 9) +#define MC_ME_MODE_MC_VIDEOPLL (1 << 10) +#define MC_ME_MODE_MC_MVRON (1 << 20) + +/* MC_ME_DRUN_SEC_CC_I */ +#define MC_ME_DRUN_SEC_CC_I(mc_me) ((mc_me) + 0x260) +/* MC_ME_RUNn_SEC_CC_I */ +#define MC_ME_RUNn_SEC_CC_I(mc_me, n) ((mc_me) + 0x270 + (n) * 0x10) +#define MC_ME_MODE_SEC_CC_I_SYSCLK1_OFFSET (4) +#define MC_ME_MODE_SEC_CC_I_SYSCLK2_OFFSET (8) +#define MC_ME_MODE_SEC_CC_I_SYSCLK3_OFFSET (12) +/* Consider only the defined clocks */ +#define MC_ME_MODE_SEC_CC_I_SYSCLK1_SIZE (0x3) +#define MC_ME_MODE_SEC_CC_I_SYSCLK2_SIZE (0x3) +#define MC_ME_MODE_SEC_CC_I_SYSCLK3_SIZE (0x3) + +/* MC_ME_RUN_PCn */ +#define MC_ME_RUN_PCn(mc_me, n) (mc_me + 0x00000080 + 0x4 * (n)) + +#define MC_ME_RUN_PCn_MAX_IDX (7) +#define MC_ME_RUN_PCn_RESET (1 << 0) +#define MC_ME_RUN_PCn_TEST (1 << 1) +#define MC_ME_RUN_PCn_DRUN (1 << 3) +#define MC_ME_RUN_PCn_RUN0 (1 << 4) +#define MC_ME_RUN_PCn_RUN1 (1 << 5) +#define MC_ME_RUN_PCn_RUN2 (1 << 6) +#define MC_ME_RUN_PCn_RUN3 (1 << 7) + +#define MC_ME_PCTLn(mc_me, n) (mc_me + 0xC0 + 4 * (n >> 2) + \ + (3 - (n) % 4)) + +static inline void entry_to_target_mode(void __iomem *mc_me, u32 mode) +{ + writel_relaxed(mode | MC_ME_MCTL_KEY, MC_ME_MCTL(mc_me)); + writel_relaxed(mode | MC_ME_MCTL_INVERTEDKEY, MC_ME_MCTL(mc_me)); + while ((readl_relaxed(MC_ME_GS(mc_me)) & + MC_ME_GS_S_MTRANS) != 0x00000000) + ; +} + +static inline void enable_cpumodes_onperipheralconfig(void __iomem *mc_me, + u32 modes, u32 run_pc_idx) +{ + WARN_ON(run_pc_idx > MC_ME_RUN_PCn_MAX_IDX); + if (run_pc_idx > MC_ME_RUN_PCn_MAX_IDX) + return; + + writel_relaxed(modes, MC_ME_RUN_PCn(mc_me, run_pc_idx)); +} + +static inline void enable_clocks_sources(u32 flags, u32 clks, + void __iomem *xrun_mc_addr) +{ + writel_relaxed(readl_relaxed(xrun_mc_addr) | flags | clks, + xrun_mc_addr); +} + +static inline void enable_sysclock(u32 clk, void __iomem *xrun_mc_addr) +{ + writel_relaxed(readl_relaxed(xrun_mc_addr) & clk, + xrun_mc_addr); +} + +#endif diff --git a/drivers/clk/s32/s32v234/pll.h b/drivers/clk/s32/s32v234/pll.h new file mode 100644 index 000000000000..b7bcc50f0a22 --- /dev/null +++ b/drivers/clk/s32/s32v234/pll.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright (C) 2017-2018 NXP + */ +#ifndef _PLL_S32V234_H +#define _PLL_S32V234_H + +/* PLLDIG PLL Divider Register (PLLDIG_PLLDV) */ +#define PLLDIG_PLLDV(base) ((base) + 0x00000028) +#define PLLDIG_PLLDV_MFD_SET(val) (PLLDIG_PLLDV_MFD_MASK & (val)) +#define PLLDIG_PLLDV_MFD_MASK (0x000000FF) + +#define PLLDIG_PLLDV_RFDPHI_SET(val) (PLLDIG_PLLDV_RFDPHI_MASK & \ + (((val) & \ + PLLDIG_PLLDV_RFDPHI_MAXVALUE) \ + << PLLDIG_PLLDV_RFDPHI_OFFSET)) +#define PLLDIG_PLLDV_RFDPHI_MASK (0x003F0000) +#define PLLDIG_PLLDV_RFDPHI_MAXVALUE (0x3F) + +#define PLLDIG_PLLDV_RFDPHI_OFFSET (16) + +#define PLLDIG_PLLDV_RFDPHI1_SET(val) (PLLDIG_PLLDV_RFDPHI1_MASK & \ + (((val) & \ + PLLDIG_PLLDV_RFDPHI1_MAXVALUE) \ + << PLLDIG_PLLDV_RFDPHI1_OFFSET)) +#define PLLDIG_PLLDV_RFDPHI1_MASK (0x7E000000) +#define PLLDIG_PLLDV_RFDPHI1_MAXVALUE (0x3F) +#define PLLDIG_PLLDV_RFDPHI1_OFFSET (25) + +#define PLLDIG_PLLDV_PREDIV_SET(val) (PLLDIG_PLLDV_PREDIV_MASK & \ + (((val) & \ + PLLDIG_PLLDV_PREDIV_MAXVALUE) \ + << PLLDIG_PLLDV_PREDIV_OFFSET)) +#define PLLDIG_PLLDV_PREDIV_MASK (0x00007000) +#define PLLDIG_PLLDV_PREDIV_MAXVALUE (0x7) +#define PLLDIG_PLLDV_PREDIV_OFFSET (12) + +/* PLLDIG PLL Fractional Divide Register (PLLDIG_PLLFD) */ +#define PLLDIG_PLLFD(base) ((base) + 0x00000030) +#define PLLDIG_PLLFD_MFN_SET(val) (PLLDIG_PLLFD_MFN_MASK & (val)) +#define PLLDIG_PLLFD_MFN_MASK (0x00007FFF) + +/* PLL Calibration Register 1 (PLLDIG_PLLCAL1) */ +#define PLLDIG_PLLCAL1(base) ((base) + 0x00000038) +#define PLLDIG_PLLCAL1_NDAC1_SET(val) (PLLDIG_PLLCAL1_NDAC1_MASK & \ + ((val) \ + << PLLDIG_PLLCAL1_NDAC1_OFFSET)) +#define PLLDIG_PLLCAL1_NDAC1_OFFSET (24) +#define PLLDIG_PLLCAL1_NDAC1_MASK (0x7F000000) + +/* Naming convention for PLL: + * ARMPLL - PLL0 + * PERIPHPLL - PLL1 + * ENETPLL - PLL2 + * DDRPLL - PLL3 + * VIDEOPLL - PLL4 + */ +/* The min,max values for PLL VCO (Hz) */ +#define PERIPHPLL_MAX_VCO_RATE (1200000000) + +/* The min,max values for PLL PHI0 and PHI1 outputs (Hz) */ +#define PERIPHPLL_MAX_PHI0_MAX_RATE (400000000) +#define PERIPHPLL_MAX_PHI1_MAX_RATE (100000000) + +/* The maximum value for PLL VCO according to data sheet */ +#define MAX_VCO_RATE (1300000000) +#define MIN_VCO_RATE (650000000) + +enum s32v234_plldig_type { + S32_PLLDIG_ARM, + S32_PLLDIG_PERIPH, + S32_PLLDIG_ENET, + S32_PLLDIG_DDR, + S32_PLLDIG_VIDEO, +}; + +#endif diff --git a/drivers/clk/s32/s32v234/src.h b/drivers/clk/s32/s32v234/src.h new file mode 100644 index 000000000000..39fa973b7c3c --- /dev/null +++ b/drivers/clk/s32/s32v234/src.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + */ +#ifndef _SRC_H +#define _SRC_H + +/* Source Reset Control: General Purpose Register 1 */ +#define SRC_GPR1 (src_base + 0x100) +#define SRC_GPR1_ARMPLL_SRC_SEL_OFFSET (27) +#define SRC_GPR1_ENETPLL_SRC_SEL_OFFSET (28) +#define SRC_GPR1_DDRPLL_SRC_SEL_OFFSET (29) +#define SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET (30) +#define SRC_GPR1_VIDEOPLL_SRC_SEL_OFFSET (31) +#define SRC_GPR1_XPLL_SRC_SEL_SIZE (1) + +#endif From 491a5c07c57fdc082c22e88a99c2ef0a4fb608ff Mon Sep 17 00:00:00 2001 From: Stoica Cosmin-Stefan Date: Mon, 8 Jun 2015 18:55:18 +0300 Subject: [PATCH 4/9] clk: Enable UART clock for S32V234 Enable the clocks needed for LINFlexD UART support on Treerunner and make use of them in the LINFlexD driver. Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Adrian.Nitu Signed-off-by: Larisa Grigore Signed-off-by: Iustin Dumitrescu Signed-off-by: Stefan-Gabriel Mirea Signed-off-by: Leonard Crestez --- drivers/clk/s32/s32v234/clk.c | 19 +++++++++++++++++++ include/dt-bindings/clock/s32v234-clock.h | 6 +++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c index 2fd325d92a5d..7801f9fce0e6 100644 --- a/drivers/clk/s32/s32v234/clk.c +++ b/drivers/clk/s32/s32v234/clk.c @@ -19,6 +19,10 @@ DEFINE_SPINLOCK(s32v234_lock); /* sources for multiplexer clocks, this is used multiple times */ PNAME(osc_sels) = {"firc", "fxosc", }; +PNAME(lin_sels) = {"firc", "fxosc", "dummy", + "periphpll_phi0_div3", "dummy", "dummy", + "dummy", "dummy", "sys6",}; + static struct clk *clk[S32V234_CLK_END]; static struct clk_onecell_data clk_data; @@ -89,6 +93,21 @@ static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) clk[S32V234_CLK_PERIPHPLL_PHI0_DIV5] = s32_clk_fixed_factor( "periphpll_phi0_div5", "periphpll_phi0", 1, 5); + /* Lin Clock */ + clk[S32V234_CLK_LIN_SEL] = s32_clk_mux("lin_sel", + CGM_ACn_SC(mc_cgm0_base, 3), + MC_CGM_ACn_SEL_OFFSET, + MC_CGM_ACn_SEL_SIZE, + lin_sels, ARRAY_SIZE(lin_sels), &s32v234_lock); + + clk[S32V234_CLK_LIN] = s32_clk_divider("lin", "lin_sel", + CGM_ACn_DCm(mc_cgm0_base, 3, 0), + MC_CGM_ACn_DCm_PREDIV_OFFSET, + MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); + + clk[S32V234_CLK_LIN_IPG] = s32_clk_fixed_factor("lin_ipg", + "lin", 1, 2); + /* enable PERIPHPLL */ enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL, MC_ME_RUNn_MC(mc_me_base, 0)); diff --git a/include/dt-bindings/clock/s32v234-clock.h b/include/dt-bindings/clock/s32v234-clock.h index c0ce57f9471a..91e9ddaaa45e 100644 --- a/include/dt-bindings/clock/s32v234-clock.h +++ b/include/dt-bindings/clock/s32v234-clock.h @@ -17,6 +17,10 @@ #define S32V234_CLK_PERIPHPLL_PHI0_DIV3 6 #define S32V234_CLK_PERIPHPLL_PHI0_DIV5 7 #define S32V234_CLK_PERIPHPLL_PHI1 8 +/* LINFlexD Clock */ +#define S32V234_CLK_LIN 9 +#define S32V234_CLK_LIN_SEL 10 +#define S32V234_CLK_LIN_IPG 11 -#define S32V234_CLK_END 9 +#define S32V234_CLK_END 12 #endif /* __DT_BINDINGS_CLOCK_S32V234_H */ From 6cbe7edb1a3179bbd5fb22fa8f5bedca379bc8f9 Mon Sep 17 00:00:00 2001 From: Stoica Cosmin-Stefan Date: Mon, 8 Jun 2015 18:55:18 +0300 Subject: [PATCH 5/9] clk: Enable SDHC clock for S32V234 Enable the clocks needed for uSDHC support on Treerunner. Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Larisa Grigore Signed-off-by: Stefan-Gabriel Mirea --- drivers/clk/s32/s32v234/clk.c | 15 +++++++++++++++ include/dt-bindings/clock/s32v234-clock.h | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c index 7801f9fce0e6..2fc6776e256d 100644 --- a/drivers/clk/s32/s32v234/clk.c +++ b/drivers/clk/s32/s32v234/clk.c @@ -23,6 +23,9 @@ PNAME(lin_sels) = {"firc", "fxosc", "dummy", "periphpll_phi0_div3", "dummy", "dummy", "dummy", "dummy", "sys6",}; +PNAME(sdhc_sels) = {"firc", "fxosc", "dummy", + "dummy",}; + static struct clk *clk[S32V234_CLK_END]; static struct clk_onecell_data clk_data; @@ -112,6 +115,18 @@ static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL, MC_ME_RUNn_MC(mc_me_base, 0)); + /* SDHC Clock */ + clk[S32V234_CLK_SDHC_SEL] = s32_clk_mux("sdhc_sel", + CGM_ACn_SC(mc_cgm0_base, 15), + MC_CGM_ACn_SEL_OFFSET, + MC_CGM_ACn_SEL_SIZE, + sdhc_sels, ARRAY_SIZE(sdhc_sels), &s32v234_lock); + + clk[S32V234_CLK_SDHC] = s32_clk_divider("sdhc", "sdhc_sel", + CGM_ACn_DCm(mc_cgm0_base, 15, 0), + MC_CGM_ACn_DCm_PREDIV_OFFSET, + MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); + /* set the system clock */ enable_sysclock(MC_ME_MODE_MC_SYSCLK(0x2), MC_ME_RUNn_MC(mc_me_base, 0)); diff --git a/include/dt-bindings/clock/s32v234-clock.h b/include/dt-bindings/clock/s32v234-clock.h index 91e9ddaaa45e..028a29af556b 100644 --- a/include/dt-bindings/clock/s32v234-clock.h +++ b/include/dt-bindings/clock/s32v234-clock.h @@ -21,6 +21,9 @@ #define S32V234_CLK_LIN 9 #define S32V234_CLK_LIN_SEL 10 #define S32V234_CLK_LIN_IPG 11 +/* SDHC Clock */ +#define S32V234_CLK_SDHC 12 +#define S32V234_CLK_SDHC_SEL 13 -#define S32V234_CLK_END 12 +#define S32V234_CLK_END 14 #endif /* __DT_BINDINGS_CLOCK_S32V234_H */ From 318d69432b39af3d2d3e5be6b2e57d8a21da55a0 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 7 Nov 2019 18:25:52 +0200 Subject: [PATCH 6/9] clk: s32v234: Add dfs clk Port from ALB v4.19.31_bsp23.0_rc2 Signed-off-by: Leonard Crestez Reviewed-by: Fugang Duan --- drivers/clk/s32/s32v234/Makefile | 2 +- drivers/clk/s32/s32v234/clk-dfs.c | 236 ++++++++++++++++++++++++++++++ drivers/clk/s32/s32v234/clk.h | 4 + drivers/clk/s32/s32v234/dfs.h | 78 ++++++++++ 4 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/s32/s32v234/clk-dfs.c create mode 100644 drivers/clk/s32/s32v234/dfs.h diff --git a/drivers/clk/s32/s32v234/Makefile b/drivers/clk/s32/s32v234/Makefile index 54f77523dbcd..7ddf9f4b5d81 100644 --- a/drivers/clk/s32/s32v234/Makefile +++ b/drivers/clk/s32/s32v234/Makefile @@ -1 +1 @@ -obj-$(CONFIG_ARCH_S32_CLK) += clk.o clk-plldig.o +obj-$(CONFIG_ARCH_S32_CLK) += clk.o clk-plldig.o clk-dfs.o diff --git a/drivers/clk/s32/s32v234/clk-dfs.c b/drivers/clk/s32/s32v234/clk-dfs.c new file mode 100644 index 000000000000..2bd569e13a18 --- /dev/null +++ b/drivers/clk/s32/s32v234/clk-dfs.c @@ -0,0 +1,236 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include "clk.h" + +/** + * struct clk_dfs - S32 DFS clock + * @clk_hw: clock source + * @reg: DFS register address + * @idx: the index of DFS encoded in the register + * + * DFS clock found on S32 series. Each register for DFS has 4 clk_dfs + * data encoded, and member idx is used to specify the one. + * Only ARMPLL(3 DFS), ENETPLL(4 DFS) and DDRPLL(3 DFS) has DFS outputs. + */ +struct clk_dfs { + struct clk_hw hw; + void __iomem *reg; + enum s32v234_plldig_type plltype; + u8 idx; + u32 mfn; +}; + +#define to_clk_dfs(_hw) container_of(_hw, struct clk_dfs, hw) + +static int get_pllx_dfs_nr(enum s32v234_plldig_type plltype) +{ + switch (plltype) { + case S32_PLLDIG_ARM: + return ARMPLL_DFS_NR; + case S32_PLLDIG_ENET: + return ENETPLL_DFS_NR; + case S32_PLLDIG_DDR: + return DDRPLL_DFS_NR; + case S32_PLLDIG_PERIPH: + case S32_PLLDIG_VIDEO: + pr_warn("Current selected PLL has no DFS\n"); + break; + } + + return -EINVAL; +} +static unsigned long get_pllx_dfsy_max_rate(enum s32v234_plldig_type plltype, + int dfsno) +{ + switch (plltype) { + case S32_PLLDIG_ARM: + switch (dfsno) { + case 0: + return ARMPLL_DFS0_MAX_RATE; + case 1: + return ARMPLL_DFS1_MAX_RATE; + case 2: + return ARMPLL_DFS2_MAX_RATE; + } + break; + case S32_PLLDIG_ENET: + switch (dfsno) { + case 0: + return ENETPLL_DFS0_MAX_RATE; + case 1: + return ENETPLL_DFS1_MAX_RATE; + case 2: + return ENETPLL_DFS2_MAX_RATE; + case 3: + return ENETPLL_DFS3_MAX_RATE; + } + break; + case S32_PLLDIG_DDR: + switch (dfsno) { + case 0: + return DDRPLL_DFS0_MAX_RATE; + case 1: + return DDRPLL_DFS1_MAX_RATE; + case 2: + return DDRPLL_DFS2_MAX_RATE; + } + break; + case S32_PLLDIG_PERIPH: + case S32_PLLDIG_VIDEO: + pr_warn("Current selected PLL has no DFS."); + break; + default: + pr_warn("Unsupported PLL. Use %d or %d\n", + S32_PLLDIG_ARM, S32_PLLDIG_VIDEO); + break; + } + + return -EINVAL; +} +static int clk_dfs_enable(struct clk_hw *hw) +{ + /* + * TODO: When SOC is available, this function + * should be tested and implemented for DFS + * if it is possible + */ + return 0; +} + +static void clk_dfs_disable(struct clk_hw *hw) +{ + /* + * TODO: When SOC is available, this function + * should be tested and implemented for DFS + * if it is possible + */ +} + +static unsigned long clk_dfs_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_dfs *dfs = to_clk_dfs(hw); + u32 mfn, mfi, rate; + u32 dvport = readl_relaxed(DFS_DVPORTn(dfs->reg, dfs->idx)); + + mfn = (dvport & DFS_DVPORTn_MFN_MASK) >> DFS_DVPORTn_MFN_OFFSET; + mfi = (dvport & DFS_DVPORTn_MFI_MASK) >> DFS_DVPORTn_MFI_OFFSET; + mfi <<= 8; + rate = parent_rate / (mfi + mfn); + rate <<= 8; + + return rate; +} + +static long clk_dfs_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_dfs *dfs = to_clk_dfs(hw); + unsigned long max_allowed_rate; + + max_allowed_rate = get_pllx_dfsy_max_rate(dfs->plltype, dfs->idx); + + if (rate > max_allowed_rate) + rate = max_allowed_rate; + + return rate; +} + +static int clk_dfs_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_dfs *dfs = to_clk_dfs(hw); + u32 mfi; + u32 portreset = readl_relaxed(DFS_PORTRESET(dfs->reg)); + + writel_relaxed(DFS_CTRL_DLL_RESET, DFS_CTRL(dfs->reg)); + writel_relaxed(portreset | ~DFS_PORTRESET_PORTRESET_SET(dfs->idx), + DFS_PORTRESET(dfs->reg)); + + mfi = parent_rate/rate; + writel_relaxed(DFS_DVPORTn_MFI_SET(mfi) | + DFS_DVPORTn_MFN_SET(dfs->mfn), + DFS_DVPORTn(dfs->reg, dfs->idx)); + + writel_relaxed(~DFS_CTRL_DLL_RESET, DFS_CTRL(dfs->reg)); + + while (readl_relaxed(DFS_PORTSR(dfs->reg)) & (1 << (dfs->idx))) + ; + + return 0; +} + +static int clk_dfs_is_enabled(struct clk_hw *hw) +{ + struct clk_dfs *dfs = to_clk_dfs(hw); + + /* Check if current DFS output port is locked */ + if (readl_relaxed(DFS_PORTSR(dfs->reg)) & (1 << (dfs->idx))) + return 0; + + return 1; +} + +static const struct clk_ops clk_dfs_ops = { + .enable = clk_dfs_enable, + .disable = clk_dfs_disable, + .recalc_rate = clk_dfs_recalc_rate, + .round_rate = clk_dfs_round_rate, + .set_rate = clk_dfs_set_rate, + .is_enabled = clk_dfs_is_enabled, +}; + +struct clk *s32v234_clk_dfs(enum s32v234_plldig_type type, const char *name, + const char *parent_name, void __iomem *reg, + u8 idx, u32 mfn) +{ + struct clk_dfs *dfs; + struct clk *clk; + struct clk_init_data init; + + /* PERIPH and VIDEO PLL do not have DFS */ + if (type == S32_PLLDIG_PERIPH || type == S32_PLLDIG_VIDEO) + return ERR_PTR(-EINVAL); + + /* check if DFS index is valid for current pll */ + if (idx >= get_pllx_dfs_nr(type)) + return ERR_PTR(-EINVAL); + + dfs = kzalloc(sizeof(*dfs), GFP_KERNEL); + if (!dfs) + return ERR_PTR(-ENOMEM); + + dfs->reg = reg; + dfs->idx = idx; + dfs->mfn = mfn; + dfs->plltype = type; + + init.name = name; + init.ops = &clk_dfs_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + dfs->hw.init = &init; + + clk = clk_register(NULL, &dfs->hw); + if (IS_ERR(clk)) + kfree(dfs); + + return clk; +} diff --git a/drivers/clk/s32/s32v234/clk.h b/drivers/clk/s32/s32v234/clk.h index ea69d13a90b5..82a222483394 100644 --- a/drivers/clk/s32/s32v234/clk.h +++ b/drivers/clk/s32/s32v234/clk.h @@ -13,6 +13,7 @@ #include "mc_me.h" #include "pll.h" #include "src.h" +#include "dfs.h" #include "../clk.h" struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name, @@ -24,4 +25,7 @@ struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type, const char *name, const char *parent, void __iomem *base, u32 phi); +struct clk *s32v234_clk_dfs(enum s32v234_plldig_type type, const char *name, + const char *parent_name, + void __iomem *reg, u8 idx, u32 mfn); #endif diff --git a/drivers/clk/s32/s32v234/dfs.h b/drivers/clk/s32/s32v234/dfs.h new file mode 100644 index 000000000000..be3104f7ae51 --- /dev/null +++ b/drivers/clk/s32/s32v234/dfs.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2018 NXP + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef _DFS_S32V234_H +#define _DFS_S32V234_H + +/* DFS Control Register (DFS_CTRL) */ +#define DFS_CTRL(base) ((base) + 0x00000018) +#define DFS_CTRL_DLL_LOLIE (1 << 0) +#define DFS_CTRL_DLL_RESET (1 << 1) + +/* DFS Port Status (DFS_PORTSR) */ +#define DFS_PORTSR(base) ((base) + 0x0000000C) +#define DFS_PORTSR_MASK (0x0000000F) +#define DFS_PORTSR_OFFSET (28) + +/* DFS Port Reset Register (DFS_PORTRESET) */ +#define DFS_PORTRESET(base) ((base) + 0x00000014) +#define DFS_PORTRESET_PORTRESET_SET(val) \ + (DFS_PORTRESET_PORTRESET_MASK | \ + (((val) & DFS_PORTRESET_PORTRESET_MAXVAL) \ + << DFS_PORTRESET_PORTRESET_OFFSET)) +#define DFS_PORTRESET_PORTRESET_MAXVAL (0xF) +#define DFS_PORTRESET_PORTRESET_MASK (0x0000000F) +#define DFS_PORTRESET_PORTRESET_OFFSET (28) + +/* DFS Divide Register Portn (DFS_DVPORTn) */ +#define DFS_DVPORTn(base, n) ((base) + (0x0000001C + \ + ((n) * sizeof(u32)))) +#define DFS_DVPORTn_MFI_SET(val) (DFS_DVPORTn_MFI_MASK & \ + (((val) & DFS_DVPORTn_MFI_MAXVAL) \ + << DFS_DVPORTn_MFI_OFFSET)) +#define DFS_DVPORTn_MFN_SET(val) (DFS_DVPORTn_MFN_MASK & \ + (((val) & DFS_DVPORTn_MFN_MAXVAL) \ + << DFS_DVPORTn_MFN_OFFSET)) +#define DFS_DVPORTn_MFI_MASK (0x0000FF00) +#define DFS_DVPORTn_MFN_MASK (0x000000FF) +#define DFS_DVPORTn_MFI_MAXVAL (0xFF) +#define DFS_DVPORTn_MFN_MAXVAL (0xFF) +#define DFS_DVPORTn_MFI_OFFSET (8) +#define DFS_DVPORTn_MFN_OFFSET (0) +#define DFS_MAXNUMBER (4) + +/* + * Naming convention for PLL: + * ARMPLL - PLL0 + * PERIPHPLL - PLL1 + * ENETPLL - PLL2 + * DDRPLL - PLL3 + * VIDEOPLL - PLL4 + */ + +/* The max values for PLL DFS is in Hz */ +/* ARMPLL */ +#define ARMPLL_DFS0_MAX_RATE (266000000) +#define ARMPLL_DFS1_MAX_RATE (600000000) +#define ARMPLL_DFS2_MAX_RATE (600000000) +/* ENETPLL */ +#define ENETPLL_DFS0_MAX_RATE (350000000) +#define ENETPLL_DFS1_MAX_RATE (350000000) +#define ENETPLL_DFS2_MAX_RATE (416000000) +#define ENETPLL_DFS3_MAX_RATE (104000000) +/* DDRPLL */ +#define DDRPLL_DFS0_MAX_RATE (500000000) +#define DDRPLL_DFS1_MAX_RATE (500000000) +#define DDRPLL_DFS2_MAX_RATE (350000000) + +#define ARMPLL_DFS_NR (3) +#define ENETPLL_DFS_NR (4) +#define DDRPLL_DFS_NR (3) + +#endif From fba4afe4760044c21e15d6290da45f4180b66128 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Thu, 7 Nov 2019 18:26:58 +0200 Subject: [PATCH 7/9] clk: s32v234: Initial enet clk support Add ethernet clocks and dependencies (sys_pll, arm_pll) Based on ALB v4.19.31_bsp23.0_rc2 Signed-off-by: Leonard Crestez Reviewed-by: Fugang Duan --- drivers/clk/s32/s32v234/clk.c | 143 +++++++++++++++++++++- drivers/clk/s32/s32v234/mc_cgm.h | 21 ++++ include/dt-bindings/clock/s32v234-clock.h | 34 ++++- 3 files changed, 196 insertions(+), 2 deletions(-) diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c index 2fc6776e256d..f3f72aebe60a 100644 --- a/drivers/clk/s32/s32v234/clk.c +++ b/drivers/clk/s32/s32v234/clk.c @@ -11,6 +11,9 @@ #include "clk.h" static void __iomem *mc_cgm0_base; +static void __iomem *mc_cgm1_base; +static void __iomem *mc_cgm2_base; +static void __iomem *mc_cgm3_base; static void __iomem *mc_me_base; static void __iomem *src_base; @@ -19,12 +22,20 @@ DEFINE_SPINLOCK(s32v234_lock); /* sources for multiplexer clocks, this is used multiple times */ PNAME(osc_sels) = {"firc", "fxosc", }; +PNAME(sys_sels) = {"firc", "fxosc", "armpll_dfs0", }; + PNAME(lin_sels) = {"firc", "fxosc", "dummy", "periphpll_phi0_div3", "dummy", "dummy", "dummy", "dummy", "sys6",}; PNAME(sdhc_sels) = {"firc", "fxosc", "dummy", - "dummy",}; + "enetpll_dfs3",}; + +PNAME(enet_sels) = {"firc", "fxosc", "dummy", + "dummy", "enetpll_phi0",}; + +PNAME(enet_time_sels) = {"firc", "fxosc", "dummy", + "dummy", "enetpll_phi0",}; static struct clk *clk[S32V234_CLK_END]; static struct clk_onecell_data clk_data; @@ -47,6 +58,21 @@ static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) if (WARN_ON(!src_base)) return; + np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm1"); + mc_cgm1_base = of_iomap(np, 0); + if (WARN_ON(!mc_cgm1_base)) + return; + + np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm2"); + mc_cgm2_base = of_iomap(np, 0); + if (WARN_ON(!mc_cgm2_base)) + return; + + np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm3"); + mc_cgm3_base = of_iomap(np, 0); + if (WARN_ON(!mc_cgm3_base)) + return; + np = mc_cgm0_node; mc_cgm0_base = of_iomap(np, 0); if (WARN_ON(!mc_cgm0_base)) @@ -67,11 +93,68 @@ static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) /* transition the core to RUN0 mode */ entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0); + clk[S32V234_CLK_ARMPLL_SRC_SEL] = s32_clk_mux("armpll_sel", + SRC_GPR1, SRC_GPR1_ARMPLL_SRC_SEL_OFFSET, + SRC_GPR1_XPLL_SRC_SEL_SIZE, + osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); + clk[S32V234_CLK_PERIPHPLL_SRC_SEL] = s32_clk_mux("periphpll_sel", SRC_GPR1, SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET, SRC_GPR1_XPLL_SRC_SEL_SIZE, osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); + clk[S32V234_CLK_ENETPLL_SRC_SEL] = s32_clk_mux("enetpll_sel", + SRC_GPR1, SRC_GPR1_ENETPLL_SRC_SEL_OFFSET, + SRC_GPR1_XPLL_SRC_SEL_SIZE, + osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); + + /* ARM_PLL */ + clk[S32V234_CLK_ARMPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_ARM, + "armpll_vco", "armpll_sel", ARMPLL_PLLDIG(mc_cgm0_base), + ARMPLL_PLLDIG_PLLDV_MFD, ARMPLL_PLLDIG_PLLDV_MFN, + ARMPLL_PLLDIG_PLLDV_RFDPHI0, ARMPLL_PLLDIG_PLLDV_RFDPHI1); + + clk[S32V234_CLK_ARMPLL_PHI0] = s32v234_clk_plldig_phi(S32_PLLDIG_ARM, + "armpll_phi0", "armpll_vco", + ARMPLL_PLLDIG(mc_cgm0_base), 0); + + clk[S32V234_CLK_ARMPLL_PHI1] = s32v234_clk_plldig_phi(S32_PLLDIG_ARM, + "armpll_phi1", "armpll_vco", + ARMPLL_PLLDIG(mc_cgm0_base), 1); + + clk[S32V234_CLK_ARMPLL_DFS0] = s32v234_clk_dfs(S32_PLLDIG_ARM, + "armpll_dfs0", "armpll_phi1", + ARMPLL_PLLDIG_DFS(mc_cgm0_base), 0, + ARMPLL_PLLDIG_DFS0_MFN); + + clk[S32V234_CLK_ARMPLL_DFS1] = s32v234_clk_dfs(S32_PLLDIG_ARM, + "armpll_dfs1", "armpll_phi1", + ARMPLL_PLLDIG_DFS(mc_cgm0_base), 1, + ARMPLL_PLLDIG_DFS1_MFN); + + clk[S32V234_CLK_ARMPLL_DFS2] = s32v234_clk_dfs(S32_PLLDIG_ARM, + "armpll_dfs2", "armpll_phi1", + ARMPLL_PLLDIG_DFS(mc_cgm0_base), 2, + ARMPLL_PLLDIG_DFS2_MFN); + + clk[S32V234_CLK_SYS_SEL] = s32_clk_mux("sys_sel", + MC_ME_RUNn_MC(mc_me_base, 0), + MC_ME_MODE_MC_SYSCLK_OFFSET, + MC_ME_MODE_MC_SYSCLK_SIZE, + sys_sels, ARRAY_SIZE(sys_sels), &s32v234_lock); + + clk[S32V234_CLK_SYS3] = s32_clk_divider("sys3", "sys_sel", + CGM_SC_DCn(mc_cgm0_base, 0), MC_CGM_SC_DCn_PREDIV_OFFSET, + MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock); + + clk[S32V234_CLK_SYS6] = s32_clk_divider("sys6", "sys_sel", + CGM_SC_DCn(mc_cgm0_base, 1), MC_CGM_SC_DCn_PREDIV_OFFSET, + MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock); + + clk[S32V234_CLK_SYS6_DIV2] = s32_clk_divider("sys6_div2", "sys_sel", + CGM_SC_DCn(mc_cgm0_base, 2), MC_CGM_SC_DCn_PREDIV_OFFSET, + MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock); + /* PERIPH_PLL */ clk[S32V234_CLK_PERIPHPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_PERIPH, "periphpll_vco", "periphpll_sel", @@ -115,6 +198,64 @@ static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL, MC_ME_RUNn_MC(mc_me_base, 0)); + /* ENET_PLL */ + clk[S32V234_CLK_ENETPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_ENET, + "enetpll_vco", "enetpll_sel", ENETPLL_PLLDIG(mc_cgm0_base), + ENETPLL_PLLDIG_PLLDV_MFD, ENETPLL_PLLDIG_PLLDV_MFN, + ENETPLL_PLLDIG_PLLDV_RFDPHI0, ENETPLL_PLLDIG_PLLDV_RFDPHI1); + + clk[S32V234_CLK_ENETPLL_PHI0] = s32v234_clk_plldig_phi(S32_PLLDIG_ENET, + "enetpll_phi0", "enetpll_vco", + ENETPLL_PLLDIG(mc_cgm0_base), 0); + + clk[S32V234_CLK_ENETPLL_PHI1] = s32v234_clk_plldig_phi(S32_PLLDIG_ENET, + "enetpll_phi1", "enetpll_vco", + ENETPLL_PLLDIG(mc_cgm0_base), 1); + + clk[S32V234_CLK_ENETPLL_DFS0] = s32v234_clk_dfs(S32_PLLDIG_ENET, + "enetpll_dfs0", "enetpll_phi1", + ENETPLL_PLLDIG_DFS(mc_cgm0_base), 0, + ENETPLL_PLLDIG_DFS0_MFN); + + clk[S32V234_CLK_ENETPLL_DFS1] = s32v234_clk_dfs(S32_PLLDIG_ENET, + "enetpll_dfs1", "enetpll_phi1", + ENETPLL_PLLDIG_DFS(mc_cgm0_base), 1, + ENETPLL_PLLDIG_DFS1_MFN); + + clk[S32V234_CLK_ENETPLL_DFS2] = s32v234_clk_dfs(S32_PLLDIG_ENET, + "enetpll_dfs2", "enetpll_phi1", + ENETPLL_PLLDIG_DFS(mc_cgm0_base), 2, + ENETPLL_PLLDIG_DFS2_MFN); + + clk[S32V234_CLK_ENETPLL_DFS3] = s32v234_clk_dfs(S32_PLLDIG_ENET, + "enetpll_dfs3", "enetpll_phi1", + ENETPLL_PLLDIG_DFS(mc_cgm0_base), 3, + ENETPLL_PLLDIG_DFS3_MFN); + + /* ENET Clock */ + clk[S32V234_CLK_ENET_SEL] = s32_clk_mux("enet_sel", + CGM_ACn_SC(mc_cgm2_base, 2), + MC_CGM_ACn_SEL_OFFSET, + MC_CGM_ACn_SEL_SIZE, + enet_sels, ARRAY_SIZE(enet_sels), &s32v234_lock); + + clk[S32V234_CLK_ENET_TIME_SEL] = s32_clk_mux("enet_time_sel", + CGM_ACn_SC(mc_cgm0_base, 7), + MC_CGM_ACn_SEL_OFFSET, + MC_CGM_ACn_SEL_SIZE, + enet_time_sels, ARRAY_SIZE(enet_time_sels), &s32v234_lock); + + clk[S32V234_CLK_ENET] = s32_clk_divider("enet", "enet_sel", + CGM_ACn_DCm(mc_cgm2_base, 2, 0), + MC_CGM_ACn_DCm_PREDIV_OFFSET, + MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); + + clk[S32V234_CLK_ENET_TIME] = s32_clk_divider("enet_time", + "enet_time_sel", + CGM_ACn_DCm(mc_cgm0_base, 7, 1), + MC_CGM_ACn_DCm_PREDIV_OFFSET, + MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); + /* SDHC Clock */ clk[S32V234_CLK_SDHC_SEL] = s32_clk_mux("sdhc_sel", CGM_ACn_SC(mc_cgm0_base, 15), diff --git a/drivers/clk/s32/s32v234/mc_cgm.h b/drivers/clk/s32/s32v234/mc_cgm.h index 61a5fe61b2d1..aeac68771890 100644 --- a/drivers/clk/s32/s32v234/mc_cgm.h +++ b/drivers/clk/s32/s32v234/mc_cgm.h @@ -6,12 +6,33 @@ #ifndef _MC_CGM_H #define _MC_CGM_H +#define ARMPLL_PLLDIG(mc_cgm) (mc_cgm) +#define ARMPLL_PLLDIG_DFS(mc_cgm) ((mc_cgm) + 0x40) +#define ARMPLL_PLLDIG_PLLDV_MFD (50) +#define ARMPLL_PLLDIG_PLLDV_MFN (0) +#define ARMPLL_PLLDIG_PLLDV_RFDPHI0 (1) +#define ARMPLL_PLLDIG_PLLDV_RFDPHI1 (1) +#define ARMPLL_PLLDIG_DFS0_MFN (195) +#define ARMPLL_PLLDIG_DFS1_MFN (171) +#define ARMPLL_PLLDIG_DFS2_MFN (171) + #define PERIPHPLL_PLLDIG(mc_cgm) ((mc_cgm) + 0x80) #define PERIPHPLL_PLLDIG_PLLDV_MFD (30) #define PERIPHPLL_PLLDIG_PLLDV_MFN (0) #define PERIPHPLL_PLLDIG_PLLDV_RFDPHI0 (0x1) #define PERIPHPLL_PLLDIG_PLLDV_RFDPHI1 (0x1) +#define ENETPLL_PLLDIG(mc_cgm) ((mc_cgm) + 0x100) +#define ENETPLL_PLLDIG_DFS(mc_cgm) ((mc_cgm) + 0x100 + 0x40) +#define ENETPLL_PLLDIG_PLLDV_MFD (50) +#define ENETPLL_PLLDIG_PLLDV_MFN (0) +#define ENETPLL_PLLDIG_PLLDV_RFDPHI0 (0x1) +#define ENETPLL_PLLDIG_PLLDV_RFDPHI1 (0x1) +#define ENETPLL_PLLDIG_DFS0_MFN (220) +#define ENETPLL_PLLDIG_DFS1_MFN (220) +#define ENETPLL_PLLDIG_DFS2_MFN (33) +#define ENETPLL_PLLDIG_DFS3_MFN (1) + /* MC_CGM_SC_SS */ #define CGM_SC_SS(mc_cgm) (((mc_cgm) + 0x7E4)) diff --git a/include/dt-bindings/clock/s32v234-clock.h b/include/dt-bindings/clock/s32v234-clock.h index 028a29af556b..34cb043f108b 100644 --- a/include/dt-bindings/clock/s32v234-clock.h +++ b/include/dt-bindings/clock/s32v234-clock.h @@ -24,6 +24,38 @@ /* SDHC Clock */ #define S32V234_CLK_SDHC 12 #define S32V234_CLK_SDHC_SEL 13 +/* ENET PLL */ +#define S32V234_CLK_ENETPLL_SRC_SEL 14 +#define S32V234_CLK_ENETPLL_VCO 15 +#define S32V234_CLK_ENETPLL_PHI0 16 +#define S32V234_CLK_ENETPLL_PHI1 17 +#define S32V234_CLK_ENETPLL_DFS0 18 +#define S32V234_CLK_ENETPLL_DFS1 19 +#define S32V234_CLK_ENETPLL_DFS2 20 +#define S32V234_CLK_ENETPLL_DFS3 21 +/* System Clock */ +#define S32V234_CLK_SYS_SEL 22 +#define S32V234_CLK_SYS3 23 +#define S32V234_CLK_SYS6 24 +#define S32V234_CLK_SYS6_DIV2 25 +/* ENET Clock */ +#define S32V234_CLK_ENET_TIME_DIV 26 +#define S32V234_CLK_ENET_TIME_SEL 27 +#define S32V234_CLK_ENET_DIV 28 +#define S32V234_CLK_ENET_SEL 29 + +#define S32V234_CLK_ENET 30 +#define S32V234_CLK_ENET_TIME 31 + +/* ARM PLL */ +#define S32V234_CLK_ARMPLL_SRC_SEL 32 +#define S32V234_CLK_ARMPLL_VCO 33 +#define S32V234_CLK_ARMPLL_PHI0 34 +#define S32V234_CLK_ARMPLL_PHI1 35 +#define S32V234_CLK_ARMPLL_DFS0 35 +#define S32V234_CLK_ARMPLL_DFS1 36 +#define S32V234_CLK_ARMPLL_DFS2 37 + +#define S32V234_CLK_END 38 -#define S32V234_CLK_END 14 #endif /* __DT_BINDINGS_CLOCK_S32V234_H */ From 086bbd068f85627000c88e0ce638f2187cbf8de4 Mon Sep 17 00:00:00 2001 From: Stoica Cosmin-Stefan Date: Mon, 8 Jun 2015 18:55:18 +0300 Subject: [PATCH 8/9] clk: s32v234: Add definitions for CAN clocks Define macros which will indicate the clock signals obtained after auxiliary clock 6 source selection and division (CAN_CLK) respectively. Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Stefan-Gabriel Mirea --- include/dt-bindings/clock/s32v234-clock.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/s32v234-clock.h b/include/dt-bindings/clock/s32v234-clock.h index 34cb043f108b..1ddfae5c1422 100644 --- a/include/dt-bindings/clock/s32v234-clock.h +++ b/include/dt-bindings/clock/s32v234-clock.h @@ -56,6 +56,10 @@ #define S32V234_CLK_ARMPLL_DFS1 36 #define S32V234_CLK_ARMPLL_DFS2 37 -#define S32V234_CLK_END 38 +/* CAN Clock */ +#define S32V234_CLK_CAN 38 +#define S32V234_CLK_CAN_SEL 39 + +#define S32V234_CLK_END 40 #endif /* __DT_BINDINGS_CLOCK_S32V234_H */ From 9ce8988c808bf29c696905437c64248605d91498 Mon Sep 17 00:00:00 2001 From: Chircu-Mare Bogdan-Petru Date: Tue, 3 Nov 2015 17:25:46 +0200 Subject: [PATCH 9/9] clk: s32v234: Enable FlexCAN clock Enable the clocks needed for FlexCAN support on Treerunner. Signed-off-by: Chircu-Mare Bogdan-Petru Signed-off-by: Stoica Cosmin-Stefan Signed-off-by: Larisa Grigore Signed-off-by: Stefan-Gabriel Mirea Reviewed-by: Li Yang Reviewed-by: Leonard Crestez --- drivers/clk/s32/s32v234/clk.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c index f3f72aebe60a..cb5abd54fa2c 100644 --- a/drivers/clk/s32/s32v234/clk.c +++ b/drivers/clk/s32/s32v234/clk.c @@ -24,6 +24,9 @@ PNAME(osc_sels) = {"firc", "fxosc", }; PNAME(sys_sels) = {"firc", "fxosc", "armpll_dfs0", }; +PNAME(can_sels) = {"firc", "fxosc", "dummy", + "periphpll_phi0_div5", }; + PNAME(lin_sels) = {"firc", "fxosc", "dummy", "periphpll_phi0_div3", "dummy", "dummy", "dummy", "dummy", "sys6",}; @@ -179,6 +182,18 @@ static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) clk[S32V234_CLK_PERIPHPLL_PHI0_DIV5] = s32_clk_fixed_factor( "periphpll_phi0_div5", "periphpll_phi0", 1, 5); + clk[S32V234_CLK_CAN_SEL] = s32_clk_mux("can_sel", + CGM_ACn_SC(mc_cgm0_base, 6), + MC_CGM_ACn_SEL_OFFSET, + MC_CGM_ACn_SEL_SIZE, + can_sels, ARRAY_SIZE(can_sels), &s32v234_lock); + + /* CAN Clock */ + clk[S32V234_CLK_CAN] = s32_clk_divider("can", "can_sel", + CGM_ACn_DCm(mc_cgm0_base, 6, 0), + MC_CGM_ACn_DCm_PREDIV_OFFSET, + MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); + /* Lin Clock */ clk[S32V234_CLK_LIN_SEL] = s32_clk_mux("lin_sel", CGM_ACn_SC(mc_cgm0_base, 3),