clk: tegra: Introduce ability for SoC-specific reset control callbacks
authorMikko Perttunen <mikko.perttunen@kapsi.fi>
Wed, 20 May 2015 06:27:05 +0000 (09:27 +0300)
committerThierry Reding <treding@nvidia.com>
Thu, 16 Jul 2015 07:32:47 +0000 (09:32 +0200)
This patch allows SoC-specific CAR initialization routines to register
their own reset_assert and reset_deassert callbacks with the common Tegra
CAR code. If defined, the common code will call these callbacks when a
reset control with number >= num_periph_banks * 32 is attempted to be asserted
or deasserted respectively. Numbers greater than or equal to num_periph_banks * 32
are used to avoid clashes with low numbers that are automatically mapped to
standard CAR reset lines.

Each SoC with these special resets should specify the defined reset control
numbers in a device tree header file.

Signed-off-by: Mikko Perttunen <mikko.perttunen@kapsi.fi>
Acked-by: Michael Turquette <mturquette@linaro.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h

index 41cd87c67be6a009a8b5a138672e21f6a4c0c003..3290fd648d1e371eb928ae7a9ed538fa0a0caa3f 100644 (file)
@@ -49,7 +49,6 @@
 #define RST_DEVICES_L                  0x004
 #define RST_DEVICES_H                  0x008
 #define RST_DEVICES_U                  0x00C
-#define RST_DFLL_DVCO                  0x2F4
 #define RST_DEVICES_V                  0x358
 #define RST_DEVICES_W                  0x35C
 #define RST_DEVICES_X                  0x28C
@@ -79,6 +78,11 @@ static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
 
+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static unsigned int num_special_reset;
+
 static struct tegra_clk_periph_regs periph_regs[] = {
        [0] = {
                .enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +156,29 @@ static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
         */
        tegra_read_chipid();
 
-       writel_relaxed(BIT(id % 32),
-                       clk_base + periph_regs[id / 32].rst_set_reg);
+       if (id < periph_banks * 32) {
+               writel_relaxed(BIT(id % 32),
+                              clk_base + periph_regs[id / 32].rst_set_reg);
+               return 0;
+       } else if (id < periph_banks * 32 + num_special_reset) {
+               return special_reset_assert(id);
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 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);
+       if (id < periph_banks * 32) {
+               writel_relaxed(BIT(id % 32),
+                              clk_base + periph_regs[id / 32].rst_clr_reg);
+               return 0;
+       } else if (id < periph_banks * 32 + num_special_reset) {
+               return special_reset_deassert(id);
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +300,19 @@ void __init tegra_add_of_provider(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
        rst_ctlr.of_node = np;
-       rst_ctlr.nr_resets = periph_banks * 32;
+       rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
        reset_controller_register(&rst_ctlr);
 }
 
+void __init tegra_init_special_resets(unsigned int num,
+                                     int (*assert)(unsigned long),
+                                     int (*deassert)(unsigned long))
+{
+       num_special_reset = num;
+       special_reset_assert = assert;
+       special_reset_deassert = deassert;
+}
+
 void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 {
        int i;
index 75ddc8ff8bd4aff97d61ff9ae27095aa2ba0cf33..0621887e06f71604eb3193f36690fe28d8ff9124 100644 (file)
@@ -591,6 +591,9 @@ struct tegra_devclk {
        char            *con_id;
 };
 
+void tegra_init_special_resets(unsigned int num, int (*assert)(unsigned long),
+                              int (*deassert)(unsigned long));
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
                struct clk *clks[], int clk_max);