diff options
Diffstat (limited to 'drivers/clk/meson/gxbb.c')
| -rw-r--r-- | drivers/clk/meson/gxbb.c | 118 | 
1 files changed, 75 insertions, 43 deletions
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 177fffb9ebef..86d3ae58e84c 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -7,7 +7,6 @@  #include <linux/clk.h>  #include <linux/clk-provider.h>  #include <linux/init.h> -#include <linux/of_address.h>  #include <linux/of_device.h>  #include <linux/mfd/syscon.h>  #include <linux/platform_device.h> @@ -971,28 +970,26 @@ static struct clk_regmap gxbb_cts_amclk_sel = {  		.mask = 0x3,  		.shift = 9,  		.table = (u32[]){ 1, 2, 3 }, +		.flags = CLK_MUX_ROUND_CLOSEST,  	},  	.hw.init = &(struct clk_init_data){  		.name = "cts_amclk_sel",  		.ops = &clk_regmap_mux_ops,  		.parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },  		.num_parents = 3, -		.flags = CLK_SET_RATE_PARENT,  	},  };  static struct clk_regmap gxbb_cts_amclk_div = { -	.data = &(struct meson_clk_audio_div_data){ -		.div = { -			.reg_off = HHI_AUD_CLK_CNTL, -			.shift   = 0, -			.width   = 8, -		}, +	.data = &(struct clk_regmap_div_data) { +		.offset = HHI_AUD_CLK_CNTL, +		.shift = 0, +		.width = 8,  		.flags = CLK_DIVIDER_ROUND_CLOSEST,  	},  	.hw.init = &(struct clk_init_data){  		.name = "cts_amclk_div", -		.ops = &meson_clk_audio_divider_ops, +		.ops = &clk_regmap_divider_ops,  		.parent_names = (const char *[]){ "cts_amclk_sel" },  		.num_parents = 1,  		.flags = CLK_SET_RATE_PARENT, @@ -1019,13 +1016,13 @@ static struct clk_regmap gxbb_cts_mclk_i958_sel = {  		.mask = 0x3,  		.shift = 25,  		.table = (u32[]){ 1, 2, 3 }, +		.flags = CLK_MUX_ROUND_CLOSEST,  	},  	.hw.init = &(struct clk_init_data) {  		.name = "cts_mclk_i958_sel",  		.ops = &clk_regmap_mux_ops,  		.parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },  		.num_parents = 3, -		.flags = CLK_SET_RATE_PARENT,  	},  }; @@ -1627,6 +1624,63 @@ static struct clk_regmap gxbb_vdec_hevc = {  	},  }; +static u32 mux_table_gen_clk[]	= { 0, 4, 5, 6, 7, 8, +				    9, 10, 11, 13, 14, }; +static const char * const gen_clk_parent_names[] = { +	"xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2", +	"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll", +}; + +static struct clk_regmap gxbb_gen_clk_sel = { +	.data = &(struct clk_regmap_mux_data){ +		.offset = HHI_GEN_CLK_CNTL, +		.mask = 0xf, +		.shift = 12, +		.table = mux_table_gen_clk, +	}, +	.hw.init = &(struct clk_init_data){ +		.name = "gen_clk_sel", +		.ops = &clk_regmap_mux_ops, +		/* +		 * bits 15:12 selects from 14 possible parents: +		 * xtal, [rtc_oscin_i], [sys_cpu_div16], [ddr_dpll_pt], +		 * vid_pll, vid2_pll (hevc), mpll0, mpll1, mpll2, fdiv4, +		 * fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll +		 */ +		.parent_names = gen_clk_parent_names, +		.num_parents = ARRAY_SIZE(gen_clk_parent_names), +	}, +}; + +static struct clk_regmap gxbb_gen_clk_div = { +	.data = &(struct clk_regmap_div_data){ +		.offset = HHI_GEN_CLK_CNTL, +		.shift = 0, +		.width = 11, +	}, +	.hw.init = &(struct clk_init_data){ +		.name = "gen_clk_div", +		.ops = &clk_regmap_divider_ops, +		.parent_names = (const char *[]){ "gen_clk_sel" }, +		.num_parents = 1, +		.flags = CLK_SET_RATE_PARENT, +	}, +}; + +static struct clk_regmap gxbb_gen_clk = { +	.data = &(struct clk_regmap_gate_data){ +		.offset = HHI_GEN_CLK_CNTL, +		.bit_idx = 7, +	}, +	.hw.init = &(struct clk_init_data){ +		.name = "gen_clk", +		.ops = &clk_regmap_gate_ops, +		.parent_names = (const char *[]){ "gen_clk_div" }, +		.num_parents = 1, +		.flags = CLK_SET_RATE_PARENT, +	}, +}; +  /* Everything Else (EE) domain gates */  static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);  static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); @@ -1876,6 +1930,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {  		[CLKID_VDEC_HEVC_SEL]	    = &gxbb_vdec_hevc_sel.hw,  		[CLKID_VDEC_HEVC_DIV]	    = &gxbb_vdec_hevc_div.hw,  		[CLKID_VDEC_HEVC]	    = &gxbb_vdec_hevc.hw, +		[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,  		[NR_CLKS]		    = NULL,  	},  	.num = NR_CLKS, @@ -2038,6 +2095,9 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {  		[CLKID_VDEC_HEVC_SEL]	    = &gxbb_vdec_hevc_sel.hw,  		[CLKID_VDEC_HEVC_DIV]	    = &gxbb_vdec_hevc_div.hw,  		[CLKID_VDEC_HEVC]	    = &gxbb_vdec_hevc.hw, +		[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,  		[NR_CLKS]		    = NULL,  	},  	.num = NR_CLKS, @@ -2202,6 +2262,9 @@ static struct clk_regmap *const gx_clk_regmaps[] = {  	&gxbb_vdec_hevc_sel,  	&gxbb_vdec_hevc_div,  	&gxbb_vdec_hevc, +	&gxbb_gen_clk_sel, +	&gxbb_gen_clk_div, +	&gxbb_gen_clk,  };  struct clkc_data { @@ -2228,17 +2291,9 @@ static const struct of_device_id clkc_match_table[] = {  	{},  }; -static const struct regmap_config clkc_regmap_config = { -	.reg_bits       = 32, -	.val_bits       = 32, -	.reg_stride     = 4, -}; -  static int gxbb_clkc_probe(struct platform_device *pdev)  {  	const struct clkc_data *clkc_data; -	struct resource *res; -	void __iomem *clk_base;  	struct regmap *map;  	int ret, i;  	struct device *dev = &pdev->dev; @@ -2250,31 +2305,8 @@ static int gxbb_clkc_probe(struct platform_device *pdev)  	/* Get the hhi system controller node if available */  	map = syscon_node_to_regmap(of_get_parent(dev->of_node));  	if (IS_ERR(map)) { -		dev_err(dev, -			"failed to get HHI regmap - Trying obsolete regs\n"); - -		/* -		 * FIXME: HHI registers should be accessed through -		 * the appropriate system controller. This is required because -		 * there is more than just clocks in this register space -		 * -		 * This fallback method is only provided temporarily until -		 * all the platform DTs are properly using the syscon node -		 */ -		res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -		if (!res) -			return -EINVAL; - -		clk_base = devm_ioremap(dev, res->start, resource_size(res)); -		if (!clk_base) { -			dev_err(dev, "Unable to map clk base\n"); -			return -ENXIO; -		} - -		map = devm_regmap_init_mmio(dev, clk_base, -					    &clkc_regmap_config); -		if (IS_ERR(map)) -			return PTR_ERR(map); +		dev_err(dev, "failed to get HHI regmap\n"); +		return PTR_ERR(map);  	}  	/* Populate regmap for the common regmap backed clocks */  |