aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-03-25 15:22:24 -0400
committerStephen Warren <swarren@nvidia.com>2013-04-04 18:09:05 -0400
commit441f199a37cfd66c5dd8dd45490bd3ea6971117d (patch)
tree0f7570e7985ea2b62f558e43d33caef6efa7e989
parent82ce742140f32394cc5be75f1c98cdbbff284582 (diff)
clk: tegra: defer application of init table
The Tegra clock driver is initialized during the ARM machine descriptor's .init_irq() hook. It can't be initialized earlier, since dynamic memory usage is required. It can't be initialized later, since the .init_timer() hook needs the clocks initialized. However, at this time, udelay() doesn't work. The Tegra clock initialization table may enable some PLLs. Enabling a PLL may require usage of udelay(). Hence, this can't happen right when the clock driver is initialized. To solve this, separate the clock driver initialization from the clock table processing, so they can execute at separate times. Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/tegra.c3
-rw-r--r--drivers/clk/tegra/clk-tegra20.c7
-rw-r--r--drivers/clk/tegra/clk-tegra30.c7
-rw-r--r--drivers/clk/tegra/clk.c10
-rw-r--r--drivers/clk/tegra/clk.h3
-rw-r--r--include/linux/clk/tegra.h1
6 files changed, 29 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 84deeab23ee7..61749e2d8111 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -36,6 +36,7 @@
36#include <linux/slab.h> 36#include <linux/slab.h>
37#include <linux/sys_soc.h> 37#include <linux/sys_soc.h>
38#include <linux/usb/tegra_usb_phy.h> 38#include <linux/usb/tegra_usb_phy.h>
39#include <linux/clk/tegra.h>
39 40
40#include <asm/mach-types.h> 41#include <asm/mach-types.h>
41#include <asm/mach/arch.h> 42#include <asm/mach/arch.h>
@@ -87,6 +88,8 @@ static void __init tegra_dt_init(void)
87 struct soc_device *soc_dev; 88 struct soc_device *soc_dev;
88 struct device *parent = NULL; 89 struct device *parent = NULL;
89 90
91 tegra_clocks_apply_init_table();
92
90 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 93 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
91 if (!soc_dev_attr) 94 if (!soc_dev_attr)
92 goto out; 95 goto out;
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index a7dc0a937361..a15fb28197b5 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -1252,6 +1252,11 @@ static __initdata struct tegra_clk_init_table init_table[] = {
1252 {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */ 1252 {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */
1253}; 1253};
1254 1254
1255static void __init tegra20_clock_apply_init_table(void)
1256{
1257 tegra_init_from_table(init_table, clks, clk_max);
1258}
1259
1255/* 1260/*
1256 * Some clocks may be used by different drivers depending on the board 1261 * Some clocks may be used by different drivers depending on the board
1257 * configuration. List those here to register them twice in the clock lookup 1262 * configuration. List those here to register them twice in the clock lookup
@@ -1318,7 +1323,7 @@ void __init tegra20_clock_init(struct device_node *np)
1318 clk_data.clk_num = ARRAY_SIZE(clks); 1323 clk_data.clk_num = ARRAY_SIZE(clks);
1319 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 1324 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
1320 1325
1321 tegra_init_from_table(init_table, clks, clk_max); 1326 tegra_clk_apply_init_table = tegra20_clock_apply_init_table;
1322 1327
1323 tegra_cpu_car_ops = &tegra20_cpu_car_ops; 1328 tegra_cpu_car_ops = &tegra20_cpu_car_ops;
1324} 1329}
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 181a6eef5ce8..e0ee93c2db6c 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -1916,6 +1916,11 @@ static __initdata struct tegra_clk_init_table init_table[] = {
1916 {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ 1916 {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
1917}; 1917};
1918 1918
1919static void __init tegra30_clock_apply_init_table(void)
1920{
1921 tegra_init_from_table(init_table, clks, clk_max);
1922}
1923
1919/* 1924/*
1920 * Some clocks may be used by different drivers depending on the board 1925 * Some clocks may be used by different drivers depending on the board
1921 * configuration. List those here to register them twice in the clock lookup 1926 * configuration. List those here to register them twice in the clock lookup
@@ -1989,7 +1994,7 @@ void __init tegra30_clock_init(struct device_node *np)
1989 clk_data.clk_num = ARRAY_SIZE(clks); 1994 clk_data.clk_num = ARRAY_SIZE(clks);
1990 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 1995 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
1991 1996
1992 tegra_init_from_table(init_table, clks, clk_max); 1997 tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
1993 1998
1994 tegra_cpu_car_ops = &tegra30_cpu_car_ops; 1999 tegra_cpu_car_ops = &tegra30_cpu_car_ops;
1995} 2000}
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index a603b9af0ad3..4a61d15425dc 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -83,3 +83,13 @@ void __init tegra_clocks_init(void)
83{ 83{
84 of_clk_init(tegra_dt_clk_match); 84 of_clk_init(tegra_dt_clk_match);
85} 85}
86
87tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
88
89void __init tegra_clocks_apply_init_table(void)
90{
91 if (!tegra_clk_apply_init_table)
92 return;
93
94 tegra_clk_apply_init_table();
95}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index a09d7dcaf183..3c566e2d518a 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -510,4 +510,7 @@ void tegra30_clock_init(struct device_node *np);
510static inline void tegra30_clock_init(struct device_node *np) {} 510static inline void tegra30_clock_init(struct device_node *np) {}
511#endif /* CONFIG_ARCH_TEGRA_3x_SOC */ 511#endif /* CONFIG_ARCH_TEGRA_3x_SOC */
512 512
513typedef void (*tegra_clk_apply_init_table_func)(void);
514extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
515
513#endif /* TEGRA_CLK_H */ 516#endif /* TEGRA_CLK_H */
diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h
index 404d6f940872..642789baec74 100644
--- a/include/linux/clk/tegra.h
+++ b/include/linux/clk/tegra.h
@@ -123,5 +123,6 @@ static inline void tegra_cpu_clock_resume(void)
123void tegra_periph_reset_deassert(struct clk *c); 123void tegra_periph_reset_deassert(struct clk *c);
124void tegra_periph_reset_assert(struct clk *c); 124void tegra_periph_reset_assert(struct clk *c);
125void tegra_clocks_init(void); 125void tegra_clocks_init(void);
126void tegra_clocks_apply_init_table(void);
126 127
127#endif /* __LINUX_CLK_TEGRA_H_ */ 128#endif /* __LINUX_CLK_TEGRA_H_ */