aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-07-11 07:19:06 -0400
committerThierry Reding <treding@nvidia.com>2014-07-17 08:58:43 -0400
commit7232398abc6a7186e315425638c367d50c674718 (patch)
tree874b08603b104c3b42a07cb7c1402a8f3bcf5ec0 /arch/arm/mach-tegra
parent24fa5af81059af90c723bec6aacc3cd2b2809d14 (diff)
ARM: tegra: Convert PMC to a driver
This commit converts the PMC support code to a platform driver. Because the boot process needs to call into this driver very early, also set up a minimal environment via an early initcall. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/Makefile2
-rw-r--r--arch/arm/mach-tegra/board.h7
-rw-r--r--arch/arm/mach-tegra/platsmp.c2
-rw-r--r--arch/arm/mach-tegra/pm.c32
-rw-r--r--arch/arm/mach-tegra/pm.h10
-rw-r--r--arch/arm/mach-tegra/pmc.c414
-rw-r--r--arch/arm/mach-tegra/pmc.h49
-rw-r--r--arch/arm/mach-tegra/powergate.c516
-rw-r--r--arch/arm/mach-tegra/tegra.c7
9 files changed, 27 insertions, 1012 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index c303b55de22e..e48a74458c25 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -2,9 +2,7 @@ asflags-y += -march=armv7-a
2 2
3obj-y += io.o 3obj-y += io.o
4obj-y += irq.o 4obj-y += irq.o
5obj-y += pmc.o
6obj-y += flowctrl.o 5obj-y += flowctrl.o
7obj-y += powergate.o
8obj-y += pm.o 6obj-y += pm.o
9obj-y += reset.o 7obj-y += reset.o
10obj-y += reset-handler.o 8obj-y += reset-handler.o
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index bcf5dbf69d58..da90c89296b9 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -28,13 +28,6 @@
28void __init tegra_map_common_io(void); 28void __init tegra_map_common_io(void);
29void __init tegra_init_irq(void); 29void __init tegra_init_irq(void);
30 30
31int __init tegra_powergate_init(void);
32#if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
33int __init tegra_powergate_debugfs_init(void);
34#else
35static inline int tegra_powergate_debugfs_init(void) { return 0; }
36#endif
37
38void __init tegra_paz00_wifikill_init(void); 31void __init tegra_paz00_wifikill_init(void);
39 32
40#endif 33#endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 0466a145b500..b45086666648 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -22,6 +22,7 @@
22#include <linux/smp.h> 22#include <linux/smp.h>
23 23
24#include <soc/tegra/fuse.h> 24#include <soc/tegra/fuse.h>
25#include <soc/tegra/pmc.h>
25 26
26#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
27#include <asm/mach-types.h> 28#include <asm/mach-types.h>
@@ -31,7 +32,6 @@
31#include "common.h" 32#include "common.h"
32#include "flowctrl.h" 33#include "flowctrl.h"
33#include "iomap.h" 34#include "iomap.h"
34#include "pmc.h"
35#include "reset.h" 35#include "reset.h"
36 36
37static cpumask_t tegra_cpu_init_mask; 37static cpumask_t tegra_cpu_init_mask;
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 94db3b6664df..b0f48a3946fa 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -28,6 +28,8 @@
28#include <linux/suspend.h> 28#include <linux/suspend.h>
29 29
30#include <soc/tegra/fuse.h> 30#include <soc/tegra/fuse.h>
31#include <soc/tegra/pm.h>
32#include <soc/tegra/pmc.h>
31 33
32#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
33#include <asm/idmap.h> 35#include <asm/idmap.h>
@@ -38,7 +40,6 @@
38 40
39#include "flowctrl.h" 41#include "flowctrl.h"
40#include "iomap.h" 42#include "iomap.h"
41#include "pmc.h"
42#include "pm.h" 43#include "pm.h"
43#include "reset.h" 44#include "reset.h"
44#include "sleep.h" 45#include "sleep.h"
@@ -167,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
167 return 0; 168 return 0;
168} 169}
169 170
171static void tegra_pm_set(enum tegra_suspend_mode mode)
172{
173 u32 value;
174
175 switch (tegra_get_chip_id()) {
176 case TEGRA20:
177 case TEGRA30:
178 break;
179 default:
180 /* Turn off CRAIL */
181 value = flowctrl_read_cpu_csr(0);
182 value &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
183 value |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
184 flowctrl_write_cpu_csr(0, value);
185 break;
186 }
187
188 tegra_pmc_enter_suspend_mode(mode);
189}
190
170void tegra_idle_lp2_last(void) 191void tegra_idle_lp2_last(void)
171{ 192{
172 tegra_pmc_pm_set(TEGRA_SUSPEND_LP2); 193 tegra_pm_set(TEGRA_SUSPEND_LP2);
173 194
174 cpu_cluster_pm_enter(); 195 cpu_cluster_pm_enter();
175 suspend_cpu_complex(); 196 suspend_cpu_complex();
@@ -268,8 +289,6 @@ static bool tegra_sleep_core_init(void)
268 289
269static void tegra_suspend_enter_lp1(void) 290static void tegra_suspend_enter_lp1(void)
270{ 291{
271 tegra_pmc_suspend();
272
273 /* copy the reset vector & SDRAM shutdown code into IRAM */ 292 /* copy the reset vector & SDRAM shutdown code into IRAM */
274 memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), 293 memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
275 iram_save_size); 294 iram_save_size);
@@ -281,8 +300,6 @@ static void tegra_suspend_enter_lp1(void)
281 300
282static void tegra_suspend_exit_lp1(void) 301static void tegra_suspend_exit_lp1(void)
283{ 302{
284 tegra_pmc_resume();
285
286 /* restore IRAM */ 303 /* restore IRAM */
287 memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr, 304 memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
288 iram_save_size); 305 iram_save_size);
@@ -307,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state)
307 324
308 pr_info("Entering suspend state %s\n", lp_state[mode]); 325 pr_info("Entering suspend state %s\n", lp_state[mode]);
309 326
310 tegra_pmc_pm_set(mode); 327 tegra_pm_set(mode);
311 328
312 local_fiq_disable(); 329 local_fiq_disable();
313 330
@@ -355,7 +372,6 @@ void __init tegra_init_suspend(void)
355 return; 372 return;
356 373
357 tegra_tear_down_cpu_init(); 374 tegra_tear_down_cpu_init();
358 tegra_pmc_suspend_init();
359 375
360 if (mode >= TEGRA_SUSPEND_LP1) { 376 if (mode >= TEGRA_SUSPEND_LP1) {
361 if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) { 377 if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index f4a89698e5b0..83bc87583446 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -21,12 +21,11 @@
21#ifndef _MACH_TEGRA_PM_H_ 21#ifndef _MACH_TEGRA_PM_H_
22#define _MACH_TEGRA_PM_H_ 22#define _MACH_TEGRA_PM_H_
23 23
24#include "pmc.h"
25
26struct tegra_lp1_iram { 24struct tegra_lp1_iram {
27 void *start_addr; 25 void *start_addr;
28 void *end_addr; 26 void *end_addr;
29}; 27};
28
30extern struct tegra_lp1_iram tegra_lp1_iram; 29extern struct tegra_lp1_iram tegra_lp1_iram;
31extern void (*tegra_sleep_core_finish)(unsigned long v2p); 30extern void (*tegra_sleep_core_finish)(unsigned long v2p);
32 31
@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(void);
42extern void (*tegra_tear_down_cpu)(void); 41extern void (*tegra_tear_down_cpu)(void);
43 42
44#ifdef CONFIG_PM_SLEEP 43#ifdef CONFIG_PM_SLEEP
45enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
46 enum tegra_suspend_mode mode);
47void tegra_init_suspend(void); 44void tegra_init_suspend(void);
48#else 45#else
49static inline enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
50 enum tegra_suspend_mode mode)
51{
52 return TEGRA_SUSPEND_NONE;
53}
54static inline void tegra_init_suspend(void) {} 46static inline void tegra_init_suspend(void) {}
55#endif 47#endif
56 48
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
deleted file mode 100644
index 69df18090c8b..000000000000
--- a/arch/arm/mach-tegra/pmc.c
+++ /dev/null
@@ -1,414 +0,0 @@
1/*
2 * Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#include <linux/clk.h>
19#include <linux/io.h>
20#include <linux/kernel.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23
24#include <soc/tegra/fuse.h>
25#include <soc/tegra/powergate.h>
26
27#include "flowctrl.h"
28#include "pm.h"
29#include "pmc.h"
30#include "sleep.h"
31
32#define TEGRA_POWER_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */
33#define TEGRA_POWER_SYSCLK_OE (1 << 11) /* system clock enable */
34#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
35#define TEGRA_POWER_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
36#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
37
38#define PMC_CTRL 0x0
39#define PMC_CTRL_INTR_LOW (1 << 17)
40#define PMC_PWRGATE_TOGGLE 0x30
41#define PMC_PWRGATE_TOGGLE_START (1 << 8)
42#define PMC_REMOVE_CLAMPING 0x34
43#define PMC_PWRGATE_STATUS 0x38
44
45#define PMC_SCRATCH0 0x50
46#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
47#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
48#define PMC_SCRATCH0_MODE_RCM (1 << 1)
49#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
50 PMC_SCRATCH0_MODE_BOOTLOADER | \
51 PMC_SCRATCH0_MODE_RCM)
52
53#define PMC_CPUPWRGOOD_TIMER 0xc8
54#define PMC_CPUPWROFF_TIMER 0xcc
55
56static u8 tegra_cpu_domains[] = {
57 0xFF, /* not available for CPU0 */
58 TEGRA_POWERGATE_CPU1,
59 TEGRA_POWERGATE_CPU2,
60 TEGRA_POWERGATE_CPU3,
61};
62static DEFINE_SPINLOCK(tegra_powergate_lock);
63
64static void __iomem *tegra_pmc_base;
65static bool tegra_pmc_invert_interrupt;
66static struct clk *tegra_pclk;
67
68struct pmc_pm_data {
69 u32 cpu_good_time; /* CPU power good time in uS */
70 u32 cpu_off_time; /* CPU power off time in uS */
71 u32 core_osc_time; /* Core power good osc time in uS */
72 u32 core_pmu_time; /* Core power good pmu time in uS */
73 u32 core_off_time; /* Core power off time in uS */
74 bool corereq_high; /* Core power request active-high */
75 bool sysclkreq_high; /* System clock request active-high */
76 bool combined_req; /* Combined pwr req for CPU & Core */
77 bool cpu_pwr_good_en; /* CPU power good signal is enabled */
78 u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */
79 u32 lp0_vec_size; /* The size of LP0 warm boot code */
80 enum tegra_suspend_mode suspend_mode;
81};
82static struct pmc_pm_data pmc_pm_data;
83
84static inline u32 tegra_pmc_readl(u32 reg)
85{
86 return readl(tegra_pmc_base + reg);
87}
88
89static inline void tegra_pmc_writel(u32 val, u32 reg)
90{
91 writel(val, tegra_pmc_base + reg);
92}
93
94static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
95{
96 if (cpuid <= 0 || cpuid >= num_possible_cpus())
97 return -EINVAL;
98 return tegra_cpu_domains[cpuid];
99}
100
101static bool tegra_pmc_powergate_is_powered(int id)
102{
103 return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
104}
105
106static int tegra_pmc_powergate_set(int id, bool new_state)
107{
108 bool old_state;
109 unsigned long flags;
110
111 spin_lock_irqsave(&tegra_powergate_lock, flags);
112
113 old_state = tegra_pmc_powergate_is_powered(id);
114 WARN_ON(old_state == new_state);
115
116 tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
117
118 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
119
120 return 0;
121}
122
123static int tegra_pmc_powergate_remove_clamping(int id)
124{
125 u32 mask;
126
127 /*
128 * Tegra has a bug where PCIE and VDE clamping masks are
129 * swapped relatively to the partition ids.
130 */
131 if (id == TEGRA_POWERGATE_VDEC)
132 mask = (1 << TEGRA_POWERGATE_PCIE);
133 else if (id == TEGRA_POWERGATE_PCIE)
134 mask = (1 << TEGRA_POWERGATE_VDEC);
135 else
136 mask = (1 << id);
137
138 tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
139
140 return 0;
141}
142
143bool tegra_pmc_cpu_is_powered(int cpuid)
144{
145 int id;
146
147 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
148 if (id < 0)
149 return false;
150 return tegra_pmc_powergate_is_powered(id);
151}
152
153int tegra_pmc_cpu_power_on(int cpuid)
154{
155 int id;
156
157 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
158 if (id < 0)
159 return id;
160 return tegra_pmc_powergate_set(id, true);
161}
162
163int tegra_pmc_cpu_remove_clamping(int cpuid)
164{
165 int id;
166
167 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
168 if (id < 0)
169 return id;
170 return tegra_pmc_powergate_remove_clamping(id);
171}
172
173void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
174{
175 u32 val;
176
177 val = tegra_pmc_readl(PMC_SCRATCH0);
178 val &= ~PMC_SCRATCH0_MODE_MASK;
179
180 if (cmd) {
181 if (strcmp(cmd, "recovery") == 0)
182 val |= PMC_SCRATCH0_MODE_RECOVERY;
183
184 if (strcmp(cmd, "bootloader") == 0)
185 val |= PMC_SCRATCH0_MODE_BOOTLOADER;
186
187 if (strcmp(cmd, "forced-recovery") == 0)
188 val |= PMC_SCRATCH0_MODE_RCM;
189 }
190
191 tegra_pmc_writel(val, PMC_SCRATCH0);
192
193 val = tegra_pmc_readl(0);
194 val |= 0x10;
195 tegra_pmc_writel(val, 0);
196}
197
198#ifdef CONFIG_PM_SLEEP
199static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
200{
201 unsigned long long ticks;
202 unsigned long long pclk;
203 static unsigned long tegra_last_pclk;
204
205 if (WARN_ON_ONCE(rate <= 0))
206 pclk = 100000000;
207 else
208 pclk = rate;
209
210 if ((rate != tegra_last_pclk)) {
211 ticks = (us_on * pclk) + 999999ull;
212 do_div(ticks, 1000000);
213 tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
214
215 ticks = (us_off * pclk) + 999999ull;
216 do_div(ticks, 1000000);
217 tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
218 wmb();
219 }
220 tegra_last_pclk = pclk;
221}
222
223enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
224{
225 return pmc_pm_data.suspend_mode;
226}
227
228void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
229{
230 if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
231 return;
232
233 pmc_pm_data.suspend_mode = mode;
234}
235
236void tegra_pmc_suspend(void)
237{
238 tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
239}
240
241void tegra_pmc_resume(void)
242{
243 tegra_pmc_writel(0x0, PMC_SCRATCH41);
244}
245
246void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
247{
248 u32 reg, csr_reg;
249 unsigned long rate = 0;
250
251 reg = tegra_pmc_readl(PMC_CTRL);
252 reg |= TEGRA_POWER_CPU_PWRREQ_OE;
253 reg &= ~TEGRA_POWER_EFFECT_LP0;
254
255 switch (tegra_get_chip_id()) {
256 case TEGRA20:
257 case TEGRA30:
258 break;
259 default:
260 /* Turn off CRAIL */
261 csr_reg = flowctrl_read_cpu_csr(0);
262 csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
263 csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
264 flowctrl_write_cpu_csr(0, csr_reg);
265 break;
266 }
267
268 switch (mode) {
269 case TEGRA_SUSPEND_LP1:
270 rate = 32768;
271 break;
272 case TEGRA_SUSPEND_LP2:
273 rate = clk_get_rate(tegra_pclk);
274 break;
275 default:
276 break;
277 }
278
279 set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
280 rate);
281
282 tegra_pmc_writel(reg, PMC_CTRL);
283}
284
285void tegra_pmc_suspend_init(void)
286{
287 u32 reg;
288
289 /* Always enable CPU power request */
290 reg = tegra_pmc_readl(PMC_CTRL);
291 reg |= TEGRA_POWER_CPU_PWRREQ_OE;
292 tegra_pmc_writel(reg, PMC_CTRL);
293
294 reg = tegra_pmc_readl(PMC_CTRL);
295
296 if (!pmc_pm_data.sysclkreq_high)
297 reg |= TEGRA_POWER_SYSCLK_POLARITY;
298 else
299 reg &= ~TEGRA_POWER_SYSCLK_POLARITY;
300
301 /* configure the output polarity while the request is tristated */
302 tegra_pmc_writel(reg, PMC_CTRL);
303
304 /* now enable the request */
305 reg |= TEGRA_POWER_SYSCLK_OE;
306 tegra_pmc_writel(reg, PMC_CTRL);
307}
308#endif
309
310static const struct of_device_id matches[] __initconst = {
311 { .compatible = "nvidia,tegra124-pmc" },
312 { .compatible = "nvidia,tegra114-pmc" },
313 { .compatible = "nvidia,tegra30-pmc" },
314 { .compatible = "nvidia,tegra20-pmc" },
315 { }
316};
317
318void __init tegra_pmc_init_irq(void)
319{
320 struct device_node *np;
321 u32 val;
322
323 np = of_find_matching_node(NULL, matches);
324 BUG_ON(!np);
325
326 tegra_pmc_base = of_iomap(np, 0);
327
328 tegra_pmc_invert_interrupt = of_property_read_bool(np,
329 "nvidia,invert-interrupt");
330
331 val = tegra_pmc_readl(PMC_CTRL);
332 if (tegra_pmc_invert_interrupt)
333 val |= PMC_CTRL_INTR_LOW;
334 else
335 val &= ~PMC_CTRL_INTR_LOW;
336 tegra_pmc_writel(val, PMC_CTRL);
337}
338
339void __init tegra_pmc_init(void)
340{
341 struct device_node *np;
342 u32 prop;
343 enum tegra_suspend_mode suspend_mode;
344 u32 core_good_time[2] = {0, 0};
345 u32 lp0_vec[2] = {0, 0};
346
347 np = of_find_matching_node(NULL, matches);
348 BUG_ON(!np);
349
350 tegra_pclk = of_clk_get_by_name(np, "pclk");
351 WARN_ON(IS_ERR(tegra_pclk));
352
353 /* Grabbing the power management configurations */
354 if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
355 suspend_mode = TEGRA_SUSPEND_NONE;
356 } else {
357 switch (prop) {
358 case 0:
359 suspend_mode = TEGRA_SUSPEND_LP0;
360 break;
361 case 1:
362 suspend_mode = TEGRA_SUSPEND_LP1;
363 break;
364 case 2:
365 suspend_mode = TEGRA_SUSPEND_LP2;
366 break;
367 default:
368 suspend_mode = TEGRA_SUSPEND_NONE;
369 break;
370 }
371 }
372 suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
373
374 if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
375 suspend_mode = TEGRA_SUSPEND_NONE;
376 pmc_pm_data.cpu_good_time = prop;
377
378 if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
379 suspend_mode = TEGRA_SUSPEND_NONE;
380 pmc_pm_data.cpu_off_time = prop;
381
382 if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
383 core_good_time, ARRAY_SIZE(core_good_time)))
384 suspend_mode = TEGRA_SUSPEND_NONE;
385 pmc_pm_data.core_osc_time = core_good_time[0];
386 pmc_pm_data.core_pmu_time = core_good_time[1];
387
388 if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
389 &prop))
390 suspend_mode = TEGRA_SUSPEND_NONE;
391 pmc_pm_data.core_off_time = prop;
392
393 pmc_pm_data.corereq_high = of_property_read_bool(np,
394 "nvidia,core-power-req-active-high");
395
396 pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
397 "nvidia,sys-clock-req-active-high");
398
399 pmc_pm_data.combined_req = of_property_read_bool(np,
400 "nvidia,combined-power-req");
401
402 pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
403 "nvidia,cpu-pwr-good-en");
404
405 if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
406 ARRAY_SIZE(lp0_vec)))
407 if (suspend_mode == TEGRA_SUSPEND_LP0)
408 suspend_mode = TEGRA_SUSPEND_LP1;
409
410 pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
411 pmc_pm_data.lp0_vec_size = lp0_vec[1];
412
413 pmc_pm_data.suspend_mode = suspend_mode;
414}
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
deleted file mode 100644
index 59e19c344298..000000000000
--- a/arch/arm/mach-tegra/pmc.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/*
2 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#ifndef __MACH_TEGRA_PMC_H
19#define __MACH_TEGRA_PMC_H
20
21#include <linux/reboot.h>
22
23enum tegra_suspend_mode {
24 TEGRA_SUSPEND_NONE = 0,
25 TEGRA_SUSPEND_LP2, /* CPU voltage off */
26 TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
27 TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
28 TEGRA_MAX_SUSPEND_MODE,
29};
30
31#ifdef CONFIG_PM_SLEEP
32enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
33void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
34void tegra_pmc_suspend(void);
35void tegra_pmc_resume(void);
36void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
37void tegra_pmc_suspend_init(void);
38#endif
39
40bool tegra_pmc_cpu_is_powered(int cpuid);
41int tegra_pmc_cpu_power_on(int cpuid);
42int tegra_pmc_cpu_remove_clamping(int cpuid);
43
44void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
45
46void tegra_pmc_init_irq(void);
47void tegra_pmc_init(void);
48
49#endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
deleted file mode 100644
index 0a14b8638437..000000000000
--- a/arch/arm/mach-tegra/powergate.c
+++ /dev/null
@@ -1,516 +0,0 @@
1/*
2 * drivers/powergate/tegra-powergate.c
3 *
4 * Copyright (c) 2010 Google, Inc
5 *
6 * Author:
7 * Colin Cross <ccross@google.com>
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/clk.h>
21#include <linux/clk/tegra.h>
22#include <linux/debugfs.h>
23#include <linux/delay.h>
24#include <linux/err.h>
25#include <linux/export.h>
26#include <linux/init.h>
27#include <linux/io.h>
28#include <linux/kernel.h>
29#include <linux/reset.h>
30#include <linux/seq_file.h>
31#include <linux/spinlock.h>
32
33#include <soc/tegra/fuse.h>
34#include <soc/tegra/powergate.h>
35
36#include "iomap.h"
37
38#define DPD_SAMPLE 0x020
39#define DPD_SAMPLE_ENABLE (1 << 0)
40#define DPD_SAMPLE_DISABLE (0 << 0)
41
42#define PWRGATE_TOGGLE 0x30
43#define PWRGATE_TOGGLE_START (1 << 8)
44
45#define REMOVE_CLAMPING 0x34
46
47#define PWRGATE_STATUS 0x38
48
49#define IO_DPD_REQ 0x1b8
50#define IO_DPD_REQ_CODE_IDLE (0 << 30)
51#define IO_DPD_REQ_CODE_OFF (1 << 30)
52#define IO_DPD_REQ_CODE_ON (2 << 30)
53#define IO_DPD_REQ_CODE_MASK (3 << 30)
54
55#define IO_DPD_STATUS 0x1bc
56#define IO_DPD2_REQ 0x1c0
57#define IO_DPD2_STATUS 0x1c4
58#define SEL_DPD_TIM 0x1c8
59
60#define GPU_RG_CNTRL 0x2d4
61
62static int tegra_num_powerdomains;
63static int tegra_num_cpu_domains;
64static const u8 *tegra_cpu_domains;
65
66static const u8 tegra30_cpu_domains[] = {
67 TEGRA_POWERGATE_CPU,
68 TEGRA_POWERGATE_CPU1,
69 TEGRA_POWERGATE_CPU2,
70 TEGRA_POWERGATE_CPU3,
71};
72
73static const u8 tegra114_cpu_domains[] = {
74 TEGRA_POWERGATE_CPU0,
75 TEGRA_POWERGATE_CPU1,
76 TEGRA_POWERGATE_CPU2,
77 TEGRA_POWERGATE_CPU3,
78};
79
80static const u8 tegra124_cpu_domains[] = {
81 TEGRA_POWERGATE_CPU0,
82 TEGRA_POWERGATE_CPU1,
83 TEGRA_POWERGATE_CPU2,
84 TEGRA_POWERGATE_CPU3,
85};
86
87static DEFINE_SPINLOCK(tegra_powergate_lock);
88
89static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
90
91static u32 pmc_read(unsigned long reg)
92{
93 return readl(pmc + reg);
94}
95
96static void pmc_write(u32 val, unsigned long reg)
97{
98 writel(val, pmc + reg);
99}
100
101static int tegra_powergate_set(int id, bool new_state)
102{
103 bool status;
104 unsigned long flags;
105
106 spin_lock_irqsave(&tegra_powergate_lock, flags);
107
108 status = pmc_read(PWRGATE_STATUS) & (1 << id);
109
110 if (status == new_state) {
111 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
112 return 0;
113 }
114
115 pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
116
117 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
118
119 return 0;
120}
121
122int tegra_powergate_power_on(int id)
123{
124 if (id < 0 || id >= tegra_num_powerdomains)
125 return -EINVAL;
126
127 return tegra_powergate_set(id, true);
128}
129
130int tegra_powergate_power_off(int id)
131{
132 if (id < 0 || id >= tegra_num_powerdomains)
133 return -EINVAL;
134
135 return tegra_powergate_set(id, false);
136}
137EXPORT_SYMBOL(tegra_powergate_power_off);
138
139int tegra_powergate_is_powered(int id)
140{
141 u32 status;
142
143 if (id < 0 || id >= tegra_num_powerdomains)
144 return -EINVAL;
145
146 status = pmc_read(PWRGATE_STATUS) & (1 << id);
147 return !!status;
148}
149
150int tegra_powergate_remove_clamping(int id)
151{
152 u32 mask;
153
154 if (id < 0 || id >= tegra_num_powerdomains)
155 return -EINVAL;
156
157 /*
158 * The Tegra124 GPU has a separate register (with different semantics)
159 * to remove clamps.
160 */
161 if (tegra_get_chip_id() == TEGRA124) {
162 if (id == TEGRA_POWERGATE_3D) {
163 pmc_write(0, GPU_RG_CNTRL);
164 return 0;
165 }
166 }
167
168 /*
169 * Tegra 2 has a bug where PCIE and VDE clamping masks are
170 * swapped relatively to the partition ids
171 */
172 if (id == TEGRA_POWERGATE_VDEC)
173 mask = (1 << TEGRA_POWERGATE_PCIE);
174 else if (id == TEGRA_POWERGATE_PCIE)
175 mask = (1 << TEGRA_POWERGATE_VDEC);
176 else
177 mask = (1 << id);
178
179 pmc_write(mask, REMOVE_CLAMPING);
180
181 return 0;
182}
183EXPORT_SYMBOL(tegra_powergate_remove_clamping);
184
185/* Must be called with clk disabled, and returns with clk enabled */
186int tegra_powergate_sequence_power_up(int id, struct clk *clk,
187 struct reset_control *rst)
188{
189 int ret;
190
191 reset_control_assert(rst);
192
193 ret = tegra_powergate_power_on(id);
194 if (ret)
195 goto err_power;
196
197 ret = clk_prepare_enable(clk);
198 if (ret)
199 goto err_clk;
200
201 udelay(10);
202
203 ret = tegra_powergate_remove_clamping(id);
204 if (ret)
205 goto err_clamp;
206
207 udelay(10);
208 reset_control_deassert(rst);
209
210 return 0;
211
212err_clamp:
213 clk_disable_unprepare(clk);
214err_clk:
215 tegra_powergate_power_off(id);
216err_power:
217 return ret;
218}
219EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
220
221int tegra_cpu_powergate_id(int cpuid)
222{
223 if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
224 return tegra_cpu_domains[cpuid];
225
226 return -EINVAL;
227}
228
229int __init tegra_powergate_init(void)
230{
231 switch (tegra_get_chip_id()) {
232 case TEGRA20:
233 tegra_num_powerdomains = 7;
234 break;
235 case TEGRA30:
236 tegra_num_powerdomains = 14;
237 tegra_num_cpu_domains = 4;
238 tegra_cpu_domains = tegra30_cpu_domains;
239 break;
240 case TEGRA114:
241 tegra_num_powerdomains = 23;
242 tegra_num_cpu_domains = 4;
243 tegra_cpu_domains = tegra114_cpu_domains;
244 break;
245 case TEGRA124:
246 tegra_num_powerdomains = 25;
247 tegra_num_cpu_domains = 4;
248 tegra_cpu_domains = tegra124_cpu_domains;
249 break;
250 default:
251 /* Unknown Tegra variant. Disable powergating */
252 tegra_num_powerdomains = 0;
253 break;
254 }
255
256 return 0;
257}
258
259#ifdef CONFIG_DEBUG_FS
260
261static const char * const *powergate_name;
262
263static const char * const powergate_name_t20[] = {
264 [TEGRA_POWERGATE_CPU] = "cpu",
265 [TEGRA_POWERGATE_3D] = "3d",
266 [TEGRA_POWERGATE_VENC] = "venc",
267 [TEGRA_POWERGATE_VDEC] = "vdec",
268 [TEGRA_POWERGATE_PCIE] = "pcie",
269 [TEGRA_POWERGATE_L2] = "l2",
270 [TEGRA_POWERGATE_MPE] = "mpe",
271};
272
273static const char * const powergate_name_t30[] = {
274 [TEGRA_POWERGATE_CPU] = "cpu0",
275 [TEGRA_POWERGATE_3D] = "3d0",
276 [TEGRA_POWERGATE_VENC] = "venc",
277 [TEGRA_POWERGATE_VDEC] = "vdec",
278 [TEGRA_POWERGATE_PCIE] = "pcie",
279 [TEGRA_POWERGATE_L2] = "l2",
280 [TEGRA_POWERGATE_MPE] = "mpe",
281 [TEGRA_POWERGATE_HEG] = "heg",
282 [TEGRA_POWERGATE_SATA] = "sata",
283 [TEGRA_POWERGATE_CPU1] = "cpu1",
284 [TEGRA_POWERGATE_CPU2] = "cpu2",
285 [TEGRA_POWERGATE_CPU3] = "cpu3",
286 [TEGRA_POWERGATE_CELP] = "celp",
287 [TEGRA_POWERGATE_3D1] = "3d1",
288};
289
290static const char * const powergate_name_t114[] = {
291 [TEGRA_POWERGATE_CPU] = "crail",
292 [TEGRA_POWERGATE_3D] = "3d",
293 [TEGRA_POWERGATE_VENC] = "venc",
294 [TEGRA_POWERGATE_VDEC] = "vdec",
295 [TEGRA_POWERGATE_MPE] = "mpe",
296 [TEGRA_POWERGATE_HEG] = "heg",
297 [TEGRA_POWERGATE_CPU1] = "cpu1",
298 [TEGRA_POWERGATE_CPU2] = "cpu2",
299 [TEGRA_POWERGATE_CPU3] = "cpu3",
300 [TEGRA_POWERGATE_CELP] = "celp",
301 [TEGRA_POWERGATE_CPU0] = "cpu0",
302 [TEGRA_POWERGATE_C0NC] = "c0nc",
303 [TEGRA_POWERGATE_C1NC] = "c1nc",
304 [TEGRA_POWERGATE_DIS] = "dis",
305 [TEGRA_POWERGATE_DISB] = "disb",
306 [TEGRA_POWERGATE_XUSBA] = "xusba",
307 [TEGRA_POWERGATE_XUSBB] = "xusbb",
308 [TEGRA_POWERGATE_XUSBC] = "xusbc",
309};
310
311static const char * const powergate_name_t124[] = {
312 [TEGRA_POWERGATE_CPU] = "crail",
313 [TEGRA_POWERGATE_3D] = "3d",
314 [TEGRA_POWERGATE_VENC] = "venc",
315 [TEGRA_POWERGATE_PCIE] = "pcie",
316 [TEGRA_POWERGATE_VDEC] = "vdec",
317 [TEGRA_POWERGATE_L2] = "l2",
318 [TEGRA_POWERGATE_MPE] = "mpe",
319 [TEGRA_POWERGATE_HEG] = "heg",
320 [TEGRA_POWERGATE_SATA] = "sata",
321 [TEGRA_POWERGATE_CPU1] = "cpu1",
322 [TEGRA_POWERGATE_CPU2] = "cpu2",
323 [TEGRA_POWERGATE_CPU3] = "cpu3",
324 [TEGRA_POWERGATE_CELP] = "celp",
325 [TEGRA_POWERGATE_CPU0] = "cpu0",
326 [TEGRA_POWERGATE_C0NC] = "c0nc",
327 [TEGRA_POWERGATE_C1NC] = "c1nc",
328 [TEGRA_POWERGATE_SOR] = "sor",
329 [TEGRA_POWERGATE_DIS] = "dis",
330 [TEGRA_POWERGATE_DISB] = "disb",
331 [TEGRA_POWERGATE_XUSBA] = "xusba",
332 [TEGRA_POWERGATE_XUSBB] = "xusbb",
333 [TEGRA_POWERGATE_XUSBC] = "xusbc",
334 [TEGRA_POWERGATE_VIC] = "vic",
335 [TEGRA_POWERGATE_IRAM] = "iram",
336};
337
338static int powergate_show(struct seq_file *s, void *data)
339{
340 int i;
341
342 seq_printf(s, " powergate powered\n");
343 seq_printf(s, "------------------\n");
344
345 for (i = 0; i < tegra_num_powerdomains; i++) {
346 if (!powergate_name[i])
347 continue;
348
349 seq_printf(s, " %9s %7s\n", powergate_name[i],
350 tegra_powergate_is_powered(i) ? "yes" : "no");
351 }
352
353 return 0;
354}
355
356static int powergate_open(struct inode *inode, struct file *file)
357{
358 return single_open(file, powergate_show, inode->i_private);
359}
360
361static const struct file_operations powergate_fops = {
362 .open = powergate_open,
363 .read = seq_read,
364 .llseek = seq_lseek,
365 .release = single_release,
366};
367
368int __init tegra_powergate_debugfs_init(void)
369{
370 struct dentry *d;
371
372 switch (tegra_get_chip_id()) {
373 case TEGRA20:
374 powergate_name = powergate_name_t20;
375 break;
376 case TEGRA30:
377 powergate_name = powergate_name_t30;
378 break;
379 case TEGRA114:
380 powergate_name = powergate_name_t114;
381 break;
382 case TEGRA124:
383 powergate_name = powergate_name_t124;
384 break;
385 }
386
387 if (powergate_name) {
388 d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
389 &powergate_fops);
390 if (!d)
391 return -ENOMEM;
392 }
393
394 return 0;
395}
396
397#endif
398
399static int tegra_io_rail_prepare(int id, unsigned long *request,
400 unsigned long *status, unsigned int *bit)
401{
402 unsigned long rate, value;
403 struct clk *clk;
404
405 *bit = id % 32;
406
407 /*
408 * There are two sets of 30 bits to select IO rails, but bits 30 and
409 * 31 are control bits rather than IO rail selection bits.
410 */
411 if (id > 63 || *bit == 30 || *bit == 31)
412 return -EINVAL;
413
414 if (id < 32) {
415 *status = IO_DPD_STATUS;
416 *request = IO_DPD_REQ;
417 } else {
418 *status = IO_DPD2_STATUS;
419 *request = IO_DPD2_REQ;
420 }
421
422 clk = clk_get_sys(NULL, "pclk");
423 if (IS_ERR(clk))
424 return PTR_ERR(clk);
425
426 rate = clk_get_rate(clk);
427 clk_put(clk);
428
429 pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
430
431 /* must be at least 200 ns, in APB (PCLK) clock cycles */
432 value = DIV_ROUND_UP(1000000000, rate);
433 value = DIV_ROUND_UP(200, value);
434 pmc_write(value, SEL_DPD_TIM);
435
436 return 0;
437}
438
439static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
440 unsigned long val, unsigned long timeout)
441{
442 unsigned long value;
443
444 timeout = jiffies + msecs_to_jiffies(timeout);
445
446 while (time_after(timeout, jiffies)) {
447 value = pmc_read(offset);
448 if ((value & mask) == val)
449 return 0;
450
451 usleep_range(250, 1000);
452 }
453
454 return -ETIMEDOUT;
455}
456
457static void tegra_io_rail_unprepare(void)
458{
459 pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
460}
461
462int tegra_io_rail_power_on(int id)
463{
464 unsigned long request, status, value;
465 unsigned int bit, mask;
466 int err;
467
468 err = tegra_io_rail_prepare(id, &request, &status, &bit);
469 if (err < 0)
470 return err;
471
472 mask = 1 << bit;
473
474 value = pmc_read(request);
475 value |= mask;
476 value &= ~IO_DPD_REQ_CODE_MASK;
477 value |= IO_DPD_REQ_CODE_OFF;
478 pmc_write(value, request);
479
480 err = tegra_io_rail_poll(status, mask, 0, 250);
481 if (err < 0)
482 return err;
483
484 tegra_io_rail_unprepare();
485
486 return 0;
487}
488EXPORT_SYMBOL(tegra_io_rail_power_on);
489
490int tegra_io_rail_power_off(int id)
491{
492 unsigned long request, status, value;
493 unsigned int bit, mask;
494 int err;
495
496 err = tegra_io_rail_prepare(id, &request, &status, &bit);
497 if (err < 0)
498 return err;
499
500 mask = 1 << bit;
501
502 value = pmc_read(request);
503 value |= mask;
504 value &= ~IO_DPD_REQ_CODE_MASK;
505 value |= IO_DPD_REQ_CODE_ON;
506 pmc_write(value, request);
507
508 err = tegra_io_rail_poll(status, mask, mask, 250);
509 if (err < 0)
510 return err;
511
512 tegra_io_rail_unprepare();
513
514 return 0;
515}
516EXPORT_SYMBOL(tegra_io_rail_power_off);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index c9176db0b9c0..5ef5173dec83 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -36,6 +36,7 @@
36#include <linux/usb/tegra_usb_phy.h> 36#include <linux/usb/tegra_usb_phy.h>
37 37
38#include <soc/tegra/fuse.h> 38#include <soc/tegra/fuse.h>
39#include <soc/tegra/pmc.h>
39 40
40#include <asm/hardware/cache-l2x0.h> 41#include <asm/hardware/cache-l2x0.h>
41#include <asm/mach/arch.h> 42#include <asm/mach/arch.h>
@@ -49,7 +50,6 @@
49#include "cpuidle.h" 50#include "cpuidle.h"
50#include "iomap.h" 51#include "iomap.h"
51#include "irq.h" 52#include "irq.h"
52#include "pmc.h"
53#include "pm.h" 53#include "pm.h"
54#include "reset.h" 54#include "reset.h"
55#include "sleep.h" 55#include "sleep.h"
@@ -74,12 +74,10 @@ static void __init tegra_init_early(void)
74{ 74{
75 of_register_trusted_foundations(); 75 of_register_trusted_foundations();
76 tegra_cpu_reset_handler_init(); 76 tegra_cpu_reset_handler_init();
77 tegra_powergate_init();
78} 77}
79 78
80static void __init tegra_dt_init_irq(void) 79static void __init tegra_dt_init_irq(void)
81{ 80{
82 tegra_pmc_init_irq();
83 tegra_init_irq(); 81 tegra_init_irq();
84 irqchip_init(); 82 irqchip_init();
85 tegra_legacy_irq_syscore_init(); 83 tegra_legacy_irq_syscore_init();
@@ -91,8 +89,6 @@ static void __init tegra_dt_init(void)
91 struct soc_device *soc_dev; 89 struct soc_device *soc_dev;
92 struct device *parent = NULL; 90 struct device *parent = NULL;
93 91
94 tegra_pmc_init();
95
96 tegra_clocks_apply_init_table(); 92 tegra_clocks_apply_init_table();
97 93
98 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 94 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -142,7 +138,6 @@ static void __init tegra_dt_init_late(void)
142 138
143 tegra_init_suspend(); 139 tegra_init_suspend();
144 tegra_cpuidle_init(); 140 tegra_cpuidle_init();
145 tegra_powergate_debugfs_init();
146 141
147 for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) { 142 for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
148 if (of_machine_is_compatible(board_init_funcs[i].machine)) { 143 if (of_machine_is_compatible(board_init_funcs[i].machine)) {