clk: tegra: implement a reset driver
The Tegra CAR module implements both a clock and reset controller. So far, the driver exposes the clock feature via the common clock API and the reset feature using a custom API. This patch adds an implementation of the common reset framework API (include/linux/reset*.h). The legacy reset implementation will be removed once all drivers have been converted. Signed-off-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Thierry Reding <treding@nvidia.com> Acked-By: Peter De Schrijver <pdeschrijver@nvidia.com>
This commit is contained in:
		
							parent
							
								
									e04214683a
								
							
						
					
					
						commit
						6d5b988e7d
					
				| @ -1460,7 +1460,8 @@ static void __init tegra114_clock_init(struct device_node *np) | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	clks = tegra_clk_init(TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_PERIPH_BANKS); | ||||
| 	clks = tegra_clk_init(clk_base, TEGRA114_CLK_CLK_MAX, | ||||
| 				TEGRA114_CLK_PERIPH_BANKS); | ||||
| 	if (!clks) | ||||
| 		return; | ||||
| 
 | ||||
|  | ||||
| @ -1398,7 +1398,7 @@ static void __init tegra124_clock_init(struct device_node *np) | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	clks = tegra_clk_init(TEGRA124_CLK_CLK_MAX, 6); | ||||
| 	clks = tegra_clk_init(clk_base, TEGRA124_CLK_CLK_MAX, 6); | ||||
| 	if (!clks) | ||||
| 		return; | ||||
| 
 | ||||
|  | ||||
| @ -1109,7 +1109,8 @@ static void __init tegra20_clock_init(struct device_node *np) | ||||
| 		BUG(); | ||||
| 	} | ||||
| 
 | ||||
| 	clks = tegra_clk_init(TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_PERIPH_BANKS); | ||||
| 	clks = tegra_clk_init(clk_base, TEGRA20_CLK_CLK_MAX, | ||||
| 				TEGRA20_CLK_PERIPH_BANKS); | ||||
| 	if (!clks) | ||||
| 		return; | ||||
| 
 | ||||
|  | ||||
| @ -1427,7 +1427,8 @@ static void __init tegra30_clock_init(struct device_node *np) | ||||
| 		BUG(); | ||||
| 	} | ||||
| 
 | ||||
| 	clks = tegra_clk_init(TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_PERIPH_BANKS); | ||||
| 	clks = tegra_clk_init(clk_base, TEGRA30_CLK_CLK_MAX, | ||||
| 				TEGRA30_CLK_PERIPH_BANKS); | ||||
| 	if (!clks) | ||||
| 		return; | ||||
| 
 | ||||
|  | ||||
| @ -18,6 +18,8 @@ | ||||
| #include <linux/clk-provider.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/clk/tegra.h> | ||||
| #include <linux/reset-controller.h> | ||||
| #include <linux/tegra-soc.h> | ||||
| 
 | ||||
| #include "clk.h" | ||||
| 
 | ||||
| @ -121,6 +123,35 @@ static struct tegra_clk_periph_regs periph_regs[] = { | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static void __iomem *clk_base; | ||||
| 
 | ||||
| static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev, | ||||
| 		unsigned long id) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * If peripheral is on the APB bus then we must read the APB bus to | ||||
| 	 * flush the write operation in apb bus. This will avoid peripheral | ||||
| 	 * access after disabling clock. Since the reset driver has no | ||||
| 	 * knowledge of which reset IDs represent which devices, simply do | ||||
| 	 * this all the time. | ||||
| 	 */ | ||||
| 	tegra_read_chipid(); | ||||
| 
 | ||||
| 	writel_relaxed(BIT(id % 32), | ||||
| 			clk_base + periph_regs[id / 32].rst_set_reg); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, | ||||
| 		unsigned long id) | ||||
| { | ||||
| 	writel_relaxed(BIT(id % 32), | ||||
| 			clk_base + periph_regs[id / 32].rst_clr_reg); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| struct tegra_clk_periph_regs *get_reg_bank(int clkid) | ||||
| { | ||||
| 	int reg_bank = clkid / 32; | ||||
| @ -133,8 +164,10 @@ struct tegra_clk_periph_regs *get_reg_bank(int clkid) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct clk ** __init tegra_clk_init(int num, int banks) | ||||
| struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks) | ||||
| { | ||||
| 	clk_base = regs; | ||||
| 
 | ||||
| 	if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) | ||||
| 		return NULL; | ||||
| 
 | ||||
| @ -203,6 +236,17 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct reset_control_ops rst_ops = { | ||||
| 	.assert = tegra_clk_rst_assert, | ||||
| 	.deassert = tegra_clk_rst_deassert, | ||||
| }; | ||||
| 
 | ||||
| static struct reset_controller_dev rst_ctlr = { | ||||
| 	.ops = &rst_ops, | ||||
| 	.owner = THIS_MODULE, | ||||
| 	.of_reset_n_cells = 1, | ||||
| }; | ||||
| 
 | ||||
| void __init tegra_add_of_provider(struct device_node *np) | ||||
| { | ||||
| 	int i; | ||||
| @ -220,6 +264,10 @@ void __init tegra_add_of_provider(struct device_node *np) | ||||
| 	clk_data.clks = clks; | ||||
| 	clk_data.clk_num = clk_num; | ||||
| 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||||
| 
 | ||||
| 	rst_ctlr.of_node = np; | ||||
| 	rst_ctlr.nr_resets = clk_num * 32; | ||||
| 	reset_controller_register(&rst_ctlr); | ||||
| } | ||||
| 
 | ||||
| void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) | ||||
|  | ||||
| @ -597,7 +597,7 @@ void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, | ||||
| 		struct clk *clks[], int clk_max); | ||||
| 
 | ||||
| struct tegra_clk_periph_regs *get_reg_bank(int clkid); | ||||
| struct clk **tegra_clk_init(int num, int periph_banks); | ||||
| struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); | ||||
| 
 | ||||
| struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user