aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/meson
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 11:08:30 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 11:08:30 -0700
commit519f64bf15dccb4f64af34b74ed186c32363ab59 (patch)
tree7d0a666701e72e03b7c9d624163ef5bda89b4356 /drivers/clk/meson
parentMerge tag 'vfio-v4.20-rc1.v2' of git://github.com/awilliam/linux-vfio (diff)
parentMerge branches 'clk-fixed-rate-remove' and 'clk-qcom-cleanup' into clk-next (diff)
downloadlinux-dev-519f64bf15dccb4f64af34b74ed186c32363ab59.tar.xz
linux-dev-519f64bf15dccb4f64af34b74ed186c32363ab59.zip
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Stephen Boyd: "This time it looks like a quieter release cycle in the clk tree. I guess that's because of summer time holidays/vacations. The biggest change in the diffstat is in the Qualcomm clk driver, where they got support for CPUs and handful of SoCs. After that, the at91 driver got a major rewrite for newer DT bindings that should make things easier going forward and the TI code moved to a clockdomain based design. The long tail is mostly small driver updates for newer clks and some simpler SoC clock drivers such as the Hisilicon and imx support. In the core framework, we only have two small changes this time. One is a new clk API to get all clks for a device with the bulk clk APIs. This allows drivers that don't care about doing anything besides turning on all the clks to just clk_get() them all and turn them on. The other change is the beginning of a way to support save and restore of clk settings in the clk framework. TI is the only user right now, but we will want to expand upon this design in the future to support more save and restore of clk registers. At least this gets us started and works well enough for one SoC, but there's more work in the future. Core: - clk_bulk_get_all() API and friends to get all the clks for a device - Basic clk state save/restore hooks New Drivers: - Renesas RZ/A2 (R7S9210) SoC, including early clocks - Rensas RZ/G1N (R8A7744) and RZ/G2E (R8A774C0) SoCs - Rensas RZ/G2M (r8a774a1) SoC - Qualcomm Krait CPU clk support - Qualcomm QCS404 GCC support - Qualcomm SDM660 GCC support - Qualcomm SDM845 camera clock controller - Ingenic jz4725b CGU - Hisilicon 3670 SoC support - TI SCI clks on K3 SoCs - iMX6 MMDC clks - Reset Controller (RMU) support for Actions Semi Owl S900 and S700 SoCs Updates: - Rework at91 PMC clock driver for new DT bindings - Nvidia Tegra clk driver MBIST workaround fix - S2RAM support for Marvell mvebu periph clks - Use updated printk format for OF node names - Fix TI code to only search DT subnodes - Various static analysis finds - Tag various drivers with SPDX license tags - Support dynamic frequency switching (DFS) on qcom SDM845 GCC - Only use s2mps11 dt-binding defines instead of redefining them in the driver - Add some more missing clks to qcom MSM8996 GCC - Quad SPI clks on qcom SDM845 - Add support for CMT timer clocks on R-Car V3H - Add support for SHDI and various timer clocks on R-Car V3M - Improve OSC and RCLK (watchdog) handling on R-Car Gen3 SoCs - Amlogic clk-pll driver improvements and updates - Amlogic axg audio controller system clocks - Register Amlogic meson8b clock controller early - Add support for SATA and Fine Display Processor (FDP) clocks on R-Car M3-N - Consolidation of system suspend related code in Exynos, S5P, S3C SoC clk drivers - Fixes for system suspend support on Exynos542x (Odroid boards) and Exynos5433 SoC - Remove obsoleted Exynos4212 ISP clock definitions - Migrated TI am3/4/5 and dra7 SoCs to clockdomain based design - TI RTC+DDR sleep mode support for clock save/restore - Allwinner A64 display engine support and fixes - Allwinner A83t display engine support and fixes" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (186 commits) clk: qcom: Remove unused arrays in SDM845 GCC clk: fixed-rate: fix of_node_get-put imbalance clk: s2mps11: Add used attribute to s2mps11_dt_match clk: qcom: gcc-sdm660: Add MODULE_LICENSE clk: qcom: Add safe switch hook for krait mux clocks dt-bindings: clock: Document qcom,krait-cc clk: qcom: Add Krait clock controller driver dt-bindings: arm: Document qcom,kpss-gcc clk: qcom: Add KPSS ACC/GCC driver clk: qcom: Add support for Krait clocks clk: qcom: Add IPQ806X's HFPLLs clk: qcom: Add MSM8960/APQ8064's HFPLLs dt-bindings: clock: Document qcom,hfpll clk: qcom: Add HFPLL driver clk: qcom: Add support for High-Frequency PLLs (HFPLLs) ARM: Add Krait L2 register accessor functions clk: imx6q: add mmdc0 ipg clock clk: imx6sl: add mmdc ipg clocks clk: imx6sll: add mmdc1 ipg clock clk: imx6sx: add mmdc1 ipg clock ...
Diffstat (limited to 'drivers/clk/meson')
-rw-r--r--drivers/clk/meson/axg-audio.c34
-rw-r--r--drivers/clk/meson/axg.c332
-rw-r--r--drivers/clk/meson/axg.h8
-rw-r--r--drivers/clk/meson/clk-pll.c156
-rw-r--r--drivers/clk/meson/clkc.h16
-rw-r--r--drivers/clk/meson/gxbb.c518
-rw-r--r--drivers/clk/meson/gxbb.h10
-rw-r--r--drivers/clk/meson/meson8b.c280
-rw-r--r--drivers/clk/meson/meson8b.h5
9 files changed, 732 insertions, 627 deletions
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index a0ed41e73bde..5f6c860aa122 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = {
"axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
};
-#define AXG_MST_MCLK_MUX(_name, _reg) \
- AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, CLK_MUX_ROUND_CLOSEST, \
+#define AXG_MST_MUX(_name, _reg, _flag) \
+ AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
mst_mux_parent_names, CLK_SET_RATE_PARENT)
+#define AXG_MST_MCLK_MUX(_name, _reg) \
+ AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
+
+#define AXG_MST_SYS_MUX(_name, _reg) \
+ AXG_MST_MUX(_name, _reg, 0)
+
static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
@@ -112,13 +118,19 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
-static AXG_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
-static AXG_MST_MCLK_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
+static AXG_MST_SYS_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+static AXG_MST_SYS_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
+
+#define AXG_MST_DIV(_name, _reg, _flag) \
+ AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
+ "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
+
+#define AXG_MST_MCLK_DIV(_name, _reg) \
+ AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
-#define AXG_MST_MCLK_DIV(_name, _reg) \
- AXG_AUD_DIV(_name##_div, _reg, 0, 16, CLK_DIVIDER_ROUND_CLOSEST, \
- "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
+#define AXG_MST_SYS_DIV(_name, _reg) \
+ AXG_MST_DIV(_name, _reg, 0)
static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
@@ -127,12 +139,12 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
-static AXG_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
-static AXG_MST_MCLK_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
+static AXG_MST_SYS_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
+static AXG_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
-#define AXG_MST_MCLK_GATE(_name, _reg) \
- AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
+#define AXG_MST_MCLK_GATE(_name, _reg) \
+ AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
CLK_SET_RATE_PARENT)
static AXG_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 00ce62ad6416..c981159b02c0 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -22,8 +22,13 @@
static DEFINE_SPINLOCK(meson_clk_lock);
-static struct clk_regmap axg_fixed_pll = {
+static struct clk_regmap axg_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_MPLL_CNTL,
.shift = 0,
@@ -34,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.frac = {
.reg_off = HHI_MPLL_CNTL2,
.shift = 0,
@@ -56,15 +56,39 @@ static struct clk_regmap axg_fixed_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "fixed_pll",
+ .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
-static struct clk_regmap axg_sys_pll = {
+static struct clk_regmap axg_fixed_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .num_parents = 1,
+ /*
+ * This clock won't ever change at runtime so
+ * CLK_SET_RATE_PARENT is not required
+ */
+ },
+};
+
+static struct clk_regmap axg_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
@@ -75,11 +99,6 @@ static struct clk_regmap axg_sys_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.l = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 31,
@@ -92,102 +111,59 @@ static struct clk_regmap axg_sys_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "sys_pll",
+ .name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
},
};
-static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
- PLL_RATE(240000000, 40, 1, 2),
- PLL_RATE(246000000, 41, 1, 2),
- PLL_RATE(252000000, 42, 1, 2),
- PLL_RATE(258000000, 43, 1, 2),
- PLL_RATE(264000000, 44, 1, 2),
- PLL_RATE(270000000, 45, 1, 2),
- PLL_RATE(276000000, 46, 1, 2),
- PLL_RATE(282000000, 47, 1, 2),
- PLL_RATE(288000000, 48, 1, 2),
- PLL_RATE(294000000, 49, 1, 2),
- PLL_RATE(300000000, 50, 1, 2),
- PLL_RATE(306000000, 51, 1, 2),
- PLL_RATE(312000000, 52, 1, 2),
- PLL_RATE(318000000, 53, 1, 2),
- PLL_RATE(324000000, 54, 1, 2),
- PLL_RATE(330000000, 55, 1, 2),
- PLL_RATE(336000000, 56, 1, 2),
- PLL_RATE(342000000, 57, 1, 2),
- PLL_RATE(348000000, 58, 1, 2),
- PLL_RATE(354000000, 59, 1, 2),
- PLL_RATE(360000000, 60, 1, 2),
- PLL_RATE(366000000, 61, 1, 2),
- PLL_RATE(372000000, 62, 1, 2),
- PLL_RATE(378000000, 63, 1, 2),
- PLL_RATE(384000000, 64, 1, 2),
- PLL_RATE(390000000, 65, 1, 3),
- PLL_RATE(396000000, 66, 1, 3),
- PLL_RATE(402000000, 67, 1, 3),
- PLL_RATE(408000000, 68, 1, 3),
- PLL_RATE(480000000, 40, 1, 1),
- PLL_RATE(492000000, 41, 1, 1),
- PLL_RATE(504000000, 42, 1, 1),
- PLL_RATE(516000000, 43, 1, 1),
- PLL_RATE(528000000, 44, 1, 1),
- PLL_RATE(540000000, 45, 1, 1),
- PLL_RATE(552000000, 46, 1, 1),
- PLL_RATE(564000000, 47, 1, 1),
- PLL_RATE(576000000, 48, 1, 1),
- PLL_RATE(588000000, 49, 1, 1),
- PLL_RATE(600000000, 50, 1, 1),
- PLL_RATE(612000000, 51, 1, 1),
- PLL_RATE(624000000, 52, 1, 1),
- PLL_RATE(636000000, 53, 1, 1),
- PLL_RATE(648000000, 54, 1, 1),
- PLL_RATE(660000000, 55, 1, 1),
- PLL_RATE(672000000, 56, 1, 1),
- PLL_RATE(684000000, 57, 1, 1),
- PLL_RATE(696000000, 58, 1, 1),
- PLL_RATE(708000000, 59, 1, 1),
- PLL_RATE(720000000, 60, 1, 1),
- PLL_RATE(732000000, 61, 1, 1),
- PLL_RATE(744000000, 62, 1, 1),
- PLL_RATE(756000000, 63, 1, 1),
- PLL_RATE(768000000, 64, 1, 1),
- PLL_RATE(780000000, 65, 1, 1),
- PLL_RATE(792000000, 66, 1, 1),
- PLL_RATE(804000000, 67, 1, 1),
- PLL_RATE(816000000, 68, 1, 1),
- PLL_RATE(960000000, 40, 1, 0),
- PLL_RATE(984000000, 41, 1, 0),
- PLL_RATE(1008000000, 42, 1, 0),
- PLL_RATE(1032000000, 43, 1, 0),
- PLL_RATE(1056000000, 44, 1, 0),
- PLL_RATE(1080000000, 45, 1, 0),
- PLL_RATE(1104000000, 46, 1, 0),
- PLL_RATE(1128000000, 47, 1, 0),
- PLL_RATE(1152000000, 48, 1, 0),
- PLL_RATE(1176000000, 49, 1, 0),
- PLL_RATE(1200000000, 50, 1, 0),
- PLL_RATE(1224000000, 51, 1, 0),
- PLL_RATE(1248000000, 52, 1, 0),
- PLL_RATE(1272000000, 53, 1, 0),
- PLL_RATE(1296000000, 54, 1, 0),
- PLL_RATE(1320000000, 55, 1, 0),
- PLL_RATE(1344000000, 56, 1, 0),
- PLL_RATE(1368000000, 57, 1, 0),
- PLL_RATE(1392000000, 58, 1, 0),
- PLL_RATE(1416000000, 59, 1, 0),
- PLL_RATE(1440000000, 60, 1, 0),
- PLL_RATE(1464000000, 61, 1, 0),
- PLL_RATE(1488000000, 62, 1, 0),
- PLL_RATE(1512000000, 63, 1, 0),
- PLL_RATE(1536000000, 64, 1, 0),
- PLL_RATE(1560000000, 65, 1, 0),
- PLL_RATE(1584000000, 66, 1, 0),
- PLL_RATE(1608000000, 67, 1, 0),
- PLL_RATE(1632000000, 68, 1, 0),
+static struct clk_regmap axg_sys_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SYS_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "sys_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct pll_params_table axg_gp0_pll_params_table[] = {
+ PLL_PARAMS(40, 1),
+ PLL_PARAMS(41, 1),
+ PLL_PARAMS(42, 1),
+ PLL_PARAMS(43, 1),
+ PLL_PARAMS(44, 1),
+ PLL_PARAMS(45, 1),
+ PLL_PARAMS(46, 1),
+ PLL_PARAMS(47, 1),
+ PLL_PARAMS(48, 1),
+ PLL_PARAMS(49, 1),
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
+ PLL_PARAMS(63, 1),
+ PLL_PARAMS(64, 1),
+ PLL_PARAMS(65, 1),
+ PLL_PARAMS(66, 1),
+ PLL_PARAMS(67, 1),
+ PLL_PARAMS(68, 1),
{ /* sentinel */ },
};
@@ -197,11 +173,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
- { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
};
-static struct clk_regmap axg_gp0_pll = {
+static struct clk_regmap axg_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 0,
@@ -212,11 +192,6 @@ static struct clk_regmap axg_gp0_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.frac = {
.reg_off = HHI_GP0_PLL_CNTL1,
.shift = 0,
@@ -232,29 +207,49 @@ static struct clk_regmap axg_gp0_pll = {
.shift = 29,
.width = 1,
},
- .table = axg_gp0_pll_rate_table,
+ .table = axg_gp0_pll_params_table,
.init_regs = axg_gp0_init_regs,
.init_count = ARRAY_SIZE(axg_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
- .name = "gp0_pll",
+ .name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
+static struct clk_regmap axg_gp0_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_GP0_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_names = (const char *[]){ "gp0_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
static const struct reg_sequence axg_hifi_init_regs[] = {
{ .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 },
{ .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be },
{ .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 },
{ .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 },
- { .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 },
};
-static struct clk_regmap axg_hifi_pll = {
+static struct clk_regmap axg_hifi_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_HIFI_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_HIFI_PLL_CNTL,
.shift = 0,
@@ -265,11 +260,6 @@ static struct clk_regmap axg_hifi_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_HIFI_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.frac = {
.reg_off = HHI_HIFI_PLL_CNTL5,
.shift = 0,
@@ -285,19 +275,35 @@ static struct clk_regmap axg_hifi_pll = {
.shift = 29,
.width = 1,
},
- .table = axg_gp0_pll_rate_table,
+ .table = axg_gp0_pll_params_table,
.init_regs = axg_hifi_init_regs,
.init_count = ARRAY_SIZE(axg_hifi_init_regs),
.flags = CLK_MESON_PLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
- .name = "hifi_pll",
+ .name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
+static struct clk_regmap axg_hifi_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HIFI_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hifi_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_names = (const char *[]){ "hifi_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
static struct clk_fixed_factor axg_fclk_div2_div = {
.mult = 1,
.div = 2,
@@ -625,29 +631,31 @@ static struct clk_regmap axg_mpll3 = {
},
};
-static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
+static const struct pll_params_table axg_pcie_pll_params_table[] = {
{
- .rate = 100000000,
- .m = 200,
- .n = 3,
- .od = 1,
- .od2 = 3,
+ .m = 200,
+ .n = 3,
},
{ /* sentinel */ },
};
static const struct reg_sequence axg_pcie_init_regs[] = {
- { .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
{ .reg = HHI_PCIE_PLL_CNTL1, .def = 0x0084a2aa },
{ .reg = HHI_PCIE_PLL_CNTL2, .def = 0xb75020be },
{ .reg = HHI_PCIE_PLL_CNTL3, .def = 0x0a47488e },
{ .reg = HHI_PCIE_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_PCIE_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_PCIE_PLL_CNTL6, .def = 0x002323c6 },
+ { .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
};
-static struct clk_regmap axg_pcie_pll = {
+static struct clk_regmap axg_pcie_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_PCIE_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_PCIE_PLL_CNTL,
.shift = 0,
@@ -658,16 +666,6 @@ static struct clk_regmap axg_pcie_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_PCIE_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
- .od2 = {
- .reg_off = HHI_PCIE_PLL_CNTL6,
- .shift = 6,
- .width = 2,
- },
.frac = {
.reg_off = HHI_PCIE_PLL_CNTL1,
.shift = 0,
@@ -683,29 +681,63 @@ static struct clk_regmap axg_pcie_pll = {
.shift = 29,
.width = 1,
},
- .table = axg_pcie_pll_rate_table,
+ .table = axg_pcie_pll_params_table,
.init_regs = axg_pcie_init_regs,
.init_count = ARRAY_SIZE(axg_pcie_init_regs),
},
.hw.init = &(struct clk_init_data){
- .name = "pcie_pll",
+ .name = "pcie_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
+static struct clk_regmap axg_pcie_pll_od = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_PCIE_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_pll_od",
+ .ops = &clk_regmap_divider_ops,
+ .parent_names = (const char *[]){ "pcie_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap axg_pcie_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_PCIE_PLL_CNTL6,
+ .shift = 6,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_names = (const char *[]){ "pcie_pll_od" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
static struct clk_regmap axg_pcie_mux = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_PCIE_PLL_CNTL6,
.mask = 0x1,
.shift = 2,
+ /* skip the parent mpll3, reserved for debug */
+ .table = (u32[]){ 1 },
},
.hw.init = &(struct clk_init_data){
.name = "pcie_mux",
.ops = &clk_regmap_mux_ops,
- .parent_names = (const char *[]){ "mpll3", "pcie_pll" },
- .num_parents = 2,
+ .parent_names = (const char *[]){ "pcie_pll" },
+ .num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1107,6 +1139,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw,
[CLKID_GEN_CLK] = &axg_gen_clk.hw,
+ [CLKID_SYS_PLL_DCO] = &axg_sys_pll_dco.hw,
+ [CLKID_FIXED_PLL_DCO] = &axg_fixed_pll_dco.hw,
+ [CLKID_GP0_PLL_DCO] = &axg_gp0_pll_dco.hw,
+ [CLKID_HIFI_PLL_DCO] = &axg_hifi_pll_dco.hw,
+ [CLKID_PCIE_PLL_DCO] = &axg_pcie_pll_dco.hw,
+ [CLKID_PCIE_PLL_OD] = &axg_pcie_pll_od.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@@ -1185,6 +1223,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_fclk_div4,
&axg_fclk_div5,
&axg_fclk_div7,
+ &axg_pcie_pll_dco,
+ &axg_pcie_pll_od,
&axg_pcie_pll,
&axg_pcie_mux,
&axg_pcie_ref,
@@ -1194,6 +1234,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_gen_clk_sel,
&axg_gen_clk_div,
&axg_gen_clk,
+ &axg_fixed_pll_dco,
+ &axg_sys_pll_dco,
+ &axg_gp0_pll_dco,
+ &axg_hifi_pll_dco,
+ &axg_pcie_pll_dco,
+ &axg_pcie_pll_od,
};
static const struct of_device_id clkc_match_table[] = {
diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
index 1d04144a1b2c..0431dabac629 100644
--- a/drivers/clk/meson/axg.h
+++ b/drivers/clk/meson/axg.h
@@ -133,8 +133,14 @@
#define CLKID_PCIE_REF 78
#define CLKID_GEN_CLK_SEL 82
#define CLKID_GEN_CLK_DIV 83
+#define CLKID_SYS_PLL_DCO 85
+#define CLKID_FIXED_PLL_DCO 86
+#define CLKID_GP0_PLL_DCO 87
+#define CLKID_HIFI_PLL_DCO 88
+#define CLKID_PCIE_PLL_DCO 89
+#define CLKID_PCIE_PLL_OD 90
-#define NR_CLKS 85
+#define NR_CLKS 91
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/axg-clkc.h>
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 3e04617ac47f..f5b5b3fabe3c 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -11,15 +11,19 @@
* In the most basic form, a Meson PLL is composed as follows:
*
* PLL
- * +------------------------------+
- * | |
- * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
- * | ^ ^ |
- * +------------------------------+
- * | |
- * FREF VCO
+ * +--------------------------------+
+ * | |
+ * | +--+ |
+ * in >>-----[ /N ]--->| | +-----+ |
+ * | | |------| DCO |---->> out
+ * | +--------->| | +--v--+ |
+ * | | +--+ | |
+ * | | | |
+ * | +--[ *(M + (F/Fmax) ]<--+ |
+ * | |
+ * +--------------------------------+
*
- * out = in * (m + frac / frac_max) / (n << sum(ods))
+ * out = in * (m + frac / frac_max) / n
*/
#include <linux/clk-provider.h>
@@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk)
}
static unsigned long __pll_params_to_rate(unsigned long parent_rate,
- const struct pll_rate_table *pllt,
+ const struct pll_params_table *pllt,
u16 frac,
struct meson_clk_pll_data *pll)
{
u64 rate = (u64)parent_rate * pllt->m;
- unsigned int od = pllt->od + pllt->od2 + pllt->od3;
if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
u64 frac_rate = (u64)parent_rate * frac;
@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
(1 << pll->frac.width));
}
- return DIV_ROUND_UP_ULL(rate, pllt->n << od);
+ return DIV_ROUND_UP_ULL(rate, pllt->n);
}
static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- struct pll_rate_table pllt;
+ struct pll_params_table pllt;
u16 frac;
pllt.n = meson_parm_read(clk->map, &pll->n);
pllt.m = meson_parm_read(clk->map, &pll->m);
- pllt.od = meson_parm_read(clk->map, &pll->od);
-
- pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
- meson_parm_read(clk->map, &pll->od2) :
- 0;
-
- pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
- meson_parm_read(clk->map, &pll->od3) :
- 0;
frac = MESON_PARM_APPLICABLE(&pll->frac) ?
meson_parm_read(clk->map, &pll->frac) :
@@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
static u16 __pll_params_with_frac(unsigned long rate,
unsigned long parent_rate,
- const struct pll_rate_table *pllt,
+ const struct pll_params_table *pllt,
struct meson_clk_pll_data *pll)
{
u16 frac_max = (1 << pll->frac.width);
u64 val = (u64)rate * pllt->n;
- val <<= pllt->od + pllt->od2 + pllt->od3;
-
if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
else
@@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
return min((u16)val, (u16)(frac_max - 1));
}
-static const struct pll_rate_table *
+static bool meson_clk_pll_is_better(unsigned long rate,
+ unsigned long best,
+ unsigned long now,
+ struct meson_clk_pll_data *pll)
+{
+ if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
+ MESON_PARM_APPLICABLE(&pll->frac)) {
+ /* Round down */
+ if (now < rate && best < now)
+ return true;
+ } else {
+ /* Round Closest */
+ if (abs(now - rate) < abs(best - rate))
+ return true;
+ }
+
+ return false;
+}
+
+static const struct pll_params_table *
meson_clk_get_pll_settings(unsigned long rate,
+ unsigned long parent_rate,
struct meson_clk_pll_data *pll)
{
- const struct pll_rate_table *table = pll->table;
- unsigned int i = 0;
+ const struct pll_params_table *table = pll->table;
+ unsigned long best = 0, now = 0;
+ unsigned int i, best_i = 0;
if (!table)
return NULL;
- /* Find the first table element exceeding rate */
- while (table[i].rate && table[i].rate <= rate)
- i++;
+ for (i = 0; table[i].n; i++) {
+ now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
- if (i != 0) {
- if (MESON_PARM_APPLICABLE(&pll->frac) ||
- !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
- (abs(rate - table[i - 1].rate) <
- abs(rate - table[i].rate)))
- i--;
+ /* If we get an exact match, don't bother any further */
+ if (now == rate) {
+ return &table[i];
+ } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
+ best = now;
+ best_i = i;
+ }
}
- return (struct pll_rate_table *)&table[i];
+ return (struct pll_params_table *)&table[best_i];
}
static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- const struct pll_rate_table *pllt =
- meson_clk_get_pll_settings(rate, pll);
+ const struct pll_params_table *pllt =
+ meson_clk_get_pll_settings(rate, *parent_rate, pll);
+ unsigned long round;
u16 frac;
if (!pllt)
return meson_clk_pll_recalc_rate(hw, *parent_rate);
- if (!MESON_PARM_APPLICABLE(&pll->frac)
- || rate == pllt->rate)
- return pllt->rate;
+ round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
+
+ if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
+ return round;
/*
* The rate provided by the setting is not an exact match, let's
@@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
}
}
+static int meson_clk_pll_enable(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+ /* Make sure the pll is in reset */
+ meson_parm_write(clk->map, &pll->rst, 1);
+
+ /* Enable the pll */
+ meson_parm_write(clk->map, &pll->en, 1);
+
+ /* Take the pll out reset */
+ meson_parm_write(clk->map, &pll->rst, 0);
+
+ if (meson_clk_pll_wait_lock(hw))
+ return -EIO;
+
+ return 0;
+}
+
+static void meson_clk_pll_disable(struct clk_hw *hw)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+ /* Put the pll is in reset */
+ meson_parm_write(clk->map, &pll->rst, 1);
+
+ /* Disable the pll */
+ meson_parm_write(clk->map, &pll->en, 0);
+}
+
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- const struct pll_rate_table *pllt;
+ const struct pll_params_table *pllt;
+ unsigned int enabled;
unsigned long old_rate;
u16 frac = 0;
@@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
old_rate = rate;
- pllt = meson_clk_get_pll_settings(rate, pll);
+ pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
if (!pllt)
return -EINVAL;
- /* Put the pll in reset to write the params */
- meson_parm_write(clk->map, &pll->rst, 1);
+ enabled = meson_parm_read(clk->map, &pll->en);
+ if (enabled)
+ meson_clk_pll_disable(hw);
meson_parm_write(clk->map, &pll->n, pllt->n);
meson_parm_write(clk->map, &pll->m, pllt->m);
- meson_parm_write(clk->map, &pll->od, pllt->od);
- if (MESON_PARM_APPLICABLE(&pll->od2))
- meson_parm_write(clk->map, &pll->od2, pllt->od2);
-
- if (MESON_PARM_APPLICABLE(&pll->od3))
- meson_parm_write(clk->map, &pll->od3, pllt->od3);
if (MESON_PARM_APPLICABLE(&pll->frac)) {
frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
meson_parm_write(clk->map, &pll->frac, frac);
}
- /* make sure the reset is cleared at this point */
- meson_parm_write(clk->map, &pll->rst, 0);
+ /* If the pll is stopped, bail out now */
+ if (!enabled)
+ return 0;
- if (meson_clk_pll_wait_lock(hw)) {
+ if (meson_clk_pll_enable(hw)) {
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
__func__, old_rate);
/*
@@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = {
.recalc_rate = meson_clk_pll_recalc_rate,
.round_rate = meson_clk_pll_round_rate,
.set_rate = meson_clk_pll_set_rate,
+ .enable = meson_clk_pll_enable,
+ .disable = meson_clk_pll_disable
};
const struct clk_ops meson_clk_pll_ro_ops = {
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 24cec16b6038..6b96d55c047d 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
}
-struct pll_rate_table {
- unsigned long rate;
+struct pll_params_table {
u16 m;
u16 n;
- u16 od;
- u16 od2;
- u16 od3;
};
-#define PLL_RATE(_r, _m, _n, _od) \
+#define PLL_PARAMS(_m, _n) \
{ \
- .rate = (_r), \
.m = (_m), \
.n = (_n), \
- .od = (_od), \
}
#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
struct meson_clk_pll_data {
+ struct parm en;
struct parm m;
struct parm n;
struct parm frac;
- struct parm od;
- struct parm od2;
- struct parm od3;
struct parm l;
struct parm rst;
const struct reg_sequence *init_regs;
unsigned int init_count;
- const struct pll_rate_table *table;
+ const struct pll_params_table *table;
u8 flags;
};
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 86d3ae58e84c..9309cfaaa464 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -18,165 +18,77 @@
static DEFINE_SPINLOCK(meson_clk_lock);
-static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
- PLL_RATE(96000000, 32, 1, 3),
- PLL_RATE(99000000, 33, 1, 3),
- PLL_RATE(102000000, 34, 1, 3),
- PLL_RATE(105000000, 35, 1, 3),
- PLL_RATE(108000000, 36, 1, 3),
- PLL_RATE(111000000, 37, 1, 3),
- PLL_RATE(114000000, 38, 1, 3),
- PLL_RATE(117000000, 39, 1, 3),
- PLL_RATE(120000000, 40, 1, 3),
- PLL_RATE(123000000, 41, 1, 3),
- PLL_RATE(126000000, 42, 1, 3),
- PLL_RATE(129000000, 43, 1, 3),
- PLL_RATE(132000000, 44, 1, 3),
- PLL_RATE(135000000, 45, 1, 3),
- PLL_RATE(138000000, 46, 1, 3),
- PLL_RATE(141000000, 47, 1, 3),
- PLL_RATE(144000000, 48, 1, 3),
- PLL_RATE(147000000, 49, 1, 3),
- PLL_RATE(150000000, 50, 1, 3),
- PLL_RATE(153000000, 51, 1, 3),
- PLL_RATE(156000000, 52, 1, 3),
- PLL_RATE(159000000, 53, 1, 3),
- PLL_RATE(162000000, 54, 1, 3),
- PLL_RATE(165000000, 55, 1, 3),
- PLL_RATE(168000000, 56, 1, 3),
- PLL_RATE(171000000, 57, 1, 3),
- PLL_RATE(174000000, 58, 1, 3),
- PLL_RATE(177000000, 59, 1, 3),
- PLL_RATE(180000000, 60, 1, 3),
- PLL_RATE(183000000, 61, 1, 3),
- PLL_RATE(186000000, 62, 1, 3),
- PLL_RATE(192000000, 32, 1, 2),
- PLL_RATE(198000000, 33, 1, 2),
- PLL_RATE(204000000, 34, 1, 2),
- PLL_RATE(210000000, 35, 1, 2),
- PLL_RATE(216000000, 36, 1, 2),
- PLL_RATE(222000000, 37, 1, 2),
- PLL_RATE(228000000, 38, 1, 2),
- PLL_RATE(234000000, 39, 1, 2),
- PLL_RATE(240000000, 40, 1, 2),
- PLL_RATE(246000000, 41, 1, 2),
- PLL_RATE(252000000, 42, 1, 2),
- PLL_RATE(258000000, 43, 1, 2),
- PLL_RATE(264000000, 44, 1, 2),
- PLL_RATE(270000000, 45, 1, 2),
- PLL_RATE(276000000, 46, 1, 2),
- PLL_RATE(282000000, 47, 1, 2),
- PLL_RATE(288000000, 48, 1, 2),
- PLL_RATE(294000000, 49, 1, 2),
- PLL_RATE(300000000, 50, 1, 2),
- PLL_RATE(306000000, 51, 1, 2),
- PLL_RATE(312000000, 52, 1, 2),
- PLL_RATE(318000000, 53, 1, 2),
- PLL_RATE(324000000, 54, 1, 2),
- PLL_RATE(330000000, 55, 1, 2),
- PLL_RATE(336000000, 56, 1, 2),
- PLL_RATE(342000000, 57, 1, 2),
- PLL_RATE(348000000, 58, 1, 2),
- PLL_RATE(354000000, 59, 1, 2),
- PLL_RATE(360000000, 60, 1, 2),
- PLL_RATE(366000000, 61, 1, 2),
- PLL_RATE(372000000, 62, 1, 2),
- PLL_RATE(384000000, 32, 1, 1),
- PLL_RATE(396000000, 33, 1, 1),
- PLL_RATE(408000000, 34, 1, 1),
- PLL_RATE(420000000, 35, 1, 1),
- PLL_RATE(432000000, 36, 1, 1),
- PLL_RATE(444000000, 37, 1, 1),
- PLL_RATE(456000000, 38, 1, 1),
- PLL_RATE(468000000, 39, 1, 1),
- PLL_RATE(480000000, 40, 1, 1),
- PLL_RATE(492000000, 41, 1, 1),
- PLL_RATE(504000000, 42, 1, 1),
- PLL_RATE(516000000, 43, 1, 1),
- PLL_RATE(528000000, 44, 1, 1),
- PLL_RATE(540000000, 45, 1, 1),
- PLL_RATE(552000000, 46, 1, 1),
- PLL_RATE(564000000, 47, 1, 1),
- PLL_RATE(576000000, 48, 1, 1),
- PLL_RATE(588000000, 49, 1, 1),
- PLL_RATE(600000000, 50, 1, 1),
- PLL_RATE(612000000, 51, 1, 1),
- PLL_RATE(624000000, 52, 1, 1),
- PLL_RATE(636000000, 53, 1, 1),
- PLL_RATE(648000000, 54, 1, 1),
- PLL_RATE(660000000, 55, 1, 1),
- PLL_RATE(672000000, 56, 1, 1),
- PLL_RATE(684000000, 57, 1, 1),
- PLL_RATE(696000000, 58, 1, 1),
- PLL_RATE(708000000, 59, 1, 1),
- PLL_RATE(720000000, 60, 1, 1),
- PLL_RATE(732000000, 61, 1, 1),
- PLL_RATE(744000000, 62, 1, 1),
- PLL_RATE(768000000, 32, 1, 0),
- PLL_RATE(792000000, 33, 1, 0),
- PLL_RATE(816000000, 34, 1, 0),
- PLL_RATE(840000000, 35, 1, 0),
- PLL_RATE(864000000, 36, 1, 0),
- PLL_RATE(888000000, 37, 1, 0),
- PLL_RATE(912000000, 38, 1, 0),
- PLL_RATE(936000000, 39, 1, 0),
- PLL_RATE(960000000, 40, 1, 0),
- PLL_RATE(984000000, 41, 1, 0),
- PLL_RATE(1008000000, 42, 1, 0),
- PLL_RATE(1032000000, 43, 1, 0),
- PLL_RATE(1056000000, 44, 1, 0),
- PLL_RATE(1080000000, 45, 1, 0),
- PLL_RATE(1104000000, 46, 1, 0),
- PLL_RATE(1128000000, 47, 1, 0),
- PLL_RATE(1152000000, 48, 1, 0),
- PLL_RATE(1176000000, 49, 1, 0),
- PLL_RATE(1200000000, 50, 1, 0),
- PLL_RATE(1224000000, 51, 1, 0),
- PLL_RATE(1248000000, 52, 1, 0),
- PLL_RATE(1272000000, 53, 1, 0),
- PLL_RATE(1296000000, 54, 1, 0),
- PLL_RATE(1320000000, 55, 1, 0),
- PLL_RATE(1344000000, 56, 1, 0),
- PLL_RATE(1368000000, 57, 1, 0),
- PLL_RATE(1392000000, 58, 1, 0),
- PLL_RATE(1416000000, 59, 1, 0),
- PLL_RATE(1440000000, 60, 1, 0),
- PLL_RATE(1464000000, 61, 1, 0),
- PLL_RATE(1488000000, 62, 1, 0),
+static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
+ PLL_PARAMS(32, 1),
+ PLL_PARAMS(33, 1),
+ PLL_PARAMS(34, 1),
+ PLL_PARAMS(35, 1),
+ PLL_PARAMS(36, 1),
+ PLL_PARAMS(37, 1),
+ PLL_PARAMS(38, 1),
+ PLL_PARAMS(39, 1),
+ PLL_PARAMS(40, 1),
+ PLL_PARAMS(41, 1),
+ PLL_PARAMS(42, 1),
+ PLL_PARAMS(43, 1),
+ PLL_PARAMS(44, 1),
+ PLL_PARAMS(45, 1),
+ PLL_PARAMS(46, 1),
+ PLL_PARAMS(47, 1),
+ PLL_PARAMS(48, 1),
+ PLL_PARAMS(49, 1),
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
{ /* sentinel */ },
};
-static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
- PLL_RATE(504000000, 42, 1, 1),
- PLL_RATE(516000000, 43, 1, 1),
- PLL_RATE(528000000, 44, 1, 1),
- PLL_RATE(540000000, 45, 1, 1),
- PLL_RATE(552000000, 46, 1, 1),
- PLL_RATE(564000000, 47, 1, 1),
- PLL_RATE(576000000, 48, 1, 1),
- PLL_RATE(588000000, 49, 1, 1),
- PLL_RATE(600000000, 50, 1, 1),
- PLL_RATE(612000000, 51, 1, 1),
- PLL_RATE(624000000, 52, 1, 1),
- PLL_RATE(636000000, 53, 1, 1),
- PLL_RATE(648000000, 54, 1, 1),
- PLL_RATE(660000000, 55, 1, 1),
- PLL_RATE(672000000, 56, 1, 1),
- PLL_RATE(684000000, 57, 1, 1),
- PLL_RATE(696000000, 58, 1, 1),
- PLL_RATE(708000000, 59, 1, 1),
- PLL_RATE(720000000, 60, 1, 1),
- PLL_RATE(732000000, 61, 1, 1),
- PLL_RATE(744000000, 62, 1, 1),
- PLL_RATE(756000000, 63, 1, 1),
- PLL_RATE(768000000, 64, 1, 1),
- PLL_RATE(780000000, 65, 1, 1),
- PLL_RATE(792000000, 66, 1, 1),
+static const struct pll_params_table gxl_gp0_pll_params_table[] = {
+ PLL_PARAMS(42, 1),
+ PLL_PARAMS(43, 1),
+ PLL_PARAMS(44, 1),
+ PLL_PARAMS(45, 1),
+ PLL_PARAMS(46, 1),
+ PLL_PARAMS(47, 1),
+ PLL_PARAMS(48, 1),
+ PLL_PARAMS(49, 1),
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
+ PLL_PARAMS(63, 1),
+ PLL_PARAMS(64, 1),
+ PLL_PARAMS(65, 1),
+ PLL_PARAMS(66, 1),
{ /* sentinel */ },
};
-static struct clk_regmap gxbb_fixed_pll = {
+static struct clk_regmap gxbb_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_MPLL_CNTL,
.shift = 0,
@@ -187,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.frac = {
.reg_off = HHI_MPLL_CNTL2,
.shift = 0,
@@ -209,11 +116,29 @@ static struct clk_regmap gxbb_fixed_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "fixed_pll",
+ .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap gxbb_fixed_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .num_parents = 1,
+ /*
+ * This clock won't ever change at runtime so
+ * CLK_SET_RATE_PARENT is not required
+ */
},
};
@@ -228,8 +153,13 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
},
};
-static struct clk_regmap gxbb_hdmi_pll = {
+static struct clk_regmap gxbb_hdmi_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_HDMI_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 0,
@@ -245,21 +175,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
.shift = 0,
.width = 12,
},
- .od = {
- .reg_off = HHI_HDMI_PLL_CNTL2,
- .shift = 16,
- .width = 2,
- },
- .od2 = {
- .reg_off = HHI_HDMI_PLL_CNTL2,
- .shift = 22,
- .width = 2,
- },
- .od3 = {
- .reg_off = HHI_HDMI_PLL_CNTL2,
- .shift = 18,
- .width = 2,
- },
.l = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 31,
@@ -272,74 +187,121 @@ static struct clk_regmap gxbb_hdmi_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "hdmi_pll",
+ .name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
.num_parents = 1,
+ /*
+ * Display directly handle hdmi pll registers ATM, we need
+ * NOCACHE to keep our view of the clock as accurate as possible
+ */
.flags = CLK_GET_RATE_NOCACHE,
},
};
+static struct clk_regmap gxbb_hdmi_pll_od = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HDMI_PLL_CNTL2,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_od",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap gxbb_hdmi_pll_od2 = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HDMI_PLL_CNTL2,
+ .shift = 22,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_od2",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_od" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap gxbb_hdmi_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HDMI_PLL_CNTL2,
+ .shift = 18,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_od2" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap gxl_hdmi_pll_od = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HDMI_PLL_CNTL + 8,
+ .shift = 21,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_od",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap gxl_hdmi_pll_od2 = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HDMI_PLL_CNTL + 8,
+ .shift = 23,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hdmi_pll_od2",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_od" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+ },
+};
+
static struct clk_regmap gxl_hdmi_pll = {
- .data = &(struct meson_clk_pll_data){
- .m = {
- .reg_off = HHI_HDMI_PLL_CNTL,
- .shift = 0,
- .width = 9,
- },
- .n = {
- .reg_off = HHI_HDMI_PLL_CNTL,
- .shift = 9,
- .width = 5,
- },
- .frac = {
- /*
- * On gxl, there is a register shift due to
- * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
- * so we compute the register offset based on the PLL
- * base to get it right
- */
- .reg_off = HHI_HDMI_PLL_CNTL + 4,
- .shift = 0,
- .width = 12,
- },
- .od = {
- .reg_off = HHI_HDMI_PLL_CNTL + 8,
- .shift = 21,
- .width = 2,
- },
- .od2 = {
- .reg_off = HHI_HDMI_PLL_CNTL + 8,
- .shift = 23,
- .width = 2,
- },
- .od3 = {
- .reg_off = HHI_HDMI_PLL_CNTL + 8,
- .shift = 19,
- .width = 2,
- },
- .l = {
- .reg_off = HHI_HDMI_PLL_CNTL,
- .shift = 31,
- .width = 1,
- },
- .rst = {
- .reg_off = HHI_HDMI_PLL_CNTL,
- .shift = 29,
- .width = 1,
- },
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_HDMI_PLL_CNTL + 8,
+ .shift = 19,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
- .ops = &meson_clk_pll_ro_ops,
- .parent_names = (const char *[]){ "xtal" },
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "hdmi_pll_od2" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
-static struct clk_regmap gxbb_sys_pll = {
+static struct clk_regmap gxbb_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
@@ -350,11 +312,6 @@ static struct clk_regmap gxbb_sys_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 10,
- .width = 2,
- },
.l = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 31,
@@ -367,11 +324,26 @@ static struct clk_regmap gxbb_sys_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "sys_pll",
+ .name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap gxbb_sys_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SYS_PLL_CNTL,
+ .shift = 10,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "sys_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -379,11 +351,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
- { .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 },
};
-static struct clk_regmap gxbb_gp0_pll = {
+static struct clk_regmap gxbb_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 0,
@@ -394,11 +370,6 @@ static struct clk_regmap gxbb_gp0_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.l = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 31,
@@ -409,16 +380,15 @@ static struct clk_regmap gxbb_gp0_pll = {
.shift = 29,
.width = 1,
},
- .table = gxbb_gp0_pll_rate_table,
+ .table = gxbb_gp0_pll_params_table,
.init_regs = gxbb_gp0_init_regs,
.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
- .name = "gp0_pll",
+ .name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
},
};
@@ -428,11 +398,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
- { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
};
-static struct clk_regmap gxl_gp0_pll = {
+static struct clk_regmap gxl_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 0,
@@ -443,11 +417,6 @@ static struct clk_regmap gxl_gp0_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_GP0_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.frac = {
.reg_off = HHI_GP0_PLL_CNTL1,
.shift = 0,
@@ -463,16 +432,31 @@ static struct clk_regmap gxl_gp0_pll = {
.shift = 29,
.width = 1,
},
- .table = gxl_gp0_pll_rate_table,
+ .table = gxl_gp0_pll_params_table,
.init_regs = gxl_gp0_init_regs,
.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
- .name = "gp0_pll",
+ .name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap gxbb_gp0_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_GP0_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_names = (const char *[]){ "gp0_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -1933,6 +1917,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
+ [CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
+ [CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
+ [CLKID_HDMI_PLL_OD] = &gxbb_hdmi_pll_od.hw,
+ [CLKID_HDMI_PLL_OD2] = &gxbb_hdmi_pll_od2.hw,
+ [CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
+ [CLKID_GP0_PLL_DCO] = &gxbb_gp0_pll_dco.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@@ -1948,7 +1938,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw,
[CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw,
[CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw,
- [CLKID_GP0_PLL] = &gxl_gp0_pll.hw,
+ [CLKID_GP0_PLL] = &gxbb_gp0_pll.hw,
[CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw,
[CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw,
[CLKID_CLK81] = &gxbb_clk81.hw,
@@ -2098,19 +2088,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
+ [CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
+ [CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
+ [CLKID_HDMI_PLL_OD] = &gxl_hdmi_pll_od.hw,
+ [CLKID_HDMI_PLL_OD2] = &gxl_hdmi_pll_od2.hw,
+ [CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
+ [CLKID_GP0_PLL_DCO] = &gxl_gp0_pll_dco.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
};
static struct clk_regmap *const gxbb_clk_regmaps[] = {
- &gxbb_gp0_pll,
+ &gxbb_gp0_pll_dco,
&gxbb_hdmi_pll,
+ &gxbb_hdmi_pll_od,
+ &gxbb_hdmi_pll_od2,
};
static struct clk_regmap *const gxl_clk_regmaps[] = {
- &gxl_gp0_pll,
+ &gxl_gp0_pll_dco,
&gxl_hdmi_pll,
+ &gxl_hdmi_pll_od,
+ &gxl_hdmi_pll_od2,
};
static struct clk_regmap *const gx_clk_regmaps[] = {
@@ -2265,6 +2265,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
&gxbb_gen_clk_sel,
&gxbb_gen_clk_div,
&gxbb_gen_clk,
+ &gxbb_fixed_pll_dco,
+ &gxbb_hdmi_pll_dco,
+ &gxbb_sys_pll_dco,
+ &gxbb_gp0_pll,
};
struct clkc_data {
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 20dfb1daf5b8..72bc077d9663 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -159,8 +159,14 @@
#define CLKID_VDEC_HEVC_DIV 155
#define CLKID_GEN_CLK_SEL 157
#define CLKID_GEN_CLK_DIV 158
-
-#define NR_CLKS 160
+#define CLKID_FIXED_PLL_DCO 160
+#define CLKID_HDMI_PLL_DCO 161
+#define CLKID_HDMI_PLL_OD 162
+#define CLKID_HDMI_PLL_OD2 163
+#define CLKID_SYS_PLL_DCO 164
+#define CLKID_GP0_PLL_DCO 165
+
+#define NR_CLKS 166
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/gxbb-clkc.h>
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 7447d96a265f..346b9e165b7a 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -11,7 +11,6 @@
#include <linux/clk-provider.h>
#include <linux/init.h>
#include <linux/of_address.h>
-#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/regmap.h>
@@ -22,66 +21,27 @@
static DEFINE_SPINLOCK(meson_clk_lock);
-static void __iomem *clk_base;
-
struct meson8b_clk_reset {
struct reset_controller_dev reset;
- void __iomem *base;
+ struct regmap *regmap;
};
-static const struct pll_rate_table sys_pll_rate_table[] = {
- PLL_RATE(312000000, 52, 1, 2),
- PLL_RATE(336000000, 56, 1, 2),
- PLL_RATE(360000000, 60, 1, 2),
- PLL_RATE(384000000, 64, 1, 2),
- PLL_RATE(408000000, 68, 1, 2),
- PLL_RATE(432000000, 72, 1, 2),
- PLL_RATE(456000000, 76, 1, 2),
- PLL_RATE(480000000, 80, 1, 2),
- PLL_RATE(504000000, 84, 1, 2),
- PLL_RATE(528000000, 88, 1, 2),
- PLL_RATE(552000000, 92, 1, 2),
- PLL_RATE(576000000, 96, 1, 2),
- PLL_RATE(600000000, 50, 1, 1),
- PLL_RATE(624000000, 52, 1, 1),
- PLL_RATE(648000000, 54, 1, 1),
- PLL_RATE(672000000, 56, 1, 1),
- PLL_RATE(696000000, 58, 1, 1),
- PLL_RATE(720000000, 60, 1, 1),
- PLL_RATE(744000000, 62, 1, 1),
- PLL_RATE(768000000, 64, 1, 1),
- PLL_RATE(792000000, 66, 1, 1),
- PLL_RATE(816000000, 68, 1, 1),
- PLL_RATE(840000000, 70, 1, 1),
- PLL_RATE(864000000, 72, 1, 1),
- PLL_RATE(888000000, 74, 1, 1),
- PLL_RATE(912000000, 76, 1, 1),
- PLL_RATE(936000000, 78, 1, 1),
- PLL_RATE(960000000, 80, 1, 1),
- PLL_RATE(984000000, 82, 1, 1),
- PLL_RATE(1008000000, 84, 1, 1),
- PLL_RATE(1032000000, 86, 1, 1),
- PLL_RATE(1056000000, 88, 1, 1),
- PLL_RATE(1080000000, 90, 1, 1),
- PLL_RATE(1104000000, 92, 1, 1),
- PLL_RATE(1128000000, 94, 1, 1),
- PLL_RATE(1152000000, 96, 1, 1),
- PLL_RATE(1176000000, 98, 1, 1),
- PLL_RATE(1200000000, 50, 1, 0),
- PLL_RATE(1224000000, 51, 1, 0),
- PLL_RATE(1248000000, 52, 1, 0),
- PLL_RATE(1272000000, 53, 1, 0),
- PLL_RATE(1296000000, 54, 1, 0),
- PLL_RATE(1320000000, 55, 1, 0),
- PLL_RATE(1344000000, 56, 1, 0),
- PLL_RATE(1368000000, 57, 1, 0),
- PLL_RATE(1392000000, 58, 1, 0),
- PLL_RATE(1416000000, 59, 1, 0),
- PLL_RATE(1440000000, 60, 1, 0),
- PLL_RATE(1464000000, 61, 1, 0),
- PLL_RATE(1488000000, 62, 1, 0),
- PLL_RATE(1512000000, 63, 1, 0),
- PLL_RATE(1536000000, 64, 1, 0),
+static const struct pll_params_table sys_pll_params_table[] = {
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
+ PLL_PARAMS(63, 1),
+ PLL_PARAMS(64, 1),
{ /* sentinel */ },
};
@@ -94,8 +54,13 @@ static struct clk_fixed_rate meson8b_xtal = {
},
};
-static struct clk_regmap meson8b_fixed_pll = {
+static struct clk_regmap meson8b_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_MPLL_CNTL,
.shift = 0,
@@ -106,11 +71,6 @@ static struct clk_regmap meson8b_fixed_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_MPLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.frac = {
.reg_off = HHI_MPLL_CNTL2,
.shift = 0,
@@ -128,16 +88,39 @@ static struct clk_regmap meson8b_fixed_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "fixed_pll",
+ .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
},
};
-static struct clk_regmap meson8b_vid_pll = {
+static struct clk_regmap meson8b_fixed_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "fixed_pll_dco" },
+ .num_parents = 1,
+ /*
+ * This clock won't ever change at runtime so
+ * CLK_SET_RATE_PARENT is not required
+ */
+ },
+};
+
+static struct clk_regmap meson8b_vid_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_VID_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_VID_PLL_CNTL,
.shift = 0,
@@ -148,11 +131,6 @@ static struct clk_regmap meson8b_vid_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_VID_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.l = {
.reg_off = HHI_VID_PLL_CNTL,
.shift = 31,
@@ -165,16 +143,36 @@ static struct clk_regmap meson8b_vid_pll = {
},
},
.hw.init = &(struct clk_init_data){
- .name = "vid_pll",
+ .name = "vid_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
},
};
-static struct clk_regmap meson8b_sys_pll = {
+static struct clk_regmap meson8b_vid_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_VID_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "vid_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "vid_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap meson8b_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
.m = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
@@ -185,11 +183,6 @@ static struct clk_regmap meson8b_sys_pll = {
.shift = 9,
.width = 5,
},
- .od = {
- .reg_off = HHI_SYS_PLL_CNTL,
- .shift = 16,
- .width = 2,
- },
.l = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 31,
@@ -200,14 +193,29 @@ static struct clk_regmap meson8b_sys_pll = {
.shift = 29,
.width = 1,
},
- .table = sys_pll_rate_table,
+ .table = sys_pll_params_table,
},
.hw.init = &(struct clk_init_data){
- .name = "sys_pll",
+ .name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap meson8b_sys_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = HHI_SYS_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_names = (const char *[]){ "sys_pll_dco" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
},
};
@@ -879,6 +887,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw,
[CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw,
[CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw,
+ [CLKID_PLL_FIXED_DCO] = &meson8b_fixed_pll_dco.hw,
+ [CLKID_PLL_VID_DCO] = &meson8b_vid_pll_dco.hw,
+ [CLKID_PLL_SYS_DCO] = &meson8b_sys_pll_dco.hw,
[CLK_NR_CLKS] = NULL,
},
.num = CLK_NR_CLKS,
@@ -987,6 +998,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_nand_clk_sel,
&meson8b_nand_clk_div,
&meson8b_nand_clk_gate,
+ &meson8b_fixed_pll_dco,
+ &meson8b_vid_pll_dco,
+ &meson8b_sys_pll_dco,
};
static const struct meson8b_clk_reset_line {
@@ -1050,7 +1064,6 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
container_of(rcdev, struct meson8b_clk_reset, reset);
unsigned long flags;
const struct meson8b_clk_reset_line *reset;
- u32 val;
if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
return -EINVAL;
@@ -1059,12 +1072,12 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
spin_lock_irqsave(&meson_clk_lock, flags);
- val = readl(meson8b_clk_reset->base + reset->reg);
if (assert)
- val |= BIT(reset->bit_idx);
+ regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
+ BIT(reset->bit_idx), BIT(reset->bit_idx));
else
- val &= ~BIT(reset->bit_idx);
- writel(val, meson8b_clk_reset->base + reset->reg);
+ regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
+ BIT(reset->bit_idx), 0);
spin_unlock_irqrestore(&meson_clk_lock, flags);
@@ -1094,62 +1107,12 @@ static const struct regmap_config clkc_regmap_config = {
.reg_stride = 4,
};
-static int meson8b_clkc_probe(struct platform_device *pdev)
-{
- int ret, i;
- struct device *dev = &pdev->dev;
- struct regmap *map;
-
- if (!clk_base)
- return -ENXIO;
-
- map = devm_regmap_init_mmio(dev, clk_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(meson8b_clk_regmaps); i++)
- meson8b_clk_regmaps[i]->map = map;
-
- /*
- * register all clks
- * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
- */
- for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
- /* array might be sparse */
- if (!meson8b_hw_onecell_data.hws[i])
- continue;
-
- ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
- if (ret)
- return ret;
- }
-
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
- &meson8b_hw_onecell_data);
-}
-
-static const struct of_device_id meson8b_clkc_match_table[] = {
- { .compatible = "amlogic,meson8-clkc" },
- { .compatible = "amlogic,meson8b-clkc" },
- { .compatible = "amlogic,meson8m2-clkc" },
- { }
-};
-
-static struct platform_driver meson8b_driver = {
- .probe = meson8b_clkc_probe,
- .driver = {
- .name = "meson8b-clkc",
- .of_match_table = meson8b_clkc_match_table,
- },
-};
-
-builtin_platform_driver(meson8b_driver);
-
-static void __init meson8b_clkc_reset_init(struct device_node *np)
+static void __init meson8b_clkc_init(struct device_node *np)
{
struct meson8b_clk_reset *rstc;
- int ret;
+ void __iomem *clk_base;
+ struct regmap *map;
+ int i, ret;
/* Generic clocks, PLLs and some of the reset-bits */
clk_base = of_iomap(np, 1);
@@ -1158,12 +1121,16 @@ static void __init meson8b_clkc_reset_init(struct device_node *np)
return;
}
+ map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config);
+ if (IS_ERR(map))
+ return;
+
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
if (!rstc)
return;
/* Reset Controller */
- rstc->base = clk_base;
+ rstc->regmap = map;
rstc->reset.ops = &meson8b_clk_reset_ops;
rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits);
rstc->reset.of_node = np;
@@ -1173,11 +1140,34 @@ static void __init meson8b_clkc_reset_init(struct device_node *np)
__func__, ret);
return;
}
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
+ meson8b_clk_regmaps[i]->map = map;
+
+ /*
+ * register all clks
+ * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
+ */
+ for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
+ /* array might be sparse */
+ if (!meson8b_hw_onecell_data.hws[i])
+ continue;
+
+ ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[i]);
+ if (ret)
+ return;
+ }
+
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
+ &meson8b_hw_onecell_data);
+ if (ret)
+ pr_err("%s: failed to register clock provider\n", __func__);
}
CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc",
- meson8b_clkc_reset_init);
+ meson8b_clkc_init);
CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc",
- meson8b_clkc_reset_init);
+ meson8b_clkc_init);
CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc",
- meson8b_clkc_reset_init);
+ meson8b_clkc_init);
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 5d09412b5084..1c6fb180e6a2 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -75,8 +75,11 @@
#define CLKID_FCLK_DIV7_DIV 109
#define CLKID_NAND_SEL 110
#define CLKID_NAND_DIV 111
+#define CLKID_PLL_FIXED_DCO 113
+#define CLKID_PLL_VID_DCO 114
+#define CLKID_PLL_SYS_DCO 115
-#define CLK_NR_CLKS 113
+#define CLK_NR_CLKS 116
/*
* include the CLKID and RESETID that have