
[ppc64] Add some rtas calls, from John Rose

Added functions for 3 RTAS calls
	get-power-level
	get-sensor-state
	set-indicator


---

 arch/ppc64/kernel/rtas.c |   86 ++++++++++++++++++++++++++++++++++++++++++++---
 include/asm-ppc64/rtas.h |    7 +++
 2 files changed, 89 insertions(+), 4 deletions(-)

diff -puN arch/ppc64/kernel/rtas.c~ppc64-rtas_functions arch/ppc64/kernel/rtas.c
--- 25/arch/ppc64/kernel/rtas.c~ppc64-rtas_functions	2004-01-13 23:22:38.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/rtas.c	2004-01-13 23:22:38.000000000 -0800
@@ -28,6 +28,7 @@
 #include <asm/system.h>
 #include <asm/abs_addr.h>
 #include <asm/udbg.h>
+#include <asm/delay.h>
 
 struct flash_block_list_header rtas_firmware_flash_list = {0, 0};
 
@@ -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
- * (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
 rtas_extended_busy_delay_time(int status)
 {
 	int order = status - 9900;
-	unsigned int ms;
+	unsigned long ms;
 
 	if (order < 0)
 		order = 0;	/* RTC depends on this for -2 clock busy */
-	else if (order > 3)
-		order = 3;	/* bound */
+	else if (order > 5)
+		order = 5;	/* bound */
 
 	/* Use microseconds for reasonable accuracy */
 	for (ms = 1000; order > 0; order--)
@@ -199,6 +200,80 @@ rtas_extended_busy_delay_time(int status
 	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)
 static void
 rtas_flash_firmware(void)
@@ -315,3 +390,6 @@ 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_indicator);
diff -puN include/asm-ppc64/rtas.h~ppc64-rtas_functions include/asm-ppc64/rtas.h
--- 25/include/asm-ppc64/rtas.h~ppc64-rtas_functions	2004-01-13 23:22:38.000000000 -0800
+++ 25-akpm/include/asm-ppc64/rtas.h	2004-01-13 23:22:38.000000000 -0800
@@ -165,6 +165,9 @@ extern void call_rtas_display_status(cha
 extern void rtas_restart(char *cmd);
 extern void rtas_power_off(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 */
 unsigned int rtas_extended_busy_delay_time(int status);
@@ -179,6 +182,10 @@ static inline int rtas_is_extended_busy(
  * of holding the buffer for long.
  */
 #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 char rtas_data_buf[RTAS_DATA_BUF_SIZE];
 

_
