diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-11-05 19:33:17 -0500 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2013-12-11 18:42:48 -0500 |
commit | 6d5b988e7dc56bb97c39bdcbc006fadcd6ca371b (patch) | |
tree | 4d5b526c30909e2b6ab88a5048fdcdffa56a48e9 | |
parent | e04214683aca5cf7bbb53ee9d16373a8dbfa4259 (diff) |
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>
-rw-r--r-- | drivers/clk/tegra/clk-tegra114.c | 3 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra124.c | 2 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra20.c | 3 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra30.c | 3 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.c | 50 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 2 |
6 files changed, 57 insertions, 6 deletions
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 29b912582e3d..90d9d25f2228 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c | |||
@@ -1460,7 +1460,8 @@ static void __init tegra114_clock_init(struct device_node *np) | |||
1460 | return; | 1460 | return; |
1461 | } | 1461 | } |
1462 | 1462 | ||
1463 | clks = tegra_clk_init(TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_PERIPH_BANKS); | 1463 | clks = tegra_clk_init(clk_base, TEGRA114_CLK_CLK_MAX, |
1464 | TEGRA114_CLK_PERIPH_BANKS); | ||
1464 | if (!clks) | 1465 | if (!clks) |
1465 | return; | 1466 | return; |
1466 | 1467 | ||
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 0ef4485e9b0a..aff86b5bc745 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c | |||
@@ -1398,7 +1398,7 @@ static void __init tegra124_clock_init(struct device_node *np) | |||
1398 | return; | 1398 | return; |
1399 | } | 1399 | } |
1400 | 1400 | ||
1401 | clks = tegra_clk_init(TEGRA124_CLK_CLK_MAX, 6); | 1401 | clks = tegra_clk_init(clk_base, TEGRA124_CLK_CLK_MAX, 6); |
1402 | if (!clks) | 1402 | if (!clks) |
1403 | return; | 1403 | return; |
1404 | 1404 | ||
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index b3b7204acfe7..5a6a60d9443a 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c | |||
@@ -1109,7 +1109,8 @@ static void __init tegra20_clock_init(struct device_node *np) | |||
1109 | BUG(); | 1109 | BUG(); |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | clks = tegra_clk_init(TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_PERIPH_BANKS); | 1112 | clks = tegra_clk_init(clk_base, TEGRA20_CLK_CLK_MAX, |
1113 | TEGRA20_CLK_PERIPH_BANKS); | ||
1113 | if (!clks) | 1114 | if (!clks) |
1114 | return; | 1115 | return; |
1115 | 1116 | ||
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index dcb6843b3a89..2e47383418c8 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c | |||
@@ -1427,7 +1427,8 @@ static void __init tegra30_clock_init(struct device_node *np) | |||
1427 | BUG(); | 1427 | BUG(); |
1428 | } | 1428 | } |
1429 | 1429 | ||
1430 | clks = tegra_clk_init(TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_PERIPH_BANKS); | 1430 | clks = tegra_clk_init(clk_base, TEGRA30_CLK_CLK_MAX, |
1431 | TEGRA30_CLK_PERIPH_BANKS); | ||
1431 | if (!clks) | 1432 | if (!clks) |
1432 | return; | 1433 | return; |
1433 | 1434 | ||
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index a12a5f5107ec..c0a7d7723510 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/clk-provider.h> | 18 | #include <linux/clk-provider.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/clk/tegra.h> | 20 | #include <linux/clk/tegra.h> |
21 | #include <linux/reset-controller.h> | ||
22 | #include <linux/tegra-soc.h> | ||
21 | 23 | ||
22 | #include "clk.h" | 24 | #include "clk.h" |
23 | 25 | ||
@@ -121,6 +123,35 @@ static struct tegra_clk_periph_regs periph_regs[] = { | |||
121 | }, | 123 | }, |
122 | }; | 124 | }; |
123 | 125 | ||
126 | static void __iomem *clk_base; | ||
127 | |||
128 | static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev, | ||
129 | unsigned long id) | ||
130 | { | ||
131 | /* | ||
132 | * If peripheral is on the APB bus then we must read the APB bus to | ||
133 | * flush the write operation in apb bus. This will avoid peripheral | ||
134 | * access after disabling clock. Since the reset driver has no | ||
135 | * knowledge of which reset IDs represent which devices, simply do | ||
136 | * this all the time. | ||
137 | */ | ||
138 | tegra_read_chipid(); | ||
139 | |||
140 | writel_relaxed(BIT(id % 32), | ||
141 | clk_base + periph_regs[id / 32].rst_set_reg); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, | ||
147 | unsigned long id) | ||
148 | { | ||
149 | writel_relaxed(BIT(id % 32), | ||
150 | clk_base + periph_regs[id / 32].rst_clr_reg); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
124 | struct tegra_clk_periph_regs *get_reg_bank(int clkid) | 155 | struct tegra_clk_periph_regs *get_reg_bank(int clkid) |
125 | { | 156 | { |
126 | int reg_bank = clkid / 32; | 157 | int reg_bank = clkid / 32; |
@@ -133,8 +164,10 @@ struct tegra_clk_periph_regs *get_reg_bank(int clkid) | |||
133 | } | 164 | } |
134 | } | 165 | } |
135 | 166 | ||
136 | struct clk ** __init tegra_clk_init(int num, int banks) | 167 | struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks) |
137 | { | 168 | { |
169 | clk_base = regs; | ||
170 | |||
138 | if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) | 171 | if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) |
139 | return NULL; | 172 | return NULL; |
140 | 173 | ||
@@ -203,6 +236,17 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, | |||
203 | } | 236 | } |
204 | } | 237 | } |
205 | 238 | ||
239 | static struct reset_control_ops rst_ops = { | ||
240 | .assert = tegra_clk_rst_assert, | ||
241 | .deassert = tegra_clk_rst_deassert, | ||
242 | }; | ||
243 | |||
244 | static struct reset_controller_dev rst_ctlr = { | ||
245 | .ops = &rst_ops, | ||
246 | .owner = THIS_MODULE, | ||
247 | .of_reset_n_cells = 1, | ||
248 | }; | ||
249 | |||
206 | void __init tegra_add_of_provider(struct device_node *np) | 250 | void __init tegra_add_of_provider(struct device_node *np) |
207 | { | 251 | { |
208 | int i; | 252 | int i; |
@@ -220,6 +264,10 @@ void __init tegra_add_of_provider(struct device_node *np) | |||
220 | clk_data.clks = clks; | 264 | clk_data.clks = clks; |
221 | clk_data.clk_num = clk_num; | 265 | clk_data.clk_num = clk_num; |
222 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 266 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); |
267 | |||
268 | rst_ctlr.of_node = np; | ||
269 | rst_ctlr.nr_resets = clk_num * 32; | ||
270 | reset_controller_register(&rst_ctlr); | ||
223 | } | 271 | } |
224 | 272 | ||
225 | void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) | 273 | void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) |
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 40fb011233c0..07c62f997371 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -597,7 +597,7 @@ void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, | |||
597 | struct clk *clks[], int clk_max); | 597 | struct clk *clks[], int clk_max); |
598 | 598 | ||
599 | struct tegra_clk_periph_regs *get_reg_bank(int clkid); | 599 | struct tegra_clk_periph_regs *get_reg_bank(int clkid); |
600 | struct clk **tegra_clk_init(int num, int periph_banks); | 600 | struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); |
601 | 601 | ||
602 | struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); | 602 | struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); |
603 | 603 | ||