aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-11-05 19:33:17 -0500
committerStephen Warren <swarren@nvidia.com>2013-12-11 18:42:48 -0500
commit6d5b988e7dc56bb97c39bdcbc006fadcd6ca371b (patch)
tree4d5b526c30909e2b6ab88a5048fdcdffa56a48e9
parente04214683aca5cf7bbb53ee9d16373a8dbfa4259 (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.c3
-rw-r--r--drivers/clk/tegra/clk-tegra124.c2
-rw-r--r--drivers/clk/tegra/clk-tegra20.c3
-rw-r--r--drivers/clk/tegra/clk-tegra30.c3
-rw-r--r--drivers/clk/tegra/clk.c50
-rw-r--r--drivers/clk/tegra/clk.h2
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
126static void __iomem *clk_base;
127
128static 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
146static 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
124struct tegra_clk_periph_regs *get_reg_bank(int clkid) 155struct 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
136struct clk ** __init tegra_clk_init(int num, int banks) 167struct 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
239static struct reset_control_ops rst_ops = {
240 .assert = tegra_clk_rst_assert,
241 .deassert = tegra_clk_rst_deassert,
242};
243
244static struct reset_controller_dev rst_ctlr = {
245 .ops = &rst_ops,
246 .owner = THIS_MODULE,
247 .of_reset_n_cells = 1,
248};
249
206void __init tegra_add_of_provider(struct device_node *np) 250void __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
225void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) 273void __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
599struct tegra_clk_periph_regs *get_reg_bank(int clkid); 599struct tegra_clk_periph_regs *get_reg_bank(int clkid);
600struct clk **tegra_clk_init(int num, int periph_banks); 600struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
601 601
602struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); 602struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
603 603