struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
};
-EXPORT_SYMBOL(rtas);
struct rtas_suspend_me_data {
long waiting;
struct rtas_args *args;
};
-DEFINE_SPINLOCK(rtas_data_buf_lock);
-EXPORT_SYMBOL(rtas_data_buf_lock);
+EXPORT_SYMBOL(rtas);
+DEFINE_SPINLOCK(rtas_data_buf_lock);
char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
-EXPORT_SYMBOL(rtas_data_buf);
-
unsigned long rtas_rmo_buf;
/*
}
}
-void __init udbg_init_rtas_panel(void)
+void __init udbg_init_rtas(void)
{
udbg_putc = call_rtas_display_status_delay;
}
-#ifdef CONFIG_UDBG_RTAS_CONSOLE
-
-/* If you think you're dying before early_init_dt_scan_rtas() does its
- * work, you can hard code the token values for your firmware here and
- * hardcode rtas.base/entry etc.
- */
-static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE;
-static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE;
-
-static void udbg_rtascon_putc(char c)
-{
- int tries;
-
- if (!rtas.base)
- return;
-
- /* Add CRs before LFs */
- if (c == '\n')
- udbg_rtascon_putc('\r');
-
- /* if there is more than one character to be displayed, wait a bit */
- for (tries = 0; tries < 16; tries++) {
- if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0)
- break;
- udelay(1000);
- }
-}
-
-static int udbg_rtascon_getc_poll(void)
-{
- int c;
-
- if (!rtas.base)
- return -1;
-
- if (rtas_call(rtas_getchar_token, 0, 2, &c))
- return -1;
-
- return c;
-}
-
-static int udbg_rtascon_getc(void)
-{
- int c;
-
- while ((c = udbg_rtascon_getc_poll()) == -1)
- ;
-
- return c;
-}
-
-
-void __init udbg_init_rtas_console(void)
-{
- udbg_putc = udbg_rtascon_putc;
- udbg_getc = udbg_rtascon_getc;
- udbg_getc_poll = udbg_rtascon_getc_poll;
-}
-#endif /* CONFIG_UDBG_RTAS_CONSOLE */
-
void rtas_progress(char *s, unsigned short hex)
{
struct device_node *root;
tokp = (int *) get_property(rtas.dev, service, NULL);
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
}
-EXPORT_SYMBOL(rtas_token);
#ifdef CONFIG_RTAS_ERROR_LOGGING
/*
char *buff_copy = NULL;
int ret;
- if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
+ if (token == RTAS_UNKNOWN_SERVICE)
return -1;
/* Gotta do something different here, use global lock for now... */
}
return ret;
}
-EXPORT_SYMBOL(rtas_call);
-/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status
- * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
+/* Given an RTAS status code of 990n compute the hinted delay of 10^n
+ * (last digit) milliseconds. For now we bound at n=5 (100 sec).
*/
-unsigned int rtas_busy_delay_time(int status)
+unsigned int rtas_extended_busy_delay_time(int status)
{
- int order;
- unsigned int ms = 0;
-
- if (status == RTAS_BUSY) {
- ms = 1;
- } else if (status >= 9900 && status <= 9905) {
- order = status - 9900;
- for (ms = 1; order > 0; order--)
- ms *= 10;
- }
-
- return ms;
-}
-EXPORT_SYMBOL(rtas_busy_delay_time);
+ int order = status - 9900;
+ unsigned long ms;
-/* For an RTAS busy status code, perform the hinted delay. */
-unsigned int rtas_busy_delay(int status)
-{
- unsigned int ms;
+ if (order < 0)
+ order = 0; /* RTC depends on this for -2 clock busy */
+ else if (order > 5)
+ order = 5; /* bound */
- might_sleep();
- ms = rtas_busy_delay_time(status);
- if (ms)
- msleep(ms);
+ /* Use microseconds for reasonable accuracy */
+ for (ms = 1; order > 0; order--)
+ ms *= 10;
- return ms;
+ return ms;
}
-EXPORT_SYMBOL(rtas_busy_delay);
int rtas_error_rc(int rtas_rc)
{
return rtas_error_rc(rc);
return rc;
}
-EXPORT_SYMBOL(rtas_get_power_level);
int rtas_set_power_level(int powerdomain, int level, int *setlevel)
{
int token = rtas_token("set-power-level");
+ unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return -ENOENT;
- do {
+ while (1) {
rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
- } while (rtas_busy_delay(rc));
+ if (rc == RTAS_BUSY)
+ udelay(1);
+ else if (rtas_is_extended_busy(rc)) {
+ wait_time = rtas_extended_busy_delay_time(rc);
+ udelay(wait_time * 1000);
+ } else
+ break;
+ }
if (rc < 0)
return rtas_error_rc(rc);
return rc;
}
-EXPORT_SYMBOL(rtas_set_power_level);
int rtas_get_sensor(int sensor, int index, int *state)
{
int token = rtas_token("get-sensor-state");
+ unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return -ENOENT;
- do {
+ while (1) {
rc = rtas_call(token, 2, 2, state, sensor, index);
- } while (rtas_busy_delay(rc));
+ if (rc == RTAS_BUSY)
+ udelay(1);
+ else if (rtas_is_extended_busy(rc)) {
+ wait_time = rtas_extended_busy_delay_time(rc);
+ udelay(wait_time * 1000);
+ } else
+ break;
+ }
if (rc < 0)
return rtas_error_rc(rc);
return rc;
}
-EXPORT_SYMBOL(rtas_get_sensor);
int rtas_set_indicator(int indicator, int index, int new_value)
{
int token = rtas_token("set-indicator");
+ unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return -ENOENT;
- do {
+ while (1) {
rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
- } while (rtas_busy_delay(rc));
-
- if (rc < 0)
- return rtas_error_rc(rc);
- return rc;
-}
-EXPORT_SYMBOL(rtas_set_indicator);
-
-/*
- * Ignoring RTAS extended delay
- */
-int rtas_set_indicator_fast(int indicator, int index, int new_value)
-{
- int rc;
- int token = rtas_token("set-indicator");
-
- if (token == RTAS_UNKNOWN_SERVICE)
- return -ENOENT;
-
- rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
-
- WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905));
+ if (rc == RTAS_BUSY)
+ udelay(1);
+ else if (rtas_is_extended_busy(rc)) {
+ wait_time = rtas_extended_busy_delay_time(rc);
+ udelay(wait_time * 1000);
+ }
+ else
+ break;
+ }
if (rc < 0)
return rtas_error_rc(rc);
-
return rc;
}
do {
status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
__pa(rtas_os_term_buf));
- } while (rtas_busy_delay(status));
- if (status != 0)
- printk(KERN_EMERG "ibm,os-term call failed %d\n",
+ if (status == RTAS_BUSY)
+ udelay(1);
+ else if (status != 0)
+ printk(KERN_EMERG "ibm,os-term call failed %d\n",
status);
+ } while (status == RTAS_BUSY);
}
static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
static int rtas_ibm_suspend_me(struct rtas_args *args)
{
int i;
- long state;
- long rc;
- unsigned long dummy;
struct rtas_suspend_me_data data;
- /* Make sure the state is valid */
- rc = plpar_hcall(H_VASI_STATE,
- ((u64)args->args[0] << 32) | args->args[1],
- 0, 0, 0,
- &state, &dummy, &dummy);
-
- if (rc) {
- printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
- return rc;
- } else if (state == H_VASI_ENABLED) {
- args->args[args->nargs] = RTAS_NOT_SUSPENDABLE;
- return 0;
- } else if (state != H_VASI_SUSPENDING) {
- printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
- state);
- args->args[args->nargs] = -1;
- return 0;
- }
-
data.waiting = 1;
data.args = args;
#endif
}
-int __init early_init_dt_scan_rtas(unsigned long node,
- const char *uname, int depth, void *data)
-{
- u32 *basep, *entryp, *sizep;
-
- if (depth != 1 || strcmp(uname, "rtas") != 0)
- return 0;
-
- basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
- entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
- sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
-
- if (basep && entryp && sizep) {
- rtas.base = *basep;
- rtas.entry = *entryp;
- rtas.size = *sizep;
- }
-
-#ifdef CONFIG_UDBG_RTAS_CONSOLE
- basep = of_get_flat_dt_prop(node, "put-term-char", NULL);
- if (basep)
- rtas_putchar_token = *basep;
-
- basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
- if (basep)
- rtas_getchar_token = *basep;
-#endif
- /* break now */
- return 1;
-}
+EXPORT_SYMBOL(rtas_token);
+EXPORT_SYMBOL(rtas_call);
+EXPORT_SYMBOL(rtas_data_buf);
+EXPORT_SYMBOL(rtas_data_buf_lock);
+EXPORT_SYMBOL(rtas_extended_busy_delay_time);
+EXPORT_SYMBOL(rtas_get_sensor);
+EXPORT_SYMBOL(rtas_get_power_level);
+EXPORT_SYMBOL(rtas_set_power_level);
+EXPORT_SYMBOL(rtas_set_indicator);