mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	Merge branches 'clk-mvebu-periph-pm', 'clk-meson', 'clk-allwinner', 'clk-mvebu-dup' and 'clk-davinci' into clk-next
- S2RAM support for Marvell mvebu periph clks * clk-mvebu-periph-pm: clk: mvebu: armada-37xx-periph: add suspend/resume support clk: mvebu: armada-37xx-periph: save the IP base address in the driver data * clk-meson: clk: meson: meson8b: use the regmap in the internal reset controller clk: meson: meson8b: register the clock controller early clk: meson-axg: pcie: drop the mpll3 clock parent clk: meson: axg: round audio system master clocks down clk: meson: clk-pll: drop hard-coded rates from pll tables clk: meson: clk-pll: remove od parameters clk: meson: clk-pll: drop CLK_GET_RATE_NOCACHE where unnecessary clk: meson: clk-pll: add enable bit * clk-allwinner: dt-bindings: clock: sun50i-a64-ccu: Add PLL_VIDEO0 macro clk: sunxi-ng: a64: Add max. rate constraint to video PLLs clk: sunxi-ng: a64: Add minimal rate for video PLLs clk: sunxi-ng: sun50i: h6: Add 2x fixed post-divider to MMC module clocks clk: sunxi-ng: a83t: Add max. rate constraint to video PLLs clk: sunxi-ng: nkmp: Add constraint for maximum rate clk: sunxi-ng: r40: Add max. rate constraint to video PLLs clk: sunxi-ng: h3/h5: Add max. rate constraint to pll-video clk: sunxi-ng: Add maximum rate constraint to NM PLLs clk: sunxi-ng: h6: fix PWM gate/reset offset clk: sunxi-ng: h6: fix bus clocks' divider position * clk-mvebu-dup: clk: mvebu: ap806: Remove superfluous of_clk_add_provider * clk-davinci: clk: davinci: kill davinci_clk_reset_assert/deassert()
This commit is contained in:
		
						commit
						cd8ca30052
					
				
					 24 changed files with 952 additions and 787 deletions
				
			
		|  | @ -1,21 +0,0 @@ | |||
| /*
 | ||||
|  * arch/arm/mach-davinci/include/mach/clock.h | ||||
|  * | ||||
|  * Clock control driver for DaVinci - header file | ||||
|  * | ||||
|  * Authors: Vladimir Barinov <source@mvista.com> | ||||
|  * | ||||
|  * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||||
|  * the terms of the GNU General Public License version 2. This program | ||||
|  * is licensed "as is" without any warranty of any kind, whether express | ||||
|  * or implied. | ||||
|  */ | ||||
| #ifndef __ASM_ARCH_DAVINCI_CLOCK_H | ||||
| #define __ASM_ARCH_DAVINCI_CLOCK_H | ||||
| 
 | ||||
| struct clk; | ||||
| 
 | ||||
| int davinci_clk_reset_assert(struct clk *c); | ||||
| int davinci_clk_reset_deassert(struct clk *c); | ||||
| 
 | ||||
| #endif | ||||
|  | @ -303,24 +303,6 @@ static int davinci_lpsc_clk_reset(struct clk *clk, bool reset) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * REVISIT: These exported functions can be removed after a non-DT lookup is | ||||
|  * added to the reset controller framework and the davinci-rproc driver is | ||||
|  * updated to use the generic reset controller framework. | ||||
|  */ | ||||
| 
 | ||||
| int davinci_clk_reset_assert(struct clk *clk) | ||||
| { | ||||
| 	return davinci_lpsc_clk_reset(clk, true); | ||||
| } | ||||
| EXPORT_SYMBOL(davinci_clk_reset_assert); | ||||
| 
 | ||||
| int davinci_clk_reset_deassert(struct clk *clk) | ||||
| { | ||||
| 	return davinci_lpsc_clk_reset(clk, false); | ||||
| } | ||||
| EXPORT_SYMBOL(davinci_clk_reset_deassert); | ||||
| 
 | ||||
| static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev, | ||||
| 				    unsigned long id) | ||||
| { | ||||
|  |  | |||
|  | @ -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_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_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_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); | ||||
|  |  | |||
|  | @ -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[] = { | ||||
|  |  | |||
|  | @ -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> | ||||
|  |  | |||
|  | @ -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 = { | ||||
|  |  | |||
|  | @ -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; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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,106 +187,163 @@ 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 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 = &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 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_HDMI_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 0, | ||||
| 			.width   = 9, | ||||
| 		}, | ||||
| 		.n = { | ||||
| 			.reg_off = HHI_HDMI_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_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, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 31, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.rst = { | ||||
| 			.reg_off = HHI_HDMI_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 29, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 	}, | ||||
| 	.hw.init = &(struct clk_init_data){ | ||||
| 		.name = "hdmi_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 meson_clk_pll_data){ | ||||
| 		.m = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 0, | ||||
| 			.width   = 9, | ||||
| 		}, | ||||
| 		.n = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 9, | ||||
| 			.width   = 5, | ||||
| 		}, | ||||
| 		.od = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 10, | ||||
| 			.width   = 2, | ||||
| 		}, | ||||
| 		.l = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 31, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.rst = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 29, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 	.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 = &meson_clk_pll_ro_ops, | ||||
| 		.parent_names = (const char *[]){ "xtal" }, | ||||
| 		.ops = &clk_regmap_divider_ro_ops, | ||||
| 		.parent_names = (const char *[]){ "sys_pll_dco" }, | ||||
| 		.num_parents = 1, | ||||
| 		.flags = CLK_GET_RATE_NOCACHE, | ||||
| 		.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 { | ||||
|  |  | |||
|  | @ -159,8 +159,14 @@ | |||
| #define CLKID_VDEC_HEVC_DIV	  155 | ||||
| #define CLKID_GEN_CLK_SEL	  157 | ||||
| #define CLKID_GEN_CLK_DIV	  158 | ||||
| #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			  160 | ||||
| #define NR_CLKS			  166 | ||||
| 
 | ||||
| /* include the CLKIDs that have been made part of the DT binding */ | ||||
| #include <dt-bindings/clock/gxbb-clkc.h> | ||||
|  |  | |||
|  | @ -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,86 +88,134 @@ 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, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| 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, | ||||
| 			.width   = 9, | ||||
| 		}, | ||||
| 		.n = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.shift   = 9, | ||||
| 			.width   = 5, | ||||
| 		}, | ||||
| 		.l = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.shift   = 31, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.rst = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.shift   = 29, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 	}, | ||||
| 	.hw.init = &(struct clk_init_data){ | ||||
| 		.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_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_VID_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 0, | ||||
| 			.width   = 9, | ||||
| 		}, | ||||
| 		.n = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 9, | ||||
| 			.width   = 5, | ||||
| 		}, | ||||
| 		.od = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.shift   = 16, | ||||
| 			.width   = 2, | ||||
| 		}, | ||||
| 		.l = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 31, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.rst = { | ||||
| 			.reg_off = HHI_VID_PLL_CNTL, | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 29, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.table = sys_pll_params_table, | ||||
| 	}, | ||||
| 	.hw.init = &(struct clk_init_data){ | ||||
| 		.name = "vid_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 meson_clk_pll_data){ | ||||
| 		.m = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 0, | ||||
| 			.width   = 9, | ||||
| 		}, | ||||
| 		.n = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 9, | ||||
| 			.width   = 5, | ||||
| 		}, | ||||
| 		.od = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 16, | ||||
| 			.width   = 2, | ||||
| 		}, | ||||
| 		.l = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 31, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.rst = { | ||||
| 			.reg_off = HHI_SYS_PLL_CNTL, | ||||
| 			.shift   = 29, | ||||
| 			.width   = 1, | ||||
| 		}, | ||||
| 		.table = sys_pll_rate_table, | ||||
| 	.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 = &meson_clk_pll_ro_ops, | ||||
| 		.parent_names = (const char *[]){ "xtal" }, | ||||
| 		.ops = &clk_regmap_divider_ro_ops, | ||||
| 		.parent_names = (const char *[]){ "sys_pll_dco" }, | ||||
| 		.num_parents = 1, | ||||
| 		.flags = CLK_GET_RATE_NOCACHE, | ||||
| 		.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,18 +1107,39 @@ static const struct regmap_config clkc_regmap_config = { | |||
| 	.reg_stride     = 4, | ||||
| }; | ||||
| 
 | ||||
| static int meson8b_clkc_probe(struct platform_device *pdev) | ||||
| static void __init meson8b_clkc_init(struct device_node *np) | ||||
| { | ||||
| 	int ret, i; | ||||
| 	struct device *dev = &pdev->dev; | ||||
| 	struct meson8b_clk_reset *rstc; | ||||
| 	void __iomem *clk_base; | ||||
| 	struct regmap *map; | ||||
| 	int i, ret; | ||||
| 
 | ||||
| 	if (!clk_base) | ||||
| 		return -ENXIO; | ||||
| 	/* Generic clocks, PLLs and some of the reset-bits */ | ||||
| 	clk_base = of_iomap(np, 1); | ||||
| 	if (!clk_base) { | ||||
| 		pr_err("%s: Unable to map clk base\n", __func__); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config); | ||||
| 	map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config); | ||||
| 	if (IS_ERR(map)) | ||||
| 		return PTR_ERR(map); | ||||
| 		return; | ||||
| 
 | ||||
| 	rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); | ||||
| 	if (!rstc) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* Reset Controller */ | ||||
| 	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; | ||||
| 	ret = reset_controller_register(&rstc->reset); | ||||
| 	if (ret) { | ||||
| 		pr_err("%s: Failed to register clkc reset controller: %d\n", | ||||
| 		       __func__, ret); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Populate regmap for the regmap backed clocks */ | ||||
| 	for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++) | ||||
|  | @ -1120,64 +1154,20 @@ static int meson8b_clkc_probe(struct platform_device *pdev) | |||
| 		if (!meson8b_hw_onecell_data.hws[i]) | ||||
| 			continue; | ||||
| 
 | ||||
| 		ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]); | ||||
| 		ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[i]); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 			return; | ||||
| 	} | ||||
| 
 | ||||
| 	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) | ||||
| { | ||||
| 	struct meson8b_clk_reset *rstc; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* Generic clocks, PLLs and some of the reset-bits */ | ||||
| 	clk_base = of_iomap(np, 1); | ||||
| 	if (!clk_base) { | ||||
| 		pr_err("%s: Unable to map clk base\n", __func__); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); | ||||
| 	if (!rstc) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* Reset Controller */ | ||||
| 	rstc->base = clk_base; | ||||
| 	rstc->reset.ops = &meson8b_clk_reset_ops; | ||||
| 	rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits); | ||||
| 	rstc->reset.of_node = np; | ||||
| 	ret = reset_controller_register(&rstc->reset); | ||||
| 	if (ret) { | ||||
| 		pr_err("%s: Failed to register clkc reset controller: %d\n", | ||||
| 		       __func__, 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); | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -153,7 +153,6 @@ static int ap806_syscon_common_probe(struct platform_device *pdev, | |||
| 		goto fail4; | ||||
| 	} | ||||
| 
 | ||||
| 	of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); | ||||
| 	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); | ||||
| 	if (ret) | ||||
| 		goto fail_clk_add; | ||||
|  |  | |||
|  | @ -56,6 +56,15 @@ | |||
| struct clk_periph_driver_data { | ||||
| 	struct clk_hw_onecell_data *hw_data; | ||||
| 	spinlock_t lock; | ||||
| 	void __iomem *reg; | ||||
| 
 | ||||
| 	/* Storage registers for suspend/resume operations */ | ||||
| 	u32 tbg_sel; | ||||
| 	u32 div_sel0; | ||||
| 	u32 div_sel1; | ||||
| 	u32 div_sel2; | ||||
| 	u32 clk_sel; | ||||
| 	u32 clk_dis; | ||||
| }; | ||||
| 
 | ||||
| struct clk_double_div { | ||||
|  | @ -672,6 +681,40 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data, | |||
| 	return PTR_ERR_OR_ZERO(*hw); | ||||
| } | ||||
| 
 | ||||
| static int __maybe_unused armada_3700_periph_clock_suspend(struct device *dev) | ||||
| { | ||||
| 	struct clk_periph_driver_data *data = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	data->tbg_sel = readl(data->reg + TBG_SEL); | ||||
| 	data->div_sel0 = readl(data->reg + DIV_SEL0); | ||||
| 	data->div_sel1 = readl(data->reg + DIV_SEL1); | ||||
| 	data->div_sel2 = readl(data->reg + DIV_SEL2); | ||||
| 	data->clk_sel = readl(data->reg + CLK_SEL); | ||||
| 	data->clk_dis = readl(data->reg + CLK_DIS); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int __maybe_unused armada_3700_periph_clock_resume(struct device *dev) | ||||
| { | ||||
| 	struct clk_periph_driver_data *data = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	/* Follow the same order than what the Cortex-M3 does (ATF code) */ | ||||
| 	writel(data->clk_dis, data->reg + CLK_DIS); | ||||
| 	writel(data->div_sel0, data->reg + DIV_SEL0); | ||||
| 	writel(data->div_sel1, data->reg + DIV_SEL1); | ||||
| 	writel(data->div_sel2, data->reg + DIV_SEL2); | ||||
| 	writel(data->tbg_sel, data->reg + TBG_SEL); | ||||
| 	writel(data->clk_sel, data->reg + CLK_SEL); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct dev_pm_ops armada_3700_periph_clock_pm_ops = { | ||||
| 	SET_SYSTEM_SLEEP_PM_OPS(armada_3700_periph_clock_suspend, | ||||
| 				armada_3700_periph_clock_resume) | ||||
| }; | ||||
| 
 | ||||
| static int armada_3700_periph_clock_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	struct clk_periph_driver_data *driver_data; | ||||
|  | @ -680,7 +723,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev) | |||
| 	struct device *dev = &pdev->dev; | ||||
| 	int num_periph = 0, i, ret; | ||||
| 	struct resource *res; | ||||
| 	void __iomem *reg; | ||||
| 
 | ||||
| 	data = of_device_get_match_data(dev); | ||||
| 	if (!data) | ||||
|  | @ -689,11 +731,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev) | |||
| 	while (data[num_periph].name) | ||||
| 		num_periph++; | ||||
| 
 | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| 	reg = devm_ioremap_resource(dev, res); | ||||
| 	if (IS_ERR(reg)) | ||||
| 		return PTR_ERR(reg); | ||||
| 
 | ||||
| 	driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); | ||||
| 	if (!driver_data) | ||||
| 		return -ENOMEM; | ||||
|  | @ -706,12 +743,16 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev) | |||
| 		return -ENOMEM; | ||||
| 	driver_data->hw_data->num = num_periph; | ||||
| 
 | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| 	driver_data->reg = devm_ioremap_resource(dev, res); | ||||
| 	if (IS_ERR(driver_data->reg)) | ||||
| 		return PTR_ERR(driver_data->reg); | ||||
| 
 | ||||
| 	spin_lock_init(&driver_data->lock); | ||||
| 
 | ||||
| 	for (i = 0; i < num_periph; i++) { | ||||
| 		struct clk_hw **hw = &driver_data->hw_data->hws[i]; | ||||
| 
 | ||||
| 		if (armada_3700_add_composite_clk(&data[i], reg, | ||||
| 		if (armada_3700_add_composite_clk(&data[i], driver_data->reg, | ||||
| 						  &driver_data->lock, dev, hw)) | ||||
| 			dev_err(dev, "Can't register periph clock %s\n", | ||||
| 				data[i].name); | ||||
|  | @ -749,6 +790,7 @@ static struct platform_driver armada_3700_periph_clock_driver = { | |||
| 	.driver		= { | ||||
| 		.name	= "marvell-armada-3700-periph-clock", | ||||
| 		.of_match_table = armada_3700_periph_clock_of_match, | ||||
| 		.pm	= &armada_3700_periph_clock_pm_ops, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,17 +64,19 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", | |||
| 				   BIT(28),	/* lock */ | ||||
| 				   CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", | ||||
| 					"osc24M", 0x010, | ||||
| 					8, 7,		/* N */ | ||||
| 					0, 4,		/* M */ | ||||
| 					BIT(24),	/* frac enable */ | ||||
| 					BIT(25),	/* frac select */ | ||||
| 					270000000,	/* frac rate 0 */ | ||||
| 					297000000,	/* frac rate 1 */ | ||||
| 					BIT(31),	/* gate */ | ||||
| 					BIT(28),	/* lock */ | ||||
| 					CLK_SET_RATE_UNGATE); | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0", | ||||
| 						"osc24M", 0x010, | ||||
| 						192000000,	/* Minimum rate */ | ||||
| 						1008000000,	/* Maximum rate */ | ||||
| 						8, 7,		/* N */ | ||||
| 						0, 4,		/* M */ | ||||
| 						BIT(24),	/* frac enable */ | ||||
| 						BIT(25),	/* frac select */ | ||||
| 						270000000,	/* frac rate 0 */ | ||||
| 						297000000,	/* frac rate 1 */ | ||||
| 						BIT(31),	/* gate */ | ||||
| 						BIT(28),	/* lock */ | ||||
| 						CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", | ||||
| 					"osc24M", 0x018, | ||||
|  | @ -125,17 +127,19 @@ static struct ccu_nk pll_periph1_clk = { | |||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", | ||||
| 					"osc24M", 0x030, | ||||
| 					8, 7,		/* N */ | ||||
| 					0, 4,		/* M */ | ||||
| 					BIT(24),	/* frac enable */ | ||||
| 					BIT(25),	/* frac select */ | ||||
| 					270000000,	/* frac rate 0 */ | ||||
| 					297000000,	/* frac rate 1 */ | ||||
| 					BIT(31),	/* gate */ | ||||
| 					BIT(28),	/* lock */ | ||||
| 					CLK_SET_RATE_UNGATE); | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1", | ||||
| 						"osc24M", 0x030, | ||||
| 						192000000,	/* Minimum rate */ | ||||
| 						1008000000,	/* Maximum rate */ | ||||
| 						8, 7,		/* N */ | ||||
| 						0, 4,		/* M */ | ||||
| 						BIT(24),	/* frac enable */ | ||||
| 						BIT(25),	/* frac select */ | ||||
| 						270000000,	/* frac rate 0 */ | ||||
| 						297000000,	/* frac rate 1 */ | ||||
| 						BIT(31),	/* gate */ | ||||
| 						BIT(28),	/* lock */ | ||||
| 						CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", | ||||
| 					"osc24M", 0x038, | ||||
|  |  | |||
|  | @ -27,7 +27,9 @@ | |||
| #define CLK_PLL_AUDIO_2X		4 | ||||
| #define CLK_PLL_AUDIO_4X		5 | ||||
| #define CLK_PLL_AUDIO_8X		6 | ||||
| #define CLK_PLL_VIDEO0			7 | ||||
| 
 | ||||
| /* PLL_VIDEO0 exported for HDMI PHY */ | ||||
| 
 | ||||
| #define CLK_PLL_VIDEO0_2X		8 | ||||
| #define CLK_PLL_VE			9 | ||||
| #define CLK_PLL_DDR0			10 | ||||
|  |  | |||
|  | @ -224,7 +224,7 @@ static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", | |||
| 			     psi_ahb1_ahb2_parents, | ||||
| 			     0x510, | ||||
| 			     0, 5,	/* M */ | ||||
| 			     16, 2,	/* P */ | ||||
| 			     8, 2,	/* P */ | ||||
| 			     24, 2,	/* mux */ | ||||
| 			     0); | ||||
| 
 | ||||
|  | @ -233,19 +233,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", | |||
| 						       "pll-periph0" }; | ||||
| static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, | ||||
| 			     0, 5,	/* M */ | ||||
| 			     16, 2,	/* P */ | ||||
| 			     8, 2,	/* P */ | ||||
| 			     24, 2,	/* mux */ | ||||
| 			     0); | ||||
| 
 | ||||
| static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, | ||||
| 			     0, 5,	/* M */ | ||||
| 			     16, 2,	/* P */ | ||||
| 			     8, 2,	/* P */ | ||||
| 			     24, 2,	/* mux */ | ||||
| 			     0); | ||||
| 
 | ||||
| static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, | ||||
| 			     0, 5,	/* M */ | ||||
| 			     16, 2,	/* P */ | ||||
| 			     8, 2,	/* P */ | ||||
| 			     24, 2,	/* mux */ | ||||
| 			     0); | ||||
| 
 | ||||
|  | @ -352,7 +352,7 @@ static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2", | |||
| static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", | ||||
| 		      0x79c, BIT(0), 0); | ||||
| 
 | ||||
| static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x79c, BIT(0), 0); | ||||
| static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0); | ||||
| 
 | ||||
| static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0); | ||||
| 
 | ||||
|  | @ -408,26 +408,29 @@ static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0); | |||
| 
 | ||||
| static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x", | ||||
| 					    "pll-periph1-2x" }; | ||||
| static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_parents, 0x830, | ||||
| 					0, 4,	/* M */ | ||||
| 					8, 2,	/* N */ | ||||
| 					24, 3,	/* mux */ | ||||
| 					BIT(31),/* gate */ | ||||
| 					0); | ||||
| static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830, | ||||
| 					  0, 4,		/* M */ | ||||
| 					  8, 2,		/* N */ | ||||
| 					  24, 3,	/* mux */ | ||||
| 					  BIT(31),	/* gate */ | ||||
| 					  2,		/* post-div */ | ||||
| 					  0); | ||||
| 
 | ||||
| static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_parents, 0x834, | ||||
| 					0, 4,	/* M */ | ||||
| 					8, 2,	/* N */ | ||||
| 					24, 3,	/* mux */ | ||||
| 					BIT(31),/* gate */ | ||||
| 					0); | ||||
| static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834, | ||||
| 					  0, 4,		/* M */ | ||||
| 					  8, 2,		/* N */ | ||||
| 					  24, 3,	/* mux */ | ||||
| 					  BIT(31),	/* gate */ | ||||
| 					  2,		/* post-div */ | ||||
| 					  0); | ||||
| 
 | ||||
| static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_parents, 0x838, | ||||
| 					0, 4,	/* M */ | ||||
| 					8, 2,	/* N */ | ||||
| 					24, 3,	/* mux */ | ||||
| 					BIT(31),/* gate */ | ||||
| 					0); | ||||
| static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838, | ||||
| 					  0, 4,		/* M */ | ||||
| 					  8, 2,		/* N */ | ||||
| 					  24, 3,	/* mux */ | ||||
| 					  BIT(31),	/* gate */ | ||||
| 					  2,		/* post-div */ | ||||
| 					  0); | ||||
| 
 | ||||
| static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0); | ||||
| static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0); | ||||
|  |  | |||
|  | @ -108,6 +108,7 @@ static struct ccu_nkmp pll_video0_clk = { | |||
| 	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), | ||||
| 	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */ | ||||
| 	.p		= _SUNXI_CCU_DIV(0, 2), /* output divider */ | ||||
| 	.max_rate	= 3000000000UL, | ||||
| 	.common		= { | ||||
| 		.reg		= 0x010, | ||||
| 		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG, | ||||
|  | @ -220,6 +221,7 @@ static struct ccu_nkmp pll_video1_clk = { | |||
| 	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), | ||||
| 	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */ | ||||
| 	.p		= _SUNXI_CCU_DIV(0, 2), /* external divider p */ | ||||
| 	.max_rate	= 3000000000UL, | ||||
| 	.common		= { | ||||
| 		.reg		= 0x04c, | ||||
| 		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG, | ||||
|  |  | |||
|  | @ -69,18 +69,19 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", | |||
| 				       BIT(28),	/* lock */ | ||||
| 				       CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video_clk, "pll-video", | ||||
| 					    "osc24M", 0x0010, | ||||
| 					    192000000,	/* Minimum rate */ | ||||
| 					    8, 7,	/* N */ | ||||
| 					    0, 4,	/* M */ | ||||
| 					    BIT(24),	/* frac enable */ | ||||
| 					    BIT(25),	/* frac select */ | ||||
| 					    270000000,	/* frac rate 0 */ | ||||
| 					    297000000,	/* frac rate 1 */ | ||||
| 					    BIT(31),	/* gate */ | ||||
| 					    BIT(28),	/* lock */ | ||||
| 					    CLK_SET_RATE_UNGATE); | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video_clk, "pll-video", | ||||
| 						"osc24M", 0x0010, | ||||
| 						192000000, /* Minimum rate */ | ||||
| 						912000000, /* Maximum rate */ | ||||
| 						8, 7,      /* N */ | ||||
| 						0, 4,	   /* M */ | ||||
| 						BIT(24),   /* frac enable */ | ||||
| 						BIT(25),   /* frac select */ | ||||
| 						270000000, /* frac rate 0 */ | ||||
| 						297000000, /* frac rate 1 */ | ||||
| 						BIT(31),   /* gate */ | ||||
| 						BIT(28),   /* lock */ | ||||
| 						CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", | ||||
| 					"osc24M", 0x0018, | ||||
|  |  | |||
|  | @ -65,19 +65,19 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", | |||
| 				   BIT(28),	/* lock */ | ||||
| 				   CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0", | ||||
| 					    "osc24M", 0x0010, | ||||
| 					    192000000,	/* Minimum rate */ | ||||
| 					    8, 7,	/* N */ | ||||
| 					    0, 4,	/* M */ | ||||
| 					    BIT(24),	/* frac enable */ | ||||
| 					    BIT(25),	/* frac select */ | ||||
| 					    270000000,	/* frac rate 0 */ | ||||
| 					    297000000,	/* frac rate 1 */ | ||||
| 					    BIT(31),	/* gate */ | ||||
| 					    BIT(28),	/* lock */ | ||||
| 					    CLK_SET_RATE_UNGATE); | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0", | ||||
| 						"osc24M", 0x0010, | ||||
| 						192000000,  /* Minimum rate */ | ||||
| 						1008000000, /* Maximum rate */ | ||||
| 						8, 7,       /* N */ | ||||
| 						0, 4,       /* M */ | ||||
| 						BIT(24),    /* frac enable */ | ||||
| 						BIT(25),    /* frac select */ | ||||
| 						270000000,  /* frac rate 0 */ | ||||
| 						297000000,  /* frac rate 1 */ | ||||
| 						BIT(31),    /* gate */ | ||||
| 						BIT(28),    /* lock */ | ||||
| 						CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", | ||||
|  | @ -152,19 +152,19 @@ static struct ccu_nk pll_periph1_clk = { | |||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1", | ||||
| 					    "osc24M", 0x030, | ||||
| 					    192000000,	/* Minimum rate */ | ||||
| 					    8, 7,	/* N */ | ||||
| 					    0, 4,	/* M */ | ||||
| 					    BIT(24),	/* frac enable */ | ||||
| 					    BIT(25),	/* frac select */ | ||||
| 					    270000000,	/* frac rate 0 */ | ||||
| 					    297000000,	/* frac rate 1 */ | ||||
| 					    BIT(31),	/* gate */ | ||||
| 					    BIT(28),	/* lock */ | ||||
| 					    CLK_SET_RATE_UNGATE); | ||||
| static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1", | ||||
| 						"osc24M", 0x030, | ||||
| 						192000000,  /* Minimum rate */ | ||||
| 						1008000000, /* Maximum rate */ | ||||
| 						8, 7,       /* N */ | ||||
| 						0, 4,       /* M */ | ||||
| 						BIT(24),    /* frac enable */ | ||||
| 						BIT(25),    /* frac select */ | ||||
| 						270000000,  /* frac rate 0 */ | ||||
| 						297000000,  /* frac rate 1 */ | ||||
| 						BIT(31),    /* gate */ | ||||
| 						BIT(28),    /* lock */ | ||||
| 						CLK_SET_RATE_UNGATE); | ||||
| 
 | ||||
| static struct ccu_nkm pll_sata_clk = { | ||||
| 	.enable		= BIT(31), | ||||
|  |  | |||
|  | @ -137,6 +137,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 	if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||||
| 		rate *= nkmp->fixed_post_div; | ||||
| 
 | ||||
| 	if (nkmp->max_rate && rate > nkmp->max_rate) { | ||||
| 		rate = nkmp->max_rate; | ||||
| 		if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||||
| 			rate /= nkmp->fixed_post_div; | ||||
| 		return rate; | ||||
| 	} | ||||
| 
 | ||||
| 	_nkmp.min_n = nkmp->n.min ?: 1; | ||||
| 	_nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; | ||||
| 	_nkmp.min_k = nkmp->k.min ?: 1; | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ struct ccu_nkmp { | |||
| 	struct ccu_div_internal		p; | ||||
| 
 | ||||
| 	unsigned int		fixed_post_div; | ||||
| 	unsigned int		max_rate; | ||||
| 
 | ||||
| 	struct ccu_common	common; | ||||
| }; | ||||
|  |  | |||
|  | @ -124,6 +124,13 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 		return rate; | ||||
| 	} | ||||
| 
 | ||||
| 	if (nm->max_rate && rate > nm->max_rate) { | ||||
| 		rate = nm->max_rate; | ||||
| 		if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||||
| 			rate /= nm->fixed_post_div; | ||||
| 		return rate; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) { | ||||
| 		if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||||
| 			rate /= nm->fixed_post_div; | ||||
|  |  | |||
|  | @ -38,6 +38,7 @@ struct ccu_nm { | |||
| 
 | ||||
| 	unsigned int		fixed_post_div; | ||||
| 	unsigned int		min_rate; | ||||
| 	unsigned int		max_rate; | ||||
| 
 | ||||
| 	struct ccu_common	common; | ||||
| }; | ||||
|  | @ -115,6 +116,35 @@ struct ccu_nm { | |||
| 		},							\ | ||||
| 	} | ||||
| 
 | ||||
| #define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name,	\ | ||||
| 						 _parent, _reg,		\ | ||||
| 						 _min_rate, _max_rate,	\ | ||||
| 						 _nshift, _nwidth,	\ | ||||
| 						 _mshift, _mwidth,	\ | ||||
| 						 _frac_en, _frac_sel,	\ | ||||
| 						 _frac_rate_0,		\ | ||||
| 						 _frac_rate_1,		\ | ||||
| 						 _gate, _lock, _flags)	\ | ||||
| 	struct ccu_nm _struct = {					\ | ||||
| 		.enable		= _gate,				\ | ||||
| 		.lock		= _lock,				\ | ||||
| 		.n		= _SUNXI_CCU_MULT(_nshift, _nwidth),	\ | ||||
| 		.m		= _SUNXI_CCU_DIV(_mshift, _mwidth),	\ | ||||
| 		.frac		= _SUNXI_CCU_FRAC(_frac_en, _frac_sel,	\ | ||||
| 						  _frac_rate_0,		\ | ||||
| 						  _frac_rate_1),	\ | ||||
| 		.min_rate	= _min_rate,				\ | ||||
| 		.max_rate	= _max_rate,				\ | ||||
| 		.common		= {					\ | ||||
| 			.reg		= _reg,				\ | ||||
| 			.features	= CCU_FEATURE_FRACTIONAL,	\ | ||||
| 			.hw.init	= CLK_HW_INIT(_name,		\ | ||||
| 						      _parent,		\ | ||||
| 						      &ccu_nm_ops,	\ | ||||
| 						      _flags),		\ | ||||
| 		},							\ | ||||
| 	} | ||||
| 
 | ||||
| #define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg,	\ | ||||
| 				    _nshift, _nwidth,			\ | ||||
| 				    _mshift, _mwidth,			\ | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ | |||
| #ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_ | ||||
| #define _DT_BINDINGS_CLK_SUN50I_A64_H_ | ||||
| 
 | ||||
| #define CLK_PLL_VIDEO0		7 | ||||
| #define CLK_PLL_PERIPH0		11 | ||||
| 
 | ||||
| #define CLK_BUS_MIPI_DSI	28 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Stephen Boyd
						Stephen Boyd