aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeoff Levand <geoffrey.levand@am.sony.com>2007-10-06 17:35:47 -0400
committerPaul Mackerras <paulus@samba.org>2007-10-09 07:01:59 -0400
commit7db19421a9b116a196845a1118729cf5988f1b57 (patch)
treea55e55e2506a1e21336d6b36d09652c774e4e206
parentd7b98e3dd87b4512462f6cdfe646a8e59673e62e (diff)
[POWERPC] PS3: Save os-area params to device tree
Add the PS3 os-area startup params to the device tree. This allows a second stage kernel loaded with kexec to use these values. Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c104
-rw-r--r--arch/powerpc/platforms/ps3/platform.h1
-rw-r--r--arch/powerpc/platforms/ps3/setup.c1
3 files changed, 104 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 473aee8580ce..e50a276fcf67 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -119,10 +119,65 @@ struct os_area_params {
119 */ 119 */
120 120
121struct saved_params { 121struct saved_params {
122 unsigned int valid;
122 s64 rtc_diff; 123 s64 rtc_diff;
123 unsigned int av_multi_out; 124 unsigned int av_multi_out;
124} static saved_params; 125} static saved_params;
125 126
127static struct property property_rtc_diff = {
128 .name = "linux,rtc_diff",
129 .length = sizeof(saved_params.rtc_diff),
130 .value = &saved_params.rtc_diff,
131};
132
133static struct property property_av_multi_out = {
134 .name = "linux,av_multi_out",
135 .length = sizeof(saved_params.av_multi_out),
136 .value = &saved_params.av_multi_out,
137};
138
139/**
140 * os_area_set_property - Add or overwrite a saved_params value to the device tree.
141 *
142 * Overwrites an existing property.
143 */
144
145static void os_area_set_property(struct device_node *node,
146 struct property *prop)
147{
148 int result;
149 struct property *tmp = of_find_property(node, prop->name, NULL);
150
151 if (tmp) {
152 pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
153 prom_remove_property(node, tmp);
154 }
155
156 result = prom_add_property(node, prop);
157
158 if (result)
159 pr_debug("%s:%d prom_set_property failed\n", __func__,
160 __LINE__);
161}
162
163/**
164 * os_area_get_property - Get a saved_params value from the device tree.
165 *
166 */
167
168static void __init os_area_get_property(struct device_node *node,
169 struct property *prop)
170{
171 const struct property *tmp = of_find_property(node, prop->name, NULL);
172
173 if (tmp) {
174 BUG_ON(prop->length != tmp->length);
175 memcpy(prop->value, tmp->value, prop->length);
176 } else
177 pr_debug("%s:%d not found %s\n", __func__, __LINE__,
178 prop->name);
179}
180
126#define dump_header(_a) _dump_header(_a, __func__, __LINE__) 181#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
127static void _dump_header(const struct os_area_header *h, const char *func, 182static void _dump_header(const struct os_area_header *h, const char *func,
128 int line) 183 int line)
@@ -196,8 +251,19 @@ static int __init verify_header(const struct os_area_header *header)
196 251
197static void os_area_queue_work_handler(struct work_struct *work) 252static void os_area_queue_work_handler(struct work_struct *work)
198{ 253{
254 struct device_node *node;
255
199 pr_debug(" -> %s:%d\n", __func__, __LINE__); 256 pr_debug(" -> %s:%d\n", __func__, __LINE__);
200 257
258 node = of_find_node_by_path("/");
259
260 if (node) {
261 os_area_set_property(node, &property_rtc_diff);
262 of_node_put(node);
263 } else
264 pr_debug("%s:%d of_find_node_by_path failed\n",
265 __func__, __LINE__);
266
201 pr_debug(" <- %s:%d\n", __func__, __LINE__); 267 pr_debug(" <- %s:%d\n", __func__, __LINE__);
202} 268}
203 269
@@ -244,6 +310,8 @@ void __init ps3_os_area_save_params(void)
244 result = verify_header(header); 310 result = verify_header(header);
245 311
246 if (result) { 312 if (result) {
313 /* Second stage kernels exit here. */
314
247 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); 315 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
248 dump_header(header); 316 dump_header(header);
249 return; 317 return;
@@ -254,6 +322,7 @@ void __init ps3_os_area_save_params(void)
254 322
255 saved_params.rtc_diff = params->rtc_diff; 323 saved_params.rtc_diff = params->rtc_diff;
256 saved_params.av_multi_out = params->av_multi_out; 324 saved_params.av_multi_out = params->av_multi_out;
325 saved_params.valid = 1;
257 326
258 memset(header, 0, sizeof(*header)); 327 memset(header, 0, sizeof(*header));
259 328
@@ -261,13 +330,44 @@ void __init ps3_os_area_save_params(void)
261} 330}
262 331
263/** 332/**
333 * ps3_os_area_init - Setup os area device tree properties as needed.
334 */
335
336void __init ps3_os_area_init(void)
337{
338 struct device_node *node;
339
340 pr_debug(" -> %s:%d\n", __func__, __LINE__);
341
342 node = of_find_node_by_path("/");
343
344 if (!saved_params.valid && node) {
345 /* Second stage kernels should have a dt entry. */
346 os_area_get_property(node, &property_rtc_diff);
347 os_area_get_property(node, &property_av_multi_out);
348 }
349
350 if(!saved_params.rtc_diff)
351 saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;
352
353 if (node) {
354 os_area_set_property(node, &property_rtc_diff);
355 os_area_set_property(node, &property_av_multi_out);
356 of_node_put(node);
357 } else
358 pr_debug("%s:%d of_find_node_by_path failed\n",
359 __func__, __LINE__);
360
361 pr_debug(" <- %s:%d\n", __func__, __LINE__);
362}
363
364/**
264 * ps3_os_area_get_rtc_diff - Returns the rtc diff value. 365 * ps3_os_area_get_rtc_diff - Returns the rtc diff value.
265 */ 366 */
266 367
267u64 ps3_os_area_get_rtc_diff(void) 368u64 ps3_os_area_get_rtc_diff(void)
268{ 369{
269 return saved_params.rtc_diff ? saved_params.rtc_diff 370 return saved_params.rtc_diff;
270 : SECONDS_FROM_1970_TO_2000;
271} 371}
272 372
273/** 373/**
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 6b4f4dd2d15a..01f0c9506e11 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -63,6 +63,7 @@ int ps3_set_rtc_time(struct rtc_time *time);
63/* os area */ 63/* os area */
64 64
65void __init ps3_os_area_save_params(void); 65void __init ps3_os_area_save_params(void);
66void __init ps3_os_area_init(void);
66u64 ps3_os_area_get_rtc_diff(void); 67u64 ps3_os_area_get_rtc_diff(void);
67void ps3_os_area_set_rtc_diff(u64 rtc_diff); 68void ps3_os_area_set_rtc_diff(u64 rtc_diff);
68 69
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index f0d5ec51ef17..5c2cbb08eb52 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -206,6 +206,7 @@ static void __init ps3_setup_arch(void)
206 prealloc_ps3flash_bounce_buffer(); 206 prealloc_ps3flash_bounce_buffer();
207 207
208 ppc_md.power_save = ps3_power_save; 208 ppc_md.power_save = ps3_power_save;
209 ps3_os_area_init();
209 210
210 DBG(" <- %s:%d\n", __func__, __LINE__); 211 DBG(" <- %s:%d\n", __func__, __LINE__);
211} 212}