Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: meson: rework and clean drivers dependencies

Initially, the meson clock directory only hosted 2 controllers drivers,
for meson8 and gxbb. At the time, both used the same set of clock drivers
so managing the dependencies was not a big concern.

Since this ancient time, entropy did its job, controllers with different
requirement and specific clock drivers have been added. Unfortunately, we
did not do a great job at managing the dependencies between the
controllers and the different clock drivers. Some drivers, such as
clk-phase or vid-pll-div, are compiled even if they are useless on the
target (meson8). As we are adding new controllers, we need to be able to
pick a driver w/o pulling the whole thing.

The patch aims to clean things up by:
* providing a dedicated CONFIG_ for each clock drivers
* allowing clock drivers to be compiled as a modules, if possible
* stating explicitly which drivers are required by each controller.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://lkml.kernel.org/r/20190201125841.26785-5-jbrunet@baylibre.com

authored by

Jerome Brunet and committed by
Neil Armstrong
889c2b7e cb78ba76

+466 -282
+59 -25
drivers/clk/meson/Kconfig
··· 1 - config COMMON_CLK_AMLOGIC 2 - bool 3 - depends on ARCH_MESON || COMPILE_TEST 4 - select COMMON_CLK_REGMAP_MESON 1 + config COMMON_CLK_MESON_INPUT 2 + tristate 5 3 6 - config COMMON_CLK_AMLOGIC_AUDIO 7 - bool 8 - depends on ARCH_MESON || COMPILE_TEST 9 - select COMMON_CLK_AMLOGIC 10 - 11 - config COMMON_CLK_MESON_AO 12 - bool 13 - depends on OF 14 - depends on ARCH_MESON || COMPILE_TEST 15 - select COMMON_CLK_REGMAP_MESON 16 - select RESET_CONTROLLER 17 - 18 - config COMMON_CLK_REGMAP_MESON 19 - bool 4 + config COMMON_CLK_MESON_REGMAP 5 + tristate 20 6 select REGMAP 7 + 8 + config COMMON_CLK_MESON_DUALDIV 9 + tristate 10 + select COMMON_CLK_MESON_REGMAP 11 + 12 + config COMMON_CLK_MESON_MPLL 13 + tristate 14 + select COMMON_CLK_MESON_REGMAP 15 + 16 + config COMMON_CLK_MESON_PHASE 17 + tristate 18 + select COMMON_CLK_MESON_REGMAP 19 + 20 + config COMMON_CLK_MESON_PLL 21 + tristate 22 + select COMMON_CLK_MESON_REGMAP 23 + 24 + config COMMON_CLK_MESON_SCLK_DIV 25 + tristate 26 + select COMMON_CLK_MESON_REGMAP 27 + 28 + config COMMON_CLK_MESON_VID_PLL_DIV 29 + tristate 30 + select COMMON_CLK_MESON_REGMAP 31 + 32 + config COMMON_CLK_MESON_AO_CLKC 33 + tristate 34 + select COMMON_CLK_MESON_REGMAP 35 + select COMMON_CLK_MESON_INPUT 36 + select RESET_CONTROLLER 21 37 22 38 config COMMON_CLK_MESON8B 23 39 bool 24 - select COMMON_CLK_AMLOGIC 40 + depends on ARCH_MESON 41 + select COMMON_CLK_MESON_REGMAP 42 + select COMMON_CLK_MESON_MPLL 43 + select COMMON_CLK_MESON_PLL 44 + select MFD_SYSCON 25 45 select RESET_CONTROLLER 26 46 help 27 47 Support for the clock controller on AmLogic S802 (Meson8), ··· 50 30 51 31 config COMMON_CLK_GXBB 52 32 bool 53 - select COMMON_CLK_AMLOGIC 54 - select COMMON_CLK_MESON_AO 33 + depends on ARCH_MESON 34 + select COMMON_CLK_MESON_INPUT 35 + select COMMON_CLK_MESON_REGMAP 36 + select COMMON_CLK_MESON_DUALDIV 37 + select COMMON_CLK_MESON_VID_PLL_DIV 38 + select COMMON_CLK_MESON_MPLL 39 + select COMMON_CLK_MESON_PLL 40 + select COMMON_CLK_MESON_AO_CLKC 55 41 select MFD_SYSCON 56 42 help 57 43 Support for the clock controller on AmLogic S905 devices, aka gxbb. ··· 65 39 66 40 config COMMON_CLK_AXG 67 41 bool 68 - select COMMON_CLK_AMLOGIC 69 - select COMMON_CLK_MESON_AO 42 + depends on ARCH_MESON 43 + select COMMON_CLK_MESON_INPUT 44 + select COMMON_CLK_MESON_REGMAP 45 + select COMMON_CLK_MESON_DUALDIV 46 + select COMMON_CLK_MESON_MPLL 47 + select COMMON_CLK_MESON_PLL 48 + select COMMON_CLK_MESON_AO_CLKC 70 49 select MFD_SYSCON 71 50 help 72 51 Support for the clock controller on AmLogic A113D devices, aka axg. ··· 79 48 80 49 config COMMON_CLK_AXG_AUDIO 81 50 tristate "Meson AXG Audio Clock Controller Driver" 82 - depends on COMMON_CLK_AXG 83 - select COMMON_CLK_AMLOGIC_AUDIO 51 + depends on ARCH_MESON 52 + select COMMON_CLK_MESON_INPUT 53 + select COMMON_CLK_MESON_REGMAP 54 + select COMMON_CLK_MESON_PHASE 55 + select COMMON_CLK_MESON_SCLK_DIV 84 56 select REGMAP_MMIO 85 57 help 86 58 Support for the audio clock controller on AmLogic A113D devices,
+16 -11
drivers/clk/meson/Makefile
··· 1 - # 2 - # Makefile for Meson specific clk 3 - # 1 + # Amlogic clock drivers 4 2 5 - obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.o 6 - obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-input.o clk-dualdiv.o 7 - obj-$(CONFIG_COMMON_CLK_AMLOGIC_AUDIO) += clk-triphase.o sclk-div.o 8 - obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o 3 + obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o 4 + obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o 5 + obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o 6 + obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o 7 + obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o 8 + obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o 9 + obj-$(CONFIG_COMMON_CLK_MESON_REGMAP) += clk-regmap.o 10 + obj-$(CONFIG_COMMON_CLK_MESON_SCLK_DIV) += sclk-div.o 11 + obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o 12 + 13 + # Amlogic Clock controllers 14 + 15 + obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o 16 + obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o 17 + obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o 9 18 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o 10 - obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o 11 - obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o 12 - obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o 13 - obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o
+3 -1
drivers/clk/meson/axg-aoclk.c
··· 12 12 #include <linux/platform_device.h> 13 13 #include <linux/reset-controller.h> 14 14 #include <linux/mfd/syscon.h> 15 - #include "clkc.h" 16 15 #include "meson-aoclk.h" 17 16 #include "axg-aoclk.h" 17 + 18 + #include "clk-regmap.h" 19 + #include "clk-dualdiv.h" 18 20 19 21 #define IN_PREFIX "ao-in-" 20 22
+4 -1
drivers/clk/meson/axg-audio.c
··· 14 14 #include <linux/reset.h> 15 15 #include <linux/slab.h> 16 16 17 - #include "clkc-audio.h" 18 17 #include "axg-audio.h" 18 + #include "clk-input.h" 19 + #include "clk-regmap.h" 20 + #include "clk-phase.h" 21 + #include "sclk-div.h" 19 22 20 23 #define AXG_MST_IN_COUNT 8 21 24 #define AXG_SLV_SCLK_COUNT 10
+4 -1
drivers/clk/meson/axg.c
··· 17 17 #include <linux/platform_device.h> 18 18 #include <linux/regmap.h> 19 19 20 - #include "clkc.h" 20 + #include "clk-input.h" 21 + #include "clk-regmap.h" 22 + #include "clk-pll.h" 23 + #include "clk-mpll.h" 21 24 #include "axg.h" 22 25 23 26 #define IN_PREFIX "ee-in-"
+9 -1
drivers/clk/meson/clk-dualdiv.c
··· 22 22 */ 23 23 24 24 #include <linux/clk-provider.h> 25 - #include "clkc.h" 25 + #include <linux/module.h> 26 + 27 + #include "clk-regmap.h" 28 + #include "clk-dualdiv.h" 26 29 27 30 static inline struct meson_clk_dualdiv_data * 28 31 meson_clk_dualdiv_data(struct clk_regmap *clk) ··· 131 128 .recalc_rate = meson_clk_dualdiv_recalc_rate, 132 129 }; 133 130 EXPORT_SYMBOL_GPL(meson_clk_dualdiv_ro_ops); 131 + 132 + MODULE_DESCRIPTION("Amlogic dual divider driver"); 133 + MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 134 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 135 + MODULE_LICENSE("GPL v2");
+33
drivers/clk/meson/clk-dualdiv.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 BayLibre, SAS. 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #ifndef __MESON_CLK_DUALDIV_H 8 + #define __MESON_CLK_DUALDIV_H 9 + 10 + #include <linux/clk-provider.h> 11 + #include "parm.h" 12 + 13 + struct meson_clk_dualdiv_param { 14 + unsigned int n1; 15 + unsigned int n2; 16 + unsigned int m1; 17 + unsigned int m2; 18 + unsigned int dual; 19 + }; 20 + 21 + struct meson_clk_dualdiv_data { 22 + struct parm n1; 23 + struct parm n2; 24 + struct parm m1; 25 + struct parm m2; 26 + struct parm dual; 27 + const struct meson_clk_dualdiv_param *table; 28 + }; 29 + 30 + extern const struct clk_ops meson_clk_dualdiv_ops; 31 + extern const struct clk_ops meson_clk_dualdiv_ro_ops; 32 + 33 + #endif /* __MESON_CLK_DUALDIV_H */
+6 -1
drivers/clk/meson/clk-input.c
··· 7 7 #include <linux/clk.h> 8 8 #include <linux/clk-provider.h> 9 9 #include <linux/device.h> 10 - #include "clkc.h" 10 + #include <linux/module.h> 11 + #include "clk-input.h" 11 12 12 13 static const struct clk_ops meson_clk_no_ops = {}; 13 14 ··· 43 42 return ret ? ERR_PTR(ret) : hw; 44 43 } 45 44 EXPORT_SYMBOL_GPL(meson_clk_hw_register_input); 45 + 46 + MODULE_DESCRIPTION("Amlogic clock input helper"); 47 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 48 + MODULE_LICENSE("GPL v2");
+19
drivers/clk/meson/clk-input.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 BayLibre, SAS. 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #ifndef __MESON_CLK_INPUT_H 8 + #define __MESON_CLK_INPUT_H 9 + 10 + #include <linux/clk-provider.h> 11 + 12 + struct device; 13 + 14 + struct clk_hw *meson_clk_hw_register_input(struct device *dev, 15 + const char *of_name, 16 + const char *clk_name, 17 + unsigned long flags); 18 + 19 + #endif /* __MESON_CLK_INPUT_H */
+11 -1
drivers/clk/meson/clk-mpll.c
··· 12 12 */ 13 13 14 14 #include <linux/clk-provider.h> 15 - #include "clkc.h" 15 + #include <linux/module.h> 16 + #include <linux/spinlock.h> 17 + 18 + #include "clk-regmap.h" 19 + #include "clk-mpll.h" 16 20 17 21 #define SDM_DEN 16384 18 22 #define N2_MIN 4 ··· 142 138 .recalc_rate = mpll_recalc_rate, 143 139 .round_rate = mpll_round_rate, 144 140 }; 141 + EXPORT_SYMBOL_GPL(meson_clk_mpll_ro_ops); 145 142 146 143 const struct clk_ops meson_clk_mpll_ops = { 147 144 .recalc_rate = mpll_recalc_rate, 148 145 .round_rate = mpll_round_rate, 149 146 .set_rate = mpll_set_rate, 150 147 }; 148 + EXPORT_SYMBOL_GPL(meson_clk_mpll_ops); 149 + 150 + MODULE_DESCRIPTION("Amlogic MPLL driver"); 151 + MODULE_AUTHOR("Michael Turquette <mturquette@baylibre.com>"); 152 + MODULE_LICENSE("GPL v2");
+30
drivers/clk/meson/clk-mpll.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 BayLibre, SAS. 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #ifndef __MESON_CLK_MPLL_H 8 + #define __MESON_CLK_MPLL_H 9 + 10 + #include <linux/clk-provider.h> 11 + #include <linux/spinlock.h> 12 + 13 + #include "parm.h" 14 + 15 + struct meson_clk_mpll_data { 16 + struct parm sdm; 17 + struct parm sdm_en; 18 + struct parm n2; 19 + struct parm ssen; 20 + struct parm misc; 21 + spinlock_t *lock; 22 + u8 flags; 23 + }; 24 + 25 + #define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0) 26 + 27 + extern const struct clk_ops meson_clk_mpll_ro_ops; 28 + extern const struct clk_ops meson_clk_mpll_ops; 29 + 30 + #endif /* __MESON_CLK_MPLL_H */
+70 -5
drivers/clk/meson/clk-phase.c
··· 5 5 */ 6 6 7 7 #include <linux/clk-provider.h> 8 - #include "clkc.h" 8 + #include <linux/module.h> 9 + 10 + #include "clk-regmap.h" 11 + #include "clk-phase.h" 9 12 10 13 #define phase_step(_width) (360 / (1 << (_width))) 11 14 ··· 18 15 return (struct meson_clk_phase_data *)clk->data; 19 16 } 20 17 21 - int meson_clk_degrees_from_val(unsigned int val, unsigned int width) 18 + static int meson_clk_degrees_from_val(unsigned int val, unsigned int width) 22 19 { 23 20 return phase_step(width) * val; 24 21 } 25 - EXPORT_SYMBOL_GPL(meson_clk_degrees_from_val); 26 22 27 - unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width) 23 + static unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width) 28 24 { 29 25 unsigned int val = DIV_ROUND_CLOSEST(degrees, phase_step(width)); 30 26 ··· 33 31 */ 34 32 return val % (1 << width); 35 33 } 36 - EXPORT_SYMBOL_GPL(meson_clk_degrees_to_val); 37 34 38 35 static int meson_clk_phase_get_phase(struct clk_hw *hw) 39 36 { ··· 62 61 .set_phase = meson_clk_phase_set_phase, 63 62 }; 64 63 EXPORT_SYMBOL_GPL(meson_clk_phase_ops); 64 + 65 + /* 66 + * This is a special clock for the audio controller. 67 + * The phase of mst_sclk clock output can be controlled independently 68 + * for the outside world (ph0), the tdmout (ph1) and tdmin (ph2). 69 + * Controlling these 3 phases as just one makes things simpler and 70 + * give the same clock view to all the element on the i2s bus. 71 + * If necessary, we can still control the phase in the tdm block 72 + * which makes these independent control redundant. 73 + */ 74 + static inline struct meson_clk_triphase_data * 75 + meson_clk_triphase_data(struct clk_regmap *clk) 76 + { 77 + return (struct meson_clk_triphase_data *)clk->data; 78 + } 79 + 80 + static void meson_clk_triphase_sync(struct clk_hw *hw) 81 + { 82 + struct clk_regmap *clk = to_clk_regmap(hw); 83 + struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); 84 + unsigned int val; 85 + 86 + /* Get phase 0 and sync it to phase 1 and 2 */ 87 + val = meson_parm_read(clk->map, &tph->ph0); 88 + meson_parm_write(clk->map, &tph->ph1, val); 89 + meson_parm_write(clk->map, &tph->ph2, val); 90 + } 91 + 92 + static int meson_clk_triphase_get_phase(struct clk_hw *hw) 93 + { 94 + struct clk_regmap *clk = to_clk_regmap(hw); 95 + struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); 96 + unsigned int val; 97 + 98 + /* Phase are in sync, reading phase 0 is enough */ 99 + val = meson_parm_read(clk->map, &tph->ph0); 100 + 101 + return meson_clk_degrees_from_val(val, tph->ph0.width); 102 + } 103 + 104 + static int meson_clk_triphase_set_phase(struct clk_hw *hw, int degrees) 105 + { 106 + struct clk_regmap *clk = to_clk_regmap(hw); 107 + struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); 108 + unsigned int val; 109 + 110 + val = meson_clk_degrees_to_val(degrees, tph->ph0.width); 111 + meson_parm_write(clk->map, &tph->ph0, val); 112 + meson_parm_write(clk->map, &tph->ph1, val); 113 + meson_parm_write(clk->map, &tph->ph2, val); 114 + 115 + return 0; 116 + } 117 + 118 + const struct clk_ops meson_clk_triphase_ops = { 119 + .init = meson_clk_triphase_sync, 120 + .get_phase = meson_clk_triphase_get_phase, 121 + .set_phase = meson_clk_triphase_set_phase, 122 + }; 123 + EXPORT_SYMBOL_GPL(meson_clk_triphase_ops); 124 + 125 + MODULE_DESCRIPTION("Amlogic phase driver"); 126 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 127 + MODULE_LICENSE("GPL v2");
+26
drivers/clk/meson/clk-phase.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 BayLibre, SAS. 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #ifndef __MESON_CLK_PHASE_H 8 + #define __MESON_CLK_PHASE_H 9 + 10 + #include <linux/clk-provider.h> 11 + #include "parm.h" 12 + 13 + struct meson_clk_phase_data { 14 + struct parm ph; 15 + }; 16 + 17 + struct meson_clk_triphase_data { 18 + struct parm ph0; 19 + struct parm ph1; 20 + struct parm ph2; 21 + }; 22 + 23 + extern const struct clk_ops meson_clk_phase_ops; 24 + extern const struct clk_ops meson_clk_triphase_ops; 25 + 26 + #endif /* __MESON_CLK_PHASE_H */
+9 -4
drivers/clk/meson/clk-pll.c
··· 32 32 #include <linux/io.h> 33 33 #include <linux/math64.h> 34 34 #include <linux/module.h> 35 - #include <linux/of_address.h> 36 - #include <linux/slab.h> 37 - #include <linux/string.h> 38 35 39 - #include "clkc.h" 36 + #include "clk-regmap.h" 37 + #include "clk-pll.h" 40 38 41 39 static inline struct meson_clk_pll_data * 42 40 meson_clk_pll_data(struct clk_regmap *clk) ··· 307 309 .enable = meson_clk_pll_enable, 308 310 .disable = meson_clk_pll_disable 309 311 }; 312 + EXPORT_SYMBOL_GPL(meson_clk_pll_ops); 310 313 311 314 const struct clk_ops meson_clk_pll_ro_ops = { 312 315 .recalc_rate = meson_clk_pll_recalc_rate, 313 316 .is_enabled = meson_clk_pll_is_enabled, 314 317 }; 318 + EXPORT_SYMBOL_GPL(meson_clk_pll_ro_ops); 319 + 320 + MODULE_DESCRIPTION("Amlogic PLL driver"); 321 + MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>"); 322 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 323 + MODULE_LICENSE("GPL v2");
+43
drivers/clk/meson/clk-pll.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 BayLibre, SAS. 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #ifndef __MESON_CLK_PLL_H 8 + #define __MESON_CLK_PLL_H 9 + 10 + #include <linux/clk-provider.h> 11 + #include <linux/regmap.h> 12 + #include "parm.h" 13 + 14 + struct pll_params_table { 15 + u16 m; 16 + u16 n; 17 + }; 18 + 19 + #define PLL_PARAMS(_m, _n) \ 20 + { \ 21 + .m = (_m), \ 22 + .n = (_n), \ 23 + } 24 + 25 + #define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) 26 + 27 + struct meson_clk_pll_data { 28 + struct parm en; 29 + struct parm m; 30 + struct parm n; 31 + struct parm frac; 32 + struct parm l; 33 + struct parm rst; 34 + const struct reg_sequence *init_regs; 35 + unsigned int init_count; 36 + const struct pll_params_table *table; 37 + u8 flags; 38 + }; 39 + 40 + extern const struct clk_ops meson_clk_pll_ro_ops; 41 + extern const struct clk_ops meson_clk_pll_ops; 42 + 43 + #endif /* __MESON_CLK_PLL_H */
+5
drivers/clk/meson/clk-regmap.c
··· 4 4 * Author: Jerome Brunet <jbrunet@baylibre.com> 5 5 */ 6 6 7 + #include <linux/module.h> 7 8 #include "clk-regmap.h" 8 9 9 10 static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable) ··· 181 180 .get_parent = clk_regmap_mux_get_parent, 182 181 }; 183 182 EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops); 183 + 184 + MODULE_DESCRIPTION("Amlogic regmap backed clock driver"); 185 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 186 + MODULE_LICENSE("GPL v2");
+15
drivers/clk/meson/clk-regmap.h
··· 111 111 extern const struct clk_ops clk_regmap_mux_ops; 112 112 extern const struct clk_ops clk_regmap_mux_ro_ops; 113 113 114 + #define MESON_GATE(_name, _reg, _bit) \ 115 + struct clk_regmap _name = { \ 116 + .data = &(struct clk_regmap_gate_data){ \ 117 + .offset = (_reg), \ 118 + .bit_idx = (_bit), \ 119 + }, \ 120 + .hw.init = &(struct clk_init_data) { \ 121 + .name = #_name, \ 122 + .ops = &clk_regmap_gate_ops, \ 123 + .parent_names = (const char *[]){ "clk81" }, \ 124 + .num_parents = 1, \ 125 + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ 126 + }, \ 127 + } 128 + 114 129 #endif /* __CLK_REGMAP_H */
-68
drivers/clk/meson/clk-triphase.c
··· 1 - // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 - /* 3 - * Copyright (c) 2018 BayLibre, SAS. 4 - * Author: Jerome Brunet <jbrunet@baylibre.com> 5 - */ 6 - 7 - #include <linux/clk-provider.h> 8 - #include "clkc-audio.h" 9 - 10 - /* 11 - * This is a special clock for the audio controller. 12 - * The phase of mst_sclk clock output can be controlled independently 13 - * for the outside world (ph0), the tdmout (ph1) and tdmin (ph2). 14 - * Controlling these 3 phases as just one makes things simpler and 15 - * give the same clock view to all the element on the i2s bus. 16 - * If necessary, we can still control the phase in the tdm block 17 - * which makes these independent control redundant. 18 - */ 19 - static inline struct meson_clk_triphase_data * 20 - meson_clk_triphase_data(struct clk_regmap *clk) 21 - { 22 - return (struct meson_clk_triphase_data *)clk->data; 23 - } 24 - 25 - static void meson_clk_triphase_sync(struct clk_hw *hw) 26 - { 27 - struct clk_regmap *clk = to_clk_regmap(hw); 28 - struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); 29 - unsigned int val; 30 - 31 - /* Get phase 0 and sync it to phase 1 and 2 */ 32 - val = meson_parm_read(clk->map, &tph->ph0); 33 - meson_parm_write(clk->map, &tph->ph1, val); 34 - meson_parm_write(clk->map, &tph->ph2, val); 35 - } 36 - 37 - static int meson_clk_triphase_get_phase(struct clk_hw *hw) 38 - { 39 - struct clk_regmap *clk = to_clk_regmap(hw); 40 - struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); 41 - unsigned int val; 42 - 43 - /* Phase are in sync, reading phase 0 is enough */ 44 - val = meson_parm_read(clk->map, &tph->ph0); 45 - 46 - return meson_clk_degrees_from_val(val, tph->ph0.width); 47 - } 48 - 49 - static int meson_clk_triphase_set_phase(struct clk_hw *hw, int degrees) 50 - { 51 - struct clk_regmap *clk = to_clk_regmap(hw); 52 - struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); 53 - unsigned int val; 54 - 55 - val = meson_clk_degrees_to_val(degrees, tph->ph0.width); 56 - meson_parm_write(clk->map, &tph->ph0, val); 57 - meson_parm_write(clk->map, &tph->ph1, val); 58 - meson_parm_write(clk->map, &tph->ph2, val); 59 - 60 - return 0; 61 - } 62 - 63 - const struct clk_ops meson_clk_triphase_ops = { 64 - .init = meson_clk_triphase_sync, 65 - .get_phase = meson_clk_triphase_get_phase, 66 - .set_phase = meson_clk_triphase_set_phase, 67 - }; 68 - EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);
+5 -11
drivers/clk/meson/clkc-audio.h drivers/clk/meson/sclk-div.h
··· 4 4 * Author: Jerome Brunet <jbrunet@baylibre.com> 5 5 */ 6 6 7 - #ifndef __MESON_CLKC_AUDIO_H 8 - #define __MESON_CLKC_AUDIO_H 7 + #ifndef __MESON_SCLK_DIV_H 8 + #define __MESON_SCLK_DIV_H 9 9 10 - #include "clkc.h" 11 - 12 - struct meson_clk_triphase_data { 13 - struct parm ph0; 14 - struct parm ph1; 15 - struct parm ph2; 16 - }; 10 + #include <linux/clk-provider.h> 11 + #include "parm.h" 17 12 18 13 struct meson_sclk_div_data { 19 14 struct parm div; ··· 17 22 struct clk_duty cached_duty; 18 23 }; 19 24 20 - extern const struct clk_ops meson_clk_triphase_ops; 21 25 extern const struct clk_ops meson_sclk_div_ops; 22 26 23 - #endif /* __MESON_CLKC_AUDIO_H */ 27 + #endif /* __MESON_SCLK_DIV_H */
-146
drivers/clk/meson/clkc.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * Copyright (c) 2015 Endless Mobile, Inc. 4 - * Author: Carlo Caione <carlo@endlessm.com> 5 - */ 6 - 7 - #ifndef __CLKC_H 8 - #define __CLKC_H 9 - 10 - #include <linux/clk-provider.h> 11 - #include "clk-regmap.h" 12 - 13 - #define PMASK(width) GENMASK(width - 1, 0) 14 - #define SETPMASK(width, shift) GENMASK(shift + width - 1, shift) 15 - #define CLRPMASK(width, shift) (~SETPMASK(width, shift)) 16 - 17 - #define PARM_GET(width, shift, reg) \ 18 - (((reg) & SETPMASK(width, shift)) >> (shift)) 19 - #define PARM_SET(width, shift, reg, val) \ 20 - (((reg) & CLRPMASK(width, shift)) | ((val) << (shift))) 21 - 22 - #define MESON_PARM_APPLICABLE(p) (!!((p)->width)) 23 - 24 - struct parm { 25 - u16 reg_off; 26 - u8 shift; 27 - u8 width; 28 - }; 29 - 30 - static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p) 31 - { 32 - unsigned int val; 33 - 34 - regmap_read(map, p->reg_off, &val); 35 - return PARM_GET(p->width, p->shift, val); 36 - } 37 - 38 - static inline void meson_parm_write(struct regmap *map, struct parm *p, 39 - unsigned int val) 40 - { 41 - regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift), 42 - val << p->shift); 43 - } 44 - 45 - 46 - struct pll_params_table { 47 - u16 m; 48 - u16 n; 49 - }; 50 - 51 - #define PLL_PARAMS(_m, _n) \ 52 - { \ 53 - .m = (_m), \ 54 - .n = (_n), \ 55 - } 56 - 57 - #define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) 58 - 59 - struct meson_clk_pll_data { 60 - struct parm en; 61 - struct parm m; 62 - struct parm n; 63 - struct parm frac; 64 - struct parm l; 65 - struct parm rst; 66 - const struct reg_sequence *init_regs; 67 - unsigned int init_count; 68 - const struct pll_params_table *table; 69 - u8 flags; 70 - }; 71 - 72 - #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) 73 - 74 - struct meson_clk_mpll_data { 75 - struct parm sdm; 76 - struct parm sdm_en; 77 - struct parm n2; 78 - struct parm ssen; 79 - struct parm misc; 80 - spinlock_t *lock; 81 - u8 flags; 82 - }; 83 - 84 - #define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0) 85 - 86 - struct meson_clk_phase_data { 87 - struct parm ph; 88 - }; 89 - 90 - int meson_clk_degrees_from_val(unsigned int val, unsigned int width); 91 - unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width); 92 - 93 - struct meson_vid_pll_div_data { 94 - struct parm val; 95 - struct parm sel; 96 - }; 97 - 98 - #define MESON_GATE(_name, _reg, _bit) \ 99 - struct clk_regmap _name = { \ 100 - .data = &(struct clk_regmap_gate_data){ \ 101 - .offset = (_reg), \ 102 - .bit_idx = (_bit), \ 103 - }, \ 104 - .hw.init = &(struct clk_init_data) { \ 105 - .name = #_name, \ 106 - .ops = &clk_regmap_gate_ops, \ 107 - .parent_names = (const char *[]){ "clk81" }, \ 108 - .num_parents = 1, \ 109 - .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ 110 - }, \ 111 - }; 112 - 113 - struct meson_clk_dualdiv_param { 114 - unsigned int n1; 115 - unsigned int n2; 116 - unsigned int m1; 117 - unsigned int m2; 118 - unsigned int dual; 119 - }; 120 - 121 - struct meson_clk_dualdiv_data { 122 - struct parm n1; 123 - struct parm n2; 124 - struct parm m1; 125 - struct parm m2; 126 - struct parm dual; 127 - const struct meson_clk_dualdiv_param *table; 128 - }; 129 - 130 - /* clk_ops */ 131 - extern const struct clk_ops meson_clk_pll_ro_ops; 132 - extern const struct clk_ops meson_clk_pll_ops; 133 - extern const struct clk_ops meson_clk_cpu_ops; 134 - extern const struct clk_ops meson_clk_mpll_ro_ops; 135 - extern const struct clk_ops meson_clk_mpll_ops; 136 - extern const struct clk_ops meson_clk_phase_ops; 137 - extern const struct clk_ops meson_vid_pll_div_ro_ops; 138 - extern const struct clk_ops meson_clk_dualdiv_ops; 139 - extern const struct clk_ops meson_clk_dualdiv_ro_ops; 140 - 141 - struct clk_hw *meson_clk_hw_register_input(struct device *dev, 142 - const char *of_name, 143 - const char *clk_name, 144 - unsigned long flags); 145 - 146 - #endif /* __CLKC_H */
+3 -1
drivers/clk/meson/gxbb-aoclk.c
··· 5 5 */ 6 6 #include <linux/platform_device.h> 7 7 #include <linux/mfd/syscon.h> 8 - #include "clkc.h" 9 8 #include "meson-aoclk.h" 10 9 #include "gxbb-aoclk.h" 10 + 11 + #include "clk-regmap.h" 12 + #include "clk-dualdiv.h" 11 13 12 14 #define IN_PREFIX "ao-in-" 13 15
+4 -1
drivers/clk/meson/gxbb.c
··· 12 12 #include <linux/platform_device.h> 13 13 #include <linux/regmap.h> 14 14 15 - #include "clkc.h" 16 15 #include "gxbb.h" 16 + #include "clk-input.h" 17 17 #include "clk-regmap.h" 18 + #include "clk-pll.h" 19 + #include "clk-mpll.h" 20 + #include "vid-pll-div.h" 18 21 19 22 #define IN_PREFIX "ee-in-" 20 23
+2
drivers/clk/meson/meson-aoclk.c
··· 17 17 #include <linux/slab.h> 18 18 #include "meson-aoclk.h" 19 19 20 + #include "clk-input.h" 21 + 20 22 static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev, 21 23 unsigned long id) 22 24 {
+4 -1
drivers/clk/meson/meson-aoclk.h
··· 11 11 #ifndef __MESON_AOCLK_H__ 12 12 #define __MESON_AOCLK_H__ 13 13 14 + #include <linux/clk-provider.h> 14 15 #include <linux/platform_device.h> 16 + #include <linux/regmap.h> 15 17 #include <linux/reset-controller.h> 16 - #include "clkc.h" 18 + 19 + #include "clk-regmap.h" 17 20 18 21 struct meson_aoclk_input { 19 22 const char *name;
+2 -1
drivers/clk/meson/meson8b.c
··· 16 16 #include <linux/slab.h> 17 17 #include <linux/regmap.h> 18 18 19 - #include "clkc.h" 20 19 #include "meson8b.h" 21 20 #include "clk-regmap.h" 21 + #include "clk-pll.h" 22 + #include "clk-mpll.h" 22 23 23 24 static DEFINE_SPINLOCK(meson_clk_lock); 24 25
+46
drivers/clk/meson/parm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2015 Endless Mobile, Inc. 4 + * Author: Carlo Caione <carlo@endlessm.com> 5 + */ 6 + 7 + #ifndef __MESON_PARM_H 8 + #define __MESON_PARM_H 9 + 10 + #include <linux/bits.h> 11 + #include <linux/regmap.h> 12 + 13 + #define PMASK(width) GENMASK(width - 1, 0) 14 + #define SETPMASK(width, shift) GENMASK(shift + width - 1, shift) 15 + #define CLRPMASK(width, shift) (~SETPMASK(width, shift)) 16 + 17 + #define PARM_GET(width, shift, reg) \ 18 + (((reg) & SETPMASK(width, shift)) >> (shift)) 19 + #define PARM_SET(width, shift, reg, val) \ 20 + (((reg) & CLRPMASK(width, shift)) | ((val) << (shift))) 21 + 22 + #define MESON_PARM_APPLICABLE(p) (!!((p)->width)) 23 + 24 + struct parm { 25 + u16 reg_off; 26 + u8 shift; 27 + u8 width; 28 + }; 29 + 30 + static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p) 31 + { 32 + unsigned int val; 33 + 34 + regmap_read(map, p->reg_off, &val); 35 + return PARM_GET(p->width, p->shift, val); 36 + } 37 + 38 + static inline void meson_parm_write(struct regmap *map, struct parm *p, 39 + unsigned int val) 40 + { 41 + regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift), 42 + val << p->shift); 43 + } 44 + 45 + #endif /* __MESON_PARM_H */ 46 +
+9 -1
drivers/clk/meson/sclk-div.c
··· 16 16 * duty_cycle = (1 + hi) / (1 + val) 17 17 */ 18 18 19 - #include "clkc-audio.h" 19 + #include <linux/clk-provider.h> 20 + #include <linux/module.h> 21 + 22 + #include "clk-regmap.h" 23 + #include "sclk-div.h" 20 24 21 25 static inline struct meson_sclk_div_data * 22 26 meson_sclk_div_data(struct clk_regmap *clk) ··· 245 241 .init = sclk_div_init, 246 242 }; 247 243 EXPORT_SYMBOL_GPL(meson_sclk_div_ops); 244 + 245 + MODULE_DESCRIPTION("Amlogic Sample divider driver"); 246 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 247 + MODULE_LICENSE("GPL v2");
+9 -1
drivers/clk/meson/vid-pll-div.c
··· 5 5 */ 6 6 7 7 #include <linux/clk-provider.h> 8 - #include "clkc.h" 8 + #include <linux/module.h> 9 + 10 + #include "clk-regmap.h" 11 + #include "vid-pll-div.h" 9 12 10 13 static inline struct meson_vid_pll_div_data * 11 14 meson_vid_pll_div_data(struct clk_regmap *clk) ··· 92 89 const struct clk_ops meson_vid_pll_div_ro_ops = { 93 90 .recalc_rate = meson_vid_pll_div_recalc_rate, 94 91 }; 92 + EXPORT_SYMBOL_GPL(meson_vid_pll_div_ro_ops); 93 + 94 + MODULE_DESCRIPTION("Amlogic video pll divider driver"); 95 + MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 96 + MODULE_LICENSE("GPL v2");
+20
drivers/clk/meson/vid-pll-div.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2019 BayLibre, SAS. 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #ifndef __MESON_VID_PLL_DIV_H 8 + #define __MESON_VID_PLL_DIV_H 9 + 10 + #include <linux/clk-provider.h> 11 + #include "parm.h" 12 + 13 + struct meson_vid_pll_div_data { 14 + struct parm val; 15 + struct parm sel; 16 + }; 17 + 18 + extern const struct clk_ops meson_vid_pll_div_ro_ops; 19 + 20 + #endif /* __MESON_VID_PLL_DIV_H */