Commit 7477a4dd authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Add some rtas calls, from John Rose

From: Anton Blanchard <anton@samba.org>

Added functions for 3 RTAS calls
	get-power-level
	get-sensor-state
	set-indicator
parent 9255d6af
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/udbg.h> #include <asm/udbg.h>
#include <asm/delay.h>
struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; struct flash_block_list_header rtas_firmware_flash_list = {0, 0};
...@@ -180,18 +181,18 @@ rtas_call(int token, int nargs, int nret, ...@@ -180,18 +181,18 @@ rtas_call(int token, int nargs, int nret,
} }
/* Given an RTAS status code of 990n compute the hinted delay of 10^n /* Given an RTAS status code of 990n compute the hinted delay of 10^n
* (last digit) milliseconds. For now we bound at n=3 (1 sec). * (last digit) milliseconds. For now we bound at n=5 (100 sec).
*/ */
unsigned int unsigned int
rtas_extended_busy_delay_time(int status) rtas_extended_busy_delay_time(int status)
{ {
int order = status - 9900; int order = status - 9900;
unsigned int ms; unsigned long ms;
if (order < 0) if (order < 0)
order = 0; /* RTC depends on this for -2 clock busy */ order = 0; /* RTC depends on this for -2 clock busy */
else if (order > 3) else if (order > 5)
order = 3; /* bound */ order = 5; /* bound */
/* Use microseconds for reasonable accuracy */ /* Use microseconds for reasonable accuracy */
for (ms = 1000; order > 0; order--) for (ms = 1000; order > 0; order--)
...@@ -199,6 +200,80 @@ rtas_extended_busy_delay_time(int status) ...@@ -199,6 +200,80 @@ rtas_extended_busy_delay_time(int status)
return ms / (1000000/HZ); /* round down is fine */ return ms / (1000000/HZ); /* round down is fine */
} }
int
rtas_get_power_level(int powerdomain, int *level)
{
int token = rtas_token("get-power-level");
long powerlevel;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return RTAS_UNKNOWN_OP;
while(1) {
rc = (int) rtas_call(token, 1, 2, &powerlevel, powerdomain);
if (rc == RTAS_BUSY)
udelay(1);
else
break;
}
*level = (int) powerlevel;
return rc;
}
int
rtas_get_sensor(int sensor, int index, int *state)
{
int token = rtas_token("get-sensor-state");
unsigned int wait_time;
long returned_state;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return RTAS_UNKNOWN_OP;
while (1) {
rc = (int) rtas_call(token, 2, 2, &returned_state, sensor,
index);
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;
}
*state = (int) returned_state;
return rc;
}
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 RTAS_UNKNOWN_OP;
while (1) {
rc = (int) rtas_call(token, 3, 1, NULL, indicator, index,
new_value);
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;
}
return rc;
}
#define FLASH_BLOCK_LIST_VERSION (1UL) #define FLASH_BLOCK_LIST_VERSION (1UL)
static void static void
rtas_flash_firmware(void) rtas_flash_firmware(void)
...@@ -315,3 +390,6 @@ EXPORT_SYMBOL(rtas_call); ...@@ -315,3 +390,6 @@ EXPORT_SYMBOL(rtas_call);
EXPORT_SYMBOL(rtas_data_buf); EXPORT_SYMBOL(rtas_data_buf);
EXPORT_SYMBOL(rtas_data_buf_lock); EXPORT_SYMBOL(rtas_data_buf_lock);
EXPORT_SYMBOL(rtas_extended_busy_delay_time); EXPORT_SYMBOL(rtas_extended_busy_delay_time);
EXPORT_SYMBOL(rtas_get_sensor);
EXPORT_SYMBOL(rtas_get_power_level);
EXPORT_SYMBOL(rtas_set_indicator);
...@@ -165,6 +165,9 @@ extern void call_rtas_display_status(char); ...@@ -165,6 +165,9 @@ extern void call_rtas_display_status(char);
extern void rtas_restart(char *cmd); extern void rtas_restart(char *cmd);
extern void rtas_power_off(void); extern void rtas_power_off(void);
extern void rtas_halt(void); extern void rtas_halt(void);
extern int rtas_get_sensor(int sensor, int index, int *state);
extern int rtas_get_power_level(int powerdomain, int *level);
extern int rtas_set_indicator(int indicator, int index, int new_value);
/* Given an RTAS status code of 9900..9905 compute the hinted delay */ /* Given an RTAS status code of 9900..9905 compute the hinted delay */
unsigned int rtas_extended_busy_delay_time(int status); unsigned int rtas_extended_busy_delay_time(int status);
...@@ -179,6 +182,10 @@ static inline int rtas_is_extended_busy(int status) ...@@ -179,6 +182,10 @@ static inline int rtas_is_extended_busy(int status)
* of holding the buffer for long. * of holding the buffer for long.
*/ */
#define RTAS_DATA_BUF_SIZE 1024 #define RTAS_DATA_BUF_SIZE 1024
#define RTAS_UNKNOWN_OP -1099 /* Return Status - Unknown RTAS Token */
#define RTAS_BUSY -2 /* RTAS Return Status - Busy */
extern spinlock_t rtas_data_buf_lock; extern spinlock_t rtas_data_buf_lock;
extern char rtas_data_buf[RTAS_DATA_BUF_SIZE]; extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment