aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/rtas.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r--arch/powerpc/kernel/rtas.c119
1 files changed, 105 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 17dc79198515..4a4cb5598402 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -38,16 +38,19 @@
38struct rtas_t rtas = { 38struct rtas_t rtas = {
39 .lock = SPIN_LOCK_UNLOCKED 39 .lock = SPIN_LOCK_UNLOCKED
40}; 40};
41EXPORT_SYMBOL(rtas);
41 42
42struct rtas_suspend_me_data { 43struct rtas_suspend_me_data {
43 long waiting; 44 long waiting;
44 struct rtas_args *args; 45 struct rtas_args *args;
45}; 46};
46 47
47EXPORT_SYMBOL(rtas);
48
49DEFINE_SPINLOCK(rtas_data_buf_lock); 48DEFINE_SPINLOCK(rtas_data_buf_lock);
49EXPORT_SYMBOL(rtas_data_buf_lock);
50
50char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; 51char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
52EXPORT_SYMBOL(rtas_data_buf);
53
51unsigned long rtas_rmo_buf; 54unsigned long rtas_rmo_buf;
52 55
53/* 56/*
@@ -106,11 +109,71 @@ static void call_rtas_display_status_delay(char c)
106 } 109 }
107} 110}
108 111
109void __init udbg_init_rtas(void) 112void __init udbg_init_rtas_panel(void)
110{ 113{
111 udbg_putc = call_rtas_display_status_delay; 114 udbg_putc = call_rtas_display_status_delay;
112} 115}
113 116
117#ifdef CONFIG_UDBG_RTAS_CONSOLE
118
119/* If you think you're dying before early_init_dt_scan_rtas() does its
120 * work, you can hard code the token values for your firmware here and
121 * hardcode rtas.base/entry etc.
122 */
123static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE;
124static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE;
125
126static void udbg_rtascon_putc(char c)
127{
128 int tries;
129
130 if (!rtas.base)
131 return;
132
133 /* Add CRs before LFs */
134 if (c == '\n')
135 udbg_rtascon_putc('\r');
136
137 /* if there is more than one character to be displayed, wait a bit */
138 for (tries = 0; tries < 16; tries++) {
139 if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0)
140 break;
141 udelay(1000);
142 }
143}
144
145static int udbg_rtascon_getc_poll(void)
146{
147 int c;
148
149 if (!rtas.base)
150 return -1;
151
152 if (rtas_call(rtas_getchar_token, 0, 2, &c))
153 return -1;
154
155 return c;
156}
157
158static int udbg_rtascon_getc(void)
159{
160 int c;
161
162 while ((c = udbg_rtascon_getc_poll()) == -1)
163 ;
164
165 return c;
166}
167
168
169void __init udbg_init_rtas_console(void)
170{
171 udbg_putc = udbg_rtascon_putc;
172 udbg_getc = udbg_rtascon_getc;
173 udbg_getc_poll = udbg_rtascon_getc_poll;
174}
175#endif /* CONFIG_UDBG_RTAS_CONSOLE */
176
114void rtas_progress(char *s, unsigned short hex) 177void rtas_progress(char *s, unsigned short hex)
115{ 178{
116 struct device_node *root; 179 struct device_node *root;
@@ -236,6 +299,7 @@ int rtas_token(const char *service)
236 tokp = (int *) get_property(rtas.dev, service, NULL); 299 tokp = (int *) get_property(rtas.dev, service, NULL);
237 return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; 300 return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
238} 301}
302EXPORT_SYMBOL(rtas_token);
239 303
240#ifdef CONFIG_RTAS_ERROR_LOGGING 304#ifdef CONFIG_RTAS_ERROR_LOGGING
241/* 305/*
@@ -328,7 +392,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
328 char *buff_copy = NULL; 392 char *buff_copy = NULL;
329 int ret; 393 int ret;
330 394
331 if (token == RTAS_UNKNOWN_SERVICE) 395 if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
332 return -1; 396 return -1;
333 397
334 /* Gotta do something different here, use global lock for now... */ 398 /* Gotta do something different here, use global lock for now... */
@@ -369,6 +433,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
369 } 433 }
370 return ret; 434 return ret;
371} 435}
436EXPORT_SYMBOL(rtas_call);
372 437
373/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status 438/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status
374 * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. 439 * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
@@ -388,6 +453,7 @@ unsigned int rtas_busy_delay_time(int status)
388 453
389 return ms; 454 return ms;
390} 455}
456EXPORT_SYMBOL(rtas_busy_delay_time);
391 457
392/* For an RTAS busy status code, perform the hinted delay. */ 458/* For an RTAS busy status code, perform the hinted delay. */
393unsigned int rtas_busy_delay(int status) 459unsigned int rtas_busy_delay(int status)
@@ -401,6 +467,7 @@ unsigned int rtas_busy_delay(int status)
401 467
402 return ms; 468 return ms;
403} 469}
470EXPORT_SYMBOL(rtas_busy_delay);
404 471
405int rtas_error_rc(int rtas_rc) 472int rtas_error_rc(int rtas_rc)
406{ 473{
@@ -446,6 +513,7 @@ int rtas_get_power_level(int powerdomain, int *level)
446 return rtas_error_rc(rc); 513 return rtas_error_rc(rc);
447 return rc; 514 return rc;
448} 515}
516EXPORT_SYMBOL(rtas_get_power_level);
449 517
450int rtas_set_power_level(int powerdomain, int level, int *setlevel) 518int rtas_set_power_level(int powerdomain, int level, int *setlevel)
451{ 519{
@@ -463,6 +531,7 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel)
463 return rtas_error_rc(rc); 531 return rtas_error_rc(rc);
464 return rc; 532 return rc;
465} 533}
534EXPORT_SYMBOL(rtas_set_power_level);
466 535
467int rtas_get_sensor(int sensor, int index, int *state) 536int rtas_get_sensor(int sensor, int index, int *state)
468{ 537{
@@ -480,6 +549,7 @@ int rtas_get_sensor(int sensor, int index, int *state)
480 return rtas_error_rc(rc); 549 return rtas_error_rc(rc);
481 return rc; 550 return rc;
482} 551}
552EXPORT_SYMBOL(rtas_get_sensor);
483 553
484int rtas_set_indicator(int indicator, int index, int new_value) 554int rtas_set_indicator(int indicator, int index, int new_value)
485{ 555{
@@ -497,6 +567,7 @@ int rtas_set_indicator(int indicator, int index, int new_value)
497 return rtas_error_rc(rc); 567 return rtas_error_rc(rc);
498 return rc; 568 return rc;
499} 569}
570EXPORT_SYMBOL(rtas_set_indicator);
500 571
501void rtas_restart(char *cmd) 572void rtas_restart(char *cmd)
502{ 573{
@@ -791,14 +862,34 @@ void __init rtas_initialize(void)
791#endif 862#endif
792} 863}
793 864
865int __init early_init_dt_scan_rtas(unsigned long node,
866 const char *uname, int depth, void *data)
867{
868 u32 *basep, *entryp, *sizep;
794 869
795EXPORT_SYMBOL(rtas_token); 870 if (depth != 1 || strcmp(uname, "rtas") != 0)
796EXPORT_SYMBOL(rtas_call); 871 return 0;
797EXPORT_SYMBOL(rtas_data_buf); 872
798EXPORT_SYMBOL(rtas_data_buf_lock); 873 basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
799EXPORT_SYMBOL(rtas_busy_delay_time); 874 entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
800EXPORT_SYMBOL(rtas_busy_delay); 875 sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
801EXPORT_SYMBOL(rtas_get_sensor); 876
802EXPORT_SYMBOL(rtas_get_power_level); 877 if (basep && entryp && sizep) {
803EXPORT_SYMBOL(rtas_set_power_level); 878 rtas.base = *basep;
804EXPORT_SYMBOL(rtas_set_indicator); 879 rtas.entry = *entryp;
880 rtas.size = *sizep;
881 }
882
883#ifdef CONFIG_UDBG_RTAS_CONSOLE
884 basep = of_get_flat_dt_prop(node, "put-term-char", NULL);
885 if (basep)
886 rtas_putchar_token = *basep;
887
888 basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
889 if (basep)
890 rtas_getchar_token = *basep;
891#endif
892
893 /* break now */
894 return 1;
895}