1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2f4fcbbe9SPaul Mackerras /*
3f4fcbbe9SPaul Mackerras * Copyright (C) 2000 Tilmann Bitterberg
4f4fcbbe9SPaul Mackerras * (tilmann@bitterberg.de)
5f4fcbbe9SPaul Mackerras *
6f4fcbbe9SPaul Mackerras * RTAS (Runtime Abstraction Services) stuff
7f4fcbbe9SPaul Mackerras * Intention is to provide a clean user interface
8f4fcbbe9SPaul Mackerras * to use the RTAS.
9f4fcbbe9SPaul Mackerras *
10f4fcbbe9SPaul Mackerras * TODO:
11f4fcbbe9SPaul Mackerras * Split off a header file and maybe move it to a different
12f4fcbbe9SPaul Mackerras * location. Write Documentation on what the /proc/rtas/ entries
13f4fcbbe9SPaul Mackerras * actually do.
14f4fcbbe9SPaul Mackerras */
15f4fcbbe9SPaul Mackerras
16f4fcbbe9SPaul Mackerras #include <linux/errno.h>
17f4fcbbe9SPaul Mackerras #include <linux/sched.h>
18f4fcbbe9SPaul Mackerras #include <linux/proc_fs.h>
19f4fcbbe9SPaul Mackerras #include <linux/stat.h>
20f4fcbbe9SPaul Mackerras #include <linux/ctype.h>
21f4fcbbe9SPaul Mackerras #include <linux/time.h>
22f4fcbbe9SPaul Mackerras #include <linux/string.h>
23f4fcbbe9SPaul Mackerras #include <linux/init.h>
24f4fcbbe9SPaul Mackerras #include <linux/seq_file.h>
25f4fcbbe9SPaul Mackerras #include <linux/bitops.h>
26f4fcbbe9SPaul Mackerras #include <linux/rtc.h>
27e6f6390aSChristophe Leroy #include <linux/of.h>
28f4fcbbe9SPaul Mackerras
297c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
30f4fcbbe9SPaul Mackerras #include <asm/processor.h>
31f4fcbbe9SPaul Mackerras #include <asm/io.h>
32f4fcbbe9SPaul Mackerras #include <asm/rtas.h>
33f4fcbbe9SPaul Mackerras #include <asm/machdep.h> /* for ppc_md */
34f4fcbbe9SPaul Mackerras #include <asm/time.h>
35f4fcbbe9SPaul Mackerras
36f4fcbbe9SPaul Mackerras /* Token for Sensors */
37f4fcbbe9SPaul Mackerras #define KEY_SWITCH 0x0001
38f4fcbbe9SPaul Mackerras #define ENCLOSURE_SWITCH 0x0002
39f4fcbbe9SPaul Mackerras #define THERMAL_SENSOR 0x0003
40f4fcbbe9SPaul Mackerras #define LID_STATUS 0x0004
41f4fcbbe9SPaul Mackerras #define POWER_SOURCE 0x0005
42f4fcbbe9SPaul Mackerras #define BATTERY_VOLTAGE 0x0006
43f4fcbbe9SPaul Mackerras #define BATTERY_REMAINING 0x0007
44f4fcbbe9SPaul Mackerras #define BATTERY_PERCENTAGE 0x0008
45f4fcbbe9SPaul Mackerras #define EPOW_SENSOR 0x0009
46f4fcbbe9SPaul Mackerras #define BATTERY_CYCLESTATE 0x000a
47f4fcbbe9SPaul Mackerras #define BATTERY_CHARGING 0x000b
48f4fcbbe9SPaul Mackerras
49f4fcbbe9SPaul Mackerras /* IBM specific sensors */
50f4fcbbe9SPaul Mackerras #define IBM_SURVEILLANCE 0x2328 /* 9000 */
51f4fcbbe9SPaul Mackerras #define IBM_FANRPM 0x2329 /* 9001 */
52f4fcbbe9SPaul Mackerras #define IBM_VOLTAGE 0x232a /* 9002 */
53f4fcbbe9SPaul Mackerras #define IBM_DRCONNECTOR 0x232b /* 9003 */
54f4fcbbe9SPaul Mackerras #define IBM_POWERSUPPLY 0x232c /* 9004 */
55f4fcbbe9SPaul Mackerras
56f4fcbbe9SPaul Mackerras /* Status return values */
57f4fcbbe9SPaul Mackerras #define SENSOR_CRITICAL_HIGH 13
58f4fcbbe9SPaul Mackerras #define SENSOR_WARNING_HIGH 12
59f4fcbbe9SPaul Mackerras #define SENSOR_NORMAL 11
60f4fcbbe9SPaul Mackerras #define SENSOR_WARNING_LOW 10
61f4fcbbe9SPaul Mackerras #define SENSOR_CRITICAL_LOW 9
62f4fcbbe9SPaul Mackerras #define SENSOR_SUCCESS 0
63f4fcbbe9SPaul Mackerras #define SENSOR_HW_ERROR -1
64f4fcbbe9SPaul Mackerras #define SENSOR_BUSY -2
65f4fcbbe9SPaul Mackerras #define SENSOR_NOT_EXIST -3
66f4fcbbe9SPaul Mackerras #define SENSOR_DR_ENTITY -9000
67f4fcbbe9SPaul Mackerras
68f4fcbbe9SPaul Mackerras /* Location Codes */
69f4fcbbe9SPaul Mackerras #define LOC_SCSI_DEV_ADDR 'A'
70f4fcbbe9SPaul Mackerras #define LOC_SCSI_DEV_LOC 'B'
71f4fcbbe9SPaul Mackerras #define LOC_CPU 'C'
72f4fcbbe9SPaul Mackerras #define LOC_DISKETTE 'D'
73f4fcbbe9SPaul Mackerras #define LOC_ETHERNET 'E'
74f4fcbbe9SPaul Mackerras #define LOC_FAN 'F'
75f4fcbbe9SPaul Mackerras #define LOC_GRAPHICS 'G'
76f4fcbbe9SPaul Mackerras /* reserved / not used 'H' */
77f4fcbbe9SPaul Mackerras #define LOC_IO_ADAPTER 'I'
78f4fcbbe9SPaul Mackerras /* reserved / not used 'J' */
79f4fcbbe9SPaul Mackerras #define LOC_KEYBOARD 'K'
80f4fcbbe9SPaul Mackerras #define LOC_LCD 'L'
81f4fcbbe9SPaul Mackerras #define LOC_MEMORY 'M'
82f4fcbbe9SPaul Mackerras #define LOC_NV_MEMORY 'N'
83f4fcbbe9SPaul Mackerras #define LOC_MOUSE 'O'
84f4fcbbe9SPaul Mackerras #define LOC_PLANAR 'P'
85f4fcbbe9SPaul Mackerras #define LOC_OTHER_IO 'Q'
86f4fcbbe9SPaul Mackerras #define LOC_PARALLEL 'R'
87f4fcbbe9SPaul Mackerras #define LOC_SERIAL 'S'
88f4fcbbe9SPaul Mackerras #define LOC_DEAD_RING 'T'
89f4fcbbe9SPaul Mackerras #define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */
90f4fcbbe9SPaul Mackerras #define LOC_VOLTAGE 'V'
91f4fcbbe9SPaul Mackerras #define LOC_SWITCH_ADAPTER 'W'
92f4fcbbe9SPaul Mackerras #define LOC_OTHER 'X'
93f4fcbbe9SPaul Mackerras #define LOC_FIRMWARE 'Y'
94f4fcbbe9SPaul Mackerras #define LOC_SCSI 'Z'
95f4fcbbe9SPaul Mackerras
96f4fcbbe9SPaul Mackerras /* Tokens for indicators */
97f4fcbbe9SPaul Mackerras #define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/
98f4fcbbe9SPaul Mackerras #define TONE_VOLUME 0x0002 /* 0 - 100 (%) */
99f4fcbbe9SPaul Mackerras #define SYSTEM_POWER_STATE 0x0003
100f4fcbbe9SPaul Mackerras #define WARNING_LIGHT 0x0004
101f4fcbbe9SPaul Mackerras #define DISK_ACTIVITY_LIGHT 0x0005
102f4fcbbe9SPaul Mackerras #define HEX_DISPLAY_UNIT 0x0006
103f4fcbbe9SPaul Mackerras #define BATTERY_WARNING_TIME 0x0007
104f4fcbbe9SPaul Mackerras #define CONDITION_CYCLE_REQUEST 0x0008
105f4fcbbe9SPaul Mackerras #define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */
106f4fcbbe9SPaul Mackerras #define DR_ACTION 0x2329 /* 9001 */
107f4fcbbe9SPaul Mackerras #define DR_INDICATOR 0x232a /* 9002 */
108f4fcbbe9SPaul Mackerras /* 9003 - 9004: Vendor specific */
109f4fcbbe9SPaul Mackerras /* 9006 - 9999: Vendor specific */
110f4fcbbe9SPaul Mackerras
111f4fcbbe9SPaul Mackerras /* other */
112f4fcbbe9SPaul Mackerras #define MAX_SENSORS 17 /* I only know of 17 sensors */
113f4fcbbe9SPaul Mackerras #define MAX_LINELENGTH 256
114f4fcbbe9SPaul Mackerras #define SENSOR_PREFIX "ibm,sensor-"
115f4fcbbe9SPaul Mackerras #define cel_to_fahr(x) ((x*9/5)+32)
116f4fcbbe9SPaul Mackerras
117f4fcbbe9SPaul Mackerras struct individual_sensor {
118f4fcbbe9SPaul Mackerras unsigned int token;
119f4fcbbe9SPaul Mackerras unsigned int quant;
120f4fcbbe9SPaul Mackerras };
121f4fcbbe9SPaul Mackerras
122f4fcbbe9SPaul Mackerras struct rtas_sensors {
123f4fcbbe9SPaul Mackerras struct individual_sensor sensor[MAX_SENSORS];
124f4fcbbe9SPaul Mackerras unsigned int quant;
125f4fcbbe9SPaul Mackerras };
126f4fcbbe9SPaul Mackerras
127ecaf5fa0SAnton Blanchard /* Globals */
128ecaf5fa0SAnton Blanchard static struct rtas_sensors sensors;
129ecaf5fa0SAnton Blanchard static struct device_node *rtas_node = NULL;
130ecaf5fa0SAnton Blanchard static unsigned long power_on_time = 0; /* Save the time the user set */
131ecaf5fa0SAnton Blanchard static char progress_led[MAX_LINELENGTH];
132ecaf5fa0SAnton Blanchard
133ecaf5fa0SAnton Blanchard static unsigned long rtas_tone_frequency = 1000;
134ecaf5fa0SAnton Blanchard static unsigned long rtas_tone_volume = 0;
135ecaf5fa0SAnton Blanchard
136f4fcbbe9SPaul Mackerras /* ****************************************************************** */
137f4fcbbe9SPaul Mackerras /* Declarations */
138f4fcbbe9SPaul Mackerras static int ppc_rtas_sensors_show(struct seq_file *m, void *v);
139f4fcbbe9SPaul Mackerras static int ppc_rtas_clock_show(struct seq_file *m, void *v);
140f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_clock_write(struct file *file,
141f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos);
142f4fcbbe9SPaul Mackerras static int ppc_rtas_progress_show(struct seq_file *m, void *v);
143f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_progress_write(struct file *file,
144f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos);
145f4fcbbe9SPaul Mackerras static int ppc_rtas_poweron_show(struct seq_file *m, void *v);
146f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_poweron_write(struct file *file,
147f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos);
148f4fcbbe9SPaul Mackerras
149f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_tone_freq_write(struct file *file,
150f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos);
151f4fcbbe9SPaul Mackerras static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v);
152f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_tone_volume_write(struct file *file,
153f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos);
154f4fcbbe9SPaul Mackerras static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v);
155f4fcbbe9SPaul Mackerras static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v);
156f4fcbbe9SPaul Mackerras
poweron_open(struct inode * inode,struct file * file)157f4fcbbe9SPaul Mackerras static int poweron_open(struct inode *inode, struct file *file)
158f4fcbbe9SPaul Mackerras {
159f4fcbbe9SPaul Mackerras return single_open(file, ppc_rtas_poweron_show, NULL);
160f4fcbbe9SPaul Mackerras }
161f4fcbbe9SPaul Mackerras
16297a32539SAlexey Dobriyan static const struct proc_ops ppc_rtas_poweron_proc_ops = {
16397a32539SAlexey Dobriyan .proc_open = poweron_open,
16497a32539SAlexey Dobriyan .proc_read = seq_read,
16597a32539SAlexey Dobriyan .proc_lseek = seq_lseek,
16697a32539SAlexey Dobriyan .proc_write = ppc_rtas_poweron_write,
16797a32539SAlexey Dobriyan .proc_release = single_release,
168f4fcbbe9SPaul Mackerras };
169f4fcbbe9SPaul Mackerras
progress_open(struct inode * inode,struct file * file)170f4fcbbe9SPaul Mackerras static int progress_open(struct inode *inode, struct file *file)
171f4fcbbe9SPaul Mackerras {
172f4fcbbe9SPaul Mackerras return single_open(file, ppc_rtas_progress_show, NULL);
173f4fcbbe9SPaul Mackerras }
174f4fcbbe9SPaul Mackerras
17597a32539SAlexey Dobriyan static const struct proc_ops ppc_rtas_progress_proc_ops = {
17697a32539SAlexey Dobriyan .proc_open = progress_open,
17797a32539SAlexey Dobriyan .proc_read = seq_read,
17897a32539SAlexey Dobriyan .proc_lseek = seq_lseek,
17997a32539SAlexey Dobriyan .proc_write = ppc_rtas_progress_write,
18097a32539SAlexey Dobriyan .proc_release = single_release,
181f4fcbbe9SPaul Mackerras };
182f4fcbbe9SPaul Mackerras
clock_open(struct inode * inode,struct file * file)183f4fcbbe9SPaul Mackerras static int clock_open(struct inode *inode, struct file *file)
184f4fcbbe9SPaul Mackerras {
185f4fcbbe9SPaul Mackerras return single_open(file, ppc_rtas_clock_show, NULL);
186f4fcbbe9SPaul Mackerras }
187f4fcbbe9SPaul Mackerras
18897a32539SAlexey Dobriyan static const struct proc_ops ppc_rtas_clock_proc_ops = {
18997a32539SAlexey Dobriyan .proc_open = clock_open,
19097a32539SAlexey Dobriyan .proc_read = seq_read,
19197a32539SAlexey Dobriyan .proc_lseek = seq_lseek,
19297a32539SAlexey Dobriyan .proc_write = ppc_rtas_clock_write,
19397a32539SAlexey Dobriyan .proc_release = single_release,
194f4fcbbe9SPaul Mackerras };
195f4fcbbe9SPaul Mackerras
tone_freq_open(struct inode * inode,struct file * file)196f4fcbbe9SPaul Mackerras static int tone_freq_open(struct inode *inode, struct file *file)
197f4fcbbe9SPaul Mackerras {
198f4fcbbe9SPaul Mackerras return single_open(file, ppc_rtas_tone_freq_show, NULL);
199f4fcbbe9SPaul Mackerras }
200f4fcbbe9SPaul Mackerras
20197a32539SAlexey Dobriyan static const struct proc_ops ppc_rtas_tone_freq_proc_ops = {
20297a32539SAlexey Dobriyan .proc_open = tone_freq_open,
20397a32539SAlexey Dobriyan .proc_read = seq_read,
20497a32539SAlexey Dobriyan .proc_lseek = seq_lseek,
20597a32539SAlexey Dobriyan .proc_write = ppc_rtas_tone_freq_write,
20697a32539SAlexey Dobriyan .proc_release = single_release,
207f4fcbbe9SPaul Mackerras };
208f4fcbbe9SPaul Mackerras
tone_volume_open(struct inode * inode,struct file * file)209f4fcbbe9SPaul Mackerras static int tone_volume_open(struct inode *inode, struct file *file)
210f4fcbbe9SPaul Mackerras {
211f4fcbbe9SPaul Mackerras return single_open(file, ppc_rtas_tone_volume_show, NULL);
212f4fcbbe9SPaul Mackerras }
213f4fcbbe9SPaul Mackerras
21497a32539SAlexey Dobriyan static const struct proc_ops ppc_rtas_tone_volume_proc_ops = {
21597a32539SAlexey Dobriyan .proc_open = tone_volume_open,
21697a32539SAlexey Dobriyan .proc_read = seq_read,
21797a32539SAlexey Dobriyan .proc_lseek = seq_lseek,
21897a32539SAlexey Dobriyan .proc_write = ppc_rtas_tone_volume_write,
21997a32539SAlexey Dobriyan .proc_release = single_release,
220f4fcbbe9SPaul Mackerras };
221f4fcbbe9SPaul Mackerras
222f4fcbbe9SPaul Mackerras static int ppc_rtas_find_all_sensors(void);
223f4fcbbe9SPaul Mackerras static void ppc_rtas_process_sensor(struct seq_file *m,
224a7f67bdfSJeremy Kerr struct individual_sensor *s, int state, int error, const char *loc);
225f4fcbbe9SPaul Mackerras static char *ppc_rtas_process_error(int error);
226f4fcbbe9SPaul Mackerras static void get_location_code(struct seq_file *m,
227a7f67bdfSJeremy Kerr struct individual_sensor *s, const char *loc);
228a7f67bdfSJeremy Kerr static void check_location_string(struct seq_file *m, const char *c);
229a7f67bdfSJeremy Kerr static void check_location(struct seq_file *m, const char *c);
230f4fcbbe9SPaul Mackerras
proc_rtas_init(void)231f4fcbbe9SPaul Mackerras static int __init proc_rtas_init(void)
232f4fcbbe9SPaul Mackerras {
233e8222502SBenjamin Herrenschmidt if (!machine_is(pseries))
23449c28e4eSAnton Blanchard return -ENODEV;
235f4fcbbe9SPaul Mackerras
236f4fcbbe9SPaul Mackerras rtas_node = of_find_node_by_name(NULL, "rtas");
237f4fcbbe9SPaul Mackerras if (rtas_node == NULL)
23849c28e4eSAnton Blanchard return -ENODEV;
239f4fcbbe9SPaul Mackerras
24057ad583fSRussell Currey proc_create("powerpc/rtas/progress", 0644, NULL,
24197a32539SAlexey Dobriyan &ppc_rtas_progress_proc_ops);
24257ad583fSRussell Currey proc_create("powerpc/rtas/clock", 0644, NULL,
24397a32539SAlexey Dobriyan &ppc_rtas_clock_proc_ops);
24457ad583fSRussell Currey proc_create("powerpc/rtas/poweron", 0644, NULL,
24597a32539SAlexey Dobriyan &ppc_rtas_poweron_proc_ops);
2463f3942acSChristoph Hellwig proc_create_single("powerpc/rtas/sensors", 0444, NULL,
2473f3942acSChristoph Hellwig ppc_rtas_sensors_show);
24857ad583fSRussell Currey proc_create("powerpc/rtas/frequency", 0644, NULL,
24997a32539SAlexey Dobriyan &ppc_rtas_tone_freq_proc_ops);
25057ad583fSRussell Currey proc_create("powerpc/rtas/volume", 0644, NULL,
25197a32539SAlexey Dobriyan &ppc_rtas_tone_volume_proc_ops);
2523f3942acSChristoph Hellwig proc_create_single("powerpc/rtas/rmo_buffer", 0400, NULL,
2533f3942acSChristoph Hellwig ppc_rtas_rmo_buf_show);
254f4fcbbe9SPaul Mackerras return 0;
255f4fcbbe9SPaul Mackerras }
256f4fcbbe9SPaul Mackerras
257f4fcbbe9SPaul Mackerras __initcall(proc_rtas_init);
258f4fcbbe9SPaul Mackerras
parse_number(const char __user * p,size_t count,u64 * val)2592dc20f45SArnd Bergmann static int parse_number(const char __user *p, size_t count, u64 *val)
260f4fcbbe9SPaul Mackerras {
261f4fcbbe9SPaul Mackerras char buf[40];
262f4fcbbe9SPaul Mackerras
263f4fcbbe9SPaul Mackerras if (count > 39)
264f4fcbbe9SPaul Mackerras return -EINVAL;
265f4fcbbe9SPaul Mackerras
266f4fcbbe9SPaul Mackerras if (copy_from_user(buf, p, count))
267f4fcbbe9SPaul Mackerras return -EFAULT;
268f4fcbbe9SPaul Mackerras
269f4fcbbe9SPaul Mackerras buf[count] = 0;
270f4fcbbe9SPaul Mackerras
27108d61b46SChen Huang return kstrtoull(buf, 10, val);
272f4fcbbe9SPaul Mackerras }
273f4fcbbe9SPaul Mackerras
274f4fcbbe9SPaul Mackerras /* ****************************************************************** */
275f4fcbbe9SPaul Mackerras /* POWER-ON-TIME */
276f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_poweron_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)277f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_poweron_write(struct file *file,
278f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos)
279f4fcbbe9SPaul Mackerras {
280f4fcbbe9SPaul Mackerras struct rtc_time tm;
2812dc20f45SArnd Bergmann time64_t nowtime;
282f4fcbbe9SPaul Mackerras int error = parse_number(buf, count, &nowtime);
283f4fcbbe9SPaul Mackerras if (error)
284f4fcbbe9SPaul Mackerras return error;
285f4fcbbe9SPaul Mackerras
286f4fcbbe9SPaul Mackerras power_on_time = nowtime; /* save the time */
287f4fcbbe9SPaul Mackerras
2882dc20f45SArnd Bergmann rtc_time64_to_tm(nowtime, &tm);
289f4fcbbe9SPaul Mackerras
290*08273c9fSNathan Lynch error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_FOR_POWER_ON), 7, 1, NULL,
2912dc20f45SArnd Bergmann tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
292f4fcbbe9SPaul Mackerras tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
293f4fcbbe9SPaul Mackerras if (error)
294f4fcbbe9SPaul Mackerras printk(KERN_WARNING "error: setting poweron time returned: %s\n",
295f4fcbbe9SPaul Mackerras ppc_rtas_process_error(error));
296f4fcbbe9SPaul Mackerras return count;
297f4fcbbe9SPaul Mackerras }
298f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_poweron_show(struct seq_file * m,void * v)299f4fcbbe9SPaul Mackerras static int ppc_rtas_poweron_show(struct seq_file *m, void *v)
300f4fcbbe9SPaul Mackerras {
301f4fcbbe9SPaul Mackerras if (power_on_time == 0)
302f4fcbbe9SPaul Mackerras seq_printf(m, "Power on time not set\n");
303f4fcbbe9SPaul Mackerras else
304f4fcbbe9SPaul Mackerras seq_printf(m, "%lu\n",power_on_time);
305f4fcbbe9SPaul Mackerras return 0;
306f4fcbbe9SPaul Mackerras }
307f4fcbbe9SPaul Mackerras
308f4fcbbe9SPaul Mackerras /* ****************************************************************** */
309f4fcbbe9SPaul Mackerras /* PROGRESS */
310f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_progress_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)311f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_progress_write(struct file *file,
312f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos)
313f4fcbbe9SPaul Mackerras {
314f4fcbbe9SPaul Mackerras unsigned long hex;
315f4fcbbe9SPaul Mackerras
316f4fcbbe9SPaul Mackerras if (count >= MAX_LINELENGTH)
317f4fcbbe9SPaul Mackerras count = MAX_LINELENGTH -1;
318f4fcbbe9SPaul Mackerras if (copy_from_user(progress_led, buf, count)) { /* save the string */
319f4fcbbe9SPaul Mackerras return -EFAULT;
320f4fcbbe9SPaul Mackerras }
321f4fcbbe9SPaul Mackerras progress_led[count] = 0;
322f4fcbbe9SPaul Mackerras
323f4fcbbe9SPaul Mackerras /* Lets see if the user passed hexdigits */
324f4fcbbe9SPaul Mackerras hex = simple_strtoul(progress_led, NULL, 10);
325f4fcbbe9SPaul Mackerras
326f4fcbbe9SPaul Mackerras rtas_progress ((char *)progress_led, hex);
327f4fcbbe9SPaul Mackerras return count;
328f4fcbbe9SPaul Mackerras
329f4fcbbe9SPaul Mackerras /* clear the line */
330f4fcbbe9SPaul Mackerras /* rtas_progress(" ", 0xffff);*/
331f4fcbbe9SPaul Mackerras }
332f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_progress_show(struct seq_file * m,void * v)333f4fcbbe9SPaul Mackerras static int ppc_rtas_progress_show(struct seq_file *m, void *v)
334f4fcbbe9SPaul Mackerras {
3359a6b5070SSegher Boessenkool if (progress_led[0])
336f4fcbbe9SPaul Mackerras seq_printf(m, "%s\n", progress_led);
337f4fcbbe9SPaul Mackerras return 0;
338f4fcbbe9SPaul Mackerras }
339f4fcbbe9SPaul Mackerras
340f4fcbbe9SPaul Mackerras /* ****************************************************************** */
341f4fcbbe9SPaul Mackerras /* CLOCK */
342f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_clock_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)343f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_clock_write(struct file *file,
344f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos)
345f4fcbbe9SPaul Mackerras {
346f4fcbbe9SPaul Mackerras struct rtc_time tm;
3472dc20f45SArnd Bergmann time64_t nowtime;
348f4fcbbe9SPaul Mackerras int error = parse_number(buf, count, &nowtime);
349f4fcbbe9SPaul Mackerras if (error)
350f4fcbbe9SPaul Mackerras return error;
351f4fcbbe9SPaul Mackerras
3522dc20f45SArnd Bergmann rtc_time64_to_tm(nowtime, &tm);
353*08273c9fSNathan Lynch error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_OF_DAY), 7, 1, NULL,
3542dc20f45SArnd Bergmann tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
355f4fcbbe9SPaul Mackerras tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
356f4fcbbe9SPaul Mackerras if (error)
357f4fcbbe9SPaul Mackerras printk(KERN_WARNING "error: setting the clock returned: %s\n",
358f4fcbbe9SPaul Mackerras ppc_rtas_process_error(error));
359f4fcbbe9SPaul Mackerras return count;
360f4fcbbe9SPaul Mackerras }
361f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_clock_show(struct seq_file * m,void * v)362f4fcbbe9SPaul Mackerras static int ppc_rtas_clock_show(struct seq_file *m, void *v)
363f4fcbbe9SPaul Mackerras {
364f4fcbbe9SPaul Mackerras int ret[8];
365*08273c9fSNathan Lynch int error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
366f4fcbbe9SPaul Mackerras
367f4fcbbe9SPaul Mackerras if (error) {
368f4fcbbe9SPaul Mackerras printk(KERN_WARNING "error: reading the clock returned: %s\n",
369f4fcbbe9SPaul Mackerras ppc_rtas_process_error(error));
370f4fcbbe9SPaul Mackerras seq_printf(m, "0");
371f4fcbbe9SPaul Mackerras } else {
372f4fcbbe9SPaul Mackerras unsigned int year, mon, day, hour, min, sec;
373f4fcbbe9SPaul Mackerras year = ret[0]; mon = ret[1]; day = ret[2];
374f4fcbbe9SPaul Mackerras hour = ret[3]; min = ret[4]; sec = ret[5];
3752dc20f45SArnd Bergmann seq_printf(m, "%lld\n",
3762dc20f45SArnd Bergmann mktime64(year, mon, day, hour, min, sec));
377f4fcbbe9SPaul Mackerras }
378f4fcbbe9SPaul Mackerras return 0;
379f4fcbbe9SPaul Mackerras }
380f4fcbbe9SPaul Mackerras
381f4fcbbe9SPaul Mackerras /* ****************************************************************** */
382f4fcbbe9SPaul Mackerras /* SENSOR STUFF */
383f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_sensors_show(struct seq_file * m,void * v)384f4fcbbe9SPaul Mackerras static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
385f4fcbbe9SPaul Mackerras {
386f4fcbbe9SPaul Mackerras int i,j;
387f4fcbbe9SPaul Mackerras int state, error;
388*08273c9fSNathan Lynch int get_sensor_state = rtas_function_token(RTAS_FN_GET_SENSOR_STATE);
389f4fcbbe9SPaul Mackerras
390f4fcbbe9SPaul Mackerras seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n");
391f4fcbbe9SPaul Mackerras seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n");
392f4fcbbe9SPaul Mackerras seq_printf(m, "********************************************************\n");
393f4fcbbe9SPaul Mackerras
394f4fcbbe9SPaul Mackerras if (ppc_rtas_find_all_sensors() != 0) {
395f4fcbbe9SPaul Mackerras seq_printf(m, "\nNo sensors are available\n");
396f4fcbbe9SPaul Mackerras return 0;
397f4fcbbe9SPaul Mackerras }
398f4fcbbe9SPaul Mackerras
399f4fcbbe9SPaul Mackerras for (i=0; i<sensors.quant; i++) {
400f4fcbbe9SPaul Mackerras struct individual_sensor *p = &sensors.sensor[i];
401f4fcbbe9SPaul Mackerras char rstr[64];
402a7f67bdfSJeremy Kerr const char *loc;
403f4fcbbe9SPaul Mackerras int llen, offs;
404f4fcbbe9SPaul Mackerras
405f4fcbbe9SPaul Mackerras sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
406e2eb6392SStephen Rothwell loc = of_get_property(rtas_node, rstr, &llen);
407f4fcbbe9SPaul Mackerras
408f4fcbbe9SPaul Mackerras /* A sensor may have multiple instances */
409f4fcbbe9SPaul Mackerras for (j = 0, offs = 0; j <= p->quant; j++) {
410f4fcbbe9SPaul Mackerras error = rtas_call(get_sensor_state, 2, 2, &state,
411f4fcbbe9SPaul Mackerras p->token, j);
412f4fcbbe9SPaul Mackerras
413f4fcbbe9SPaul Mackerras ppc_rtas_process_sensor(m, p, state, error, loc);
414f4fcbbe9SPaul Mackerras seq_putc(m, '\n');
415f4fcbbe9SPaul Mackerras if (loc) {
416f4fcbbe9SPaul Mackerras offs += strlen(loc) + 1;
417f4fcbbe9SPaul Mackerras loc += strlen(loc) + 1;
418f4fcbbe9SPaul Mackerras if (offs >= llen)
419f4fcbbe9SPaul Mackerras loc = NULL;
420f4fcbbe9SPaul Mackerras }
421f4fcbbe9SPaul Mackerras }
422f4fcbbe9SPaul Mackerras }
423f4fcbbe9SPaul Mackerras return 0;
424f4fcbbe9SPaul Mackerras }
425f4fcbbe9SPaul Mackerras
426f4fcbbe9SPaul Mackerras /* ****************************************************************** */
427f4fcbbe9SPaul Mackerras
ppc_rtas_find_all_sensors(void)428f4fcbbe9SPaul Mackerras static int ppc_rtas_find_all_sensors(void)
429f4fcbbe9SPaul Mackerras {
430a7f67bdfSJeremy Kerr const unsigned int *utmp;
431f4fcbbe9SPaul Mackerras int len, i;
432f4fcbbe9SPaul Mackerras
433e2eb6392SStephen Rothwell utmp = of_get_property(rtas_node, "rtas-sensors", &len);
434f4fcbbe9SPaul Mackerras if (utmp == NULL) {
435f4fcbbe9SPaul Mackerras printk (KERN_ERR "error: could not get rtas-sensors\n");
436f4fcbbe9SPaul Mackerras return 1;
437f4fcbbe9SPaul Mackerras }
438f4fcbbe9SPaul Mackerras
439f4fcbbe9SPaul Mackerras sensors.quant = len / 8; /* int + int */
440f4fcbbe9SPaul Mackerras
441f4fcbbe9SPaul Mackerras for (i=0; i<sensors.quant; i++) {
442f4fcbbe9SPaul Mackerras sensors.sensor[i].token = *utmp++;
443f4fcbbe9SPaul Mackerras sensors.sensor[i].quant = *utmp++;
444f4fcbbe9SPaul Mackerras }
445f4fcbbe9SPaul Mackerras return 0;
446f4fcbbe9SPaul Mackerras }
447f4fcbbe9SPaul Mackerras
448f4fcbbe9SPaul Mackerras /* ****************************************************************** */
449f4fcbbe9SPaul Mackerras /*
450f4fcbbe9SPaul Mackerras * Builds a string of what rtas returned
451f4fcbbe9SPaul Mackerras */
ppc_rtas_process_error(int error)452f4fcbbe9SPaul Mackerras static char *ppc_rtas_process_error(int error)
453f4fcbbe9SPaul Mackerras {
454f4fcbbe9SPaul Mackerras switch (error) {
455f4fcbbe9SPaul Mackerras case SENSOR_CRITICAL_HIGH:
456f4fcbbe9SPaul Mackerras return "(critical high)";
457f4fcbbe9SPaul Mackerras case SENSOR_WARNING_HIGH:
458f4fcbbe9SPaul Mackerras return "(warning high)";
459f4fcbbe9SPaul Mackerras case SENSOR_NORMAL:
460f4fcbbe9SPaul Mackerras return "(normal)";
461f4fcbbe9SPaul Mackerras case SENSOR_WARNING_LOW:
462f4fcbbe9SPaul Mackerras return "(warning low)";
463f4fcbbe9SPaul Mackerras case SENSOR_CRITICAL_LOW:
464f4fcbbe9SPaul Mackerras return "(critical low)";
465f4fcbbe9SPaul Mackerras case SENSOR_SUCCESS:
466f4fcbbe9SPaul Mackerras return "(read ok)";
467f4fcbbe9SPaul Mackerras case SENSOR_HW_ERROR:
468f4fcbbe9SPaul Mackerras return "(hardware error)";
469f4fcbbe9SPaul Mackerras case SENSOR_BUSY:
470f4fcbbe9SPaul Mackerras return "(busy)";
471f4fcbbe9SPaul Mackerras case SENSOR_NOT_EXIST:
472f4fcbbe9SPaul Mackerras return "(non existent)";
473f4fcbbe9SPaul Mackerras case SENSOR_DR_ENTITY:
474f4fcbbe9SPaul Mackerras return "(dr entity removed)";
475f4fcbbe9SPaul Mackerras default:
476f4fcbbe9SPaul Mackerras return "(UNKNOWN)";
477f4fcbbe9SPaul Mackerras }
478f4fcbbe9SPaul Mackerras }
479f4fcbbe9SPaul Mackerras
480f4fcbbe9SPaul Mackerras /* ****************************************************************** */
481f4fcbbe9SPaul Mackerras /*
482f4fcbbe9SPaul Mackerras * Builds a string out of what the sensor said
483f4fcbbe9SPaul Mackerras */
484f4fcbbe9SPaul Mackerras
ppc_rtas_process_sensor(struct seq_file * m,struct individual_sensor * s,int state,int error,const char * loc)485f4fcbbe9SPaul Mackerras static void ppc_rtas_process_sensor(struct seq_file *m,
486a7f67bdfSJeremy Kerr struct individual_sensor *s, int state, int error, const char *loc)
487f4fcbbe9SPaul Mackerras {
488f4fcbbe9SPaul Mackerras /* Defined return vales */
489f4fcbbe9SPaul Mackerras const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t",
490f4fcbbe9SPaul Mackerras "Maintenance" };
491f4fcbbe9SPaul Mackerras const char * enclosure_switch[] = { "Closed", "Open" };
492f4fcbbe9SPaul Mackerras const char * lid_status[] = { " ", "Open", "Closed" };
493f4fcbbe9SPaul Mackerras const char * power_source[] = { "AC\t", "Battery",
494f4fcbbe9SPaul Mackerras "AC & Battery" };
495f4fcbbe9SPaul Mackerras const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
496f4fcbbe9SPaul Mackerras const char * epow_sensor[] = {
497f4fcbbe9SPaul Mackerras "EPOW Reset", "Cooling warning", "Power warning",
498f4fcbbe9SPaul Mackerras "System shutdown", "System halt", "EPOW main enclosure",
499f4fcbbe9SPaul Mackerras "EPOW power off" };
500f4fcbbe9SPaul Mackerras const char * battery_cyclestate[] = { "None", "In progress",
501f4fcbbe9SPaul Mackerras "Requested" };
502ba01b058SColin Ian King const char * battery_charging[] = { "Charging", "Discharging",
503f4fcbbe9SPaul Mackerras "No current flow" };
504f4fcbbe9SPaul Mackerras const char * ibm_drconnector[] = { "Empty", "Present", "Unusable",
505f4fcbbe9SPaul Mackerras "Exchange" };
506f4fcbbe9SPaul Mackerras
507f4fcbbe9SPaul Mackerras int have_strings = 0;
508f4fcbbe9SPaul Mackerras int num_states = 0;
509f4fcbbe9SPaul Mackerras int temperature = 0;
510f4fcbbe9SPaul Mackerras int unknown = 0;
511f4fcbbe9SPaul Mackerras
512f4fcbbe9SPaul Mackerras /* What kind of sensor do we have here? */
513f4fcbbe9SPaul Mackerras
514f4fcbbe9SPaul Mackerras switch (s->token) {
515f4fcbbe9SPaul Mackerras case KEY_SWITCH:
516f4fcbbe9SPaul Mackerras seq_printf(m, "Key switch:\t");
517f4fcbbe9SPaul Mackerras num_states = sizeof(key_switch) / sizeof(char *);
518f4fcbbe9SPaul Mackerras if (state < num_states) {
519f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t", key_switch[state]);
520f4fcbbe9SPaul Mackerras have_strings = 1;
521f4fcbbe9SPaul Mackerras }
522f4fcbbe9SPaul Mackerras break;
523f4fcbbe9SPaul Mackerras case ENCLOSURE_SWITCH:
524f4fcbbe9SPaul Mackerras seq_printf(m, "Enclosure switch:\t");
525f4fcbbe9SPaul Mackerras num_states = sizeof(enclosure_switch) / sizeof(char *);
526f4fcbbe9SPaul Mackerras if (state < num_states) {
527f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t",
528f4fcbbe9SPaul Mackerras enclosure_switch[state]);
529f4fcbbe9SPaul Mackerras have_strings = 1;
530f4fcbbe9SPaul Mackerras }
531f4fcbbe9SPaul Mackerras break;
532f4fcbbe9SPaul Mackerras case THERMAL_SENSOR:
533f4fcbbe9SPaul Mackerras seq_printf(m, "Temp. (C/F):\t");
534f4fcbbe9SPaul Mackerras temperature = 1;
535f4fcbbe9SPaul Mackerras break;
536f4fcbbe9SPaul Mackerras case LID_STATUS:
537f4fcbbe9SPaul Mackerras seq_printf(m, "Lid status:\t");
538f4fcbbe9SPaul Mackerras num_states = sizeof(lid_status) / sizeof(char *);
539f4fcbbe9SPaul Mackerras if (state < num_states) {
540f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t", lid_status[state]);
541f4fcbbe9SPaul Mackerras have_strings = 1;
542f4fcbbe9SPaul Mackerras }
543f4fcbbe9SPaul Mackerras break;
544f4fcbbe9SPaul Mackerras case POWER_SOURCE:
545f4fcbbe9SPaul Mackerras seq_printf(m, "Power source:\t");
546f4fcbbe9SPaul Mackerras num_states = sizeof(power_source) / sizeof(char *);
547f4fcbbe9SPaul Mackerras if (state < num_states) {
548f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t",
549f4fcbbe9SPaul Mackerras power_source[state]);
550f4fcbbe9SPaul Mackerras have_strings = 1;
551f4fcbbe9SPaul Mackerras }
552f4fcbbe9SPaul Mackerras break;
553f4fcbbe9SPaul Mackerras case BATTERY_VOLTAGE:
554f4fcbbe9SPaul Mackerras seq_printf(m, "Battery voltage:\t");
555f4fcbbe9SPaul Mackerras break;
556f4fcbbe9SPaul Mackerras case BATTERY_REMAINING:
557f4fcbbe9SPaul Mackerras seq_printf(m, "Battery remaining:\t");
558f4fcbbe9SPaul Mackerras num_states = sizeof(battery_remaining) / sizeof(char *);
559f4fcbbe9SPaul Mackerras if (state < num_states)
560f4fcbbe9SPaul Mackerras {
561f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t",
562f4fcbbe9SPaul Mackerras battery_remaining[state]);
563f4fcbbe9SPaul Mackerras have_strings = 1;
564f4fcbbe9SPaul Mackerras }
565f4fcbbe9SPaul Mackerras break;
566f4fcbbe9SPaul Mackerras case BATTERY_PERCENTAGE:
567f4fcbbe9SPaul Mackerras seq_printf(m, "Battery percentage:\t");
568f4fcbbe9SPaul Mackerras break;
569f4fcbbe9SPaul Mackerras case EPOW_SENSOR:
570f4fcbbe9SPaul Mackerras seq_printf(m, "EPOW Sensor:\t");
571f4fcbbe9SPaul Mackerras num_states = sizeof(epow_sensor) / sizeof(char *);
572f4fcbbe9SPaul Mackerras if (state < num_states) {
573f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t", epow_sensor[state]);
574f4fcbbe9SPaul Mackerras have_strings = 1;
575f4fcbbe9SPaul Mackerras }
576f4fcbbe9SPaul Mackerras break;
577f4fcbbe9SPaul Mackerras case BATTERY_CYCLESTATE:
578f4fcbbe9SPaul Mackerras seq_printf(m, "Battery cyclestate:\t");
579f4fcbbe9SPaul Mackerras num_states = sizeof(battery_cyclestate) /
580f4fcbbe9SPaul Mackerras sizeof(char *);
581f4fcbbe9SPaul Mackerras if (state < num_states) {
582f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t",
583f4fcbbe9SPaul Mackerras battery_cyclestate[state]);
584f4fcbbe9SPaul Mackerras have_strings = 1;
585f4fcbbe9SPaul Mackerras }
586f4fcbbe9SPaul Mackerras break;
587f4fcbbe9SPaul Mackerras case BATTERY_CHARGING:
588f4fcbbe9SPaul Mackerras seq_printf(m, "Battery Charging:\t");
589f4fcbbe9SPaul Mackerras num_states = sizeof(battery_charging) / sizeof(char *);
590f4fcbbe9SPaul Mackerras if (state < num_states) {
591f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t",
592f4fcbbe9SPaul Mackerras battery_charging[state]);
593f4fcbbe9SPaul Mackerras have_strings = 1;
594f4fcbbe9SPaul Mackerras }
595f4fcbbe9SPaul Mackerras break;
596f4fcbbe9SPaul Mackerras case IBM_SURVEILLANCE:
597f4fcbbe9SPaul Mackerras seq_printf(m, "Surveillance:\t");
598f4fcbbe9SPaul Mackerras break;
599f4fcbbe9SPaul Mackerras case IBM_FANRPM:
600f4fcbbe9SPaul Mackerras seq_printf(m, "Fan (rpm):\t");
601f4fcbbe9SPaul Mackerras break;
602f4fcbbe9SPaul Mackerras case IBM_VOLTAGE:
603f4fcbbe9SPaul Mackerras seq_printf(m, "Voltage (mv):\t");
604f4fcbbe9SPaul Mackerras break;
605f4fcbbe9SPaul Mackerras case IBM_DRCONNECTOR:
606f4fcbbe9SPaul Mackerras seq_printf(m, "DR connector:\t");
607f4fcbbe9SPaul Mackerras num_states = sizeof(ibm_drconnector) / sizeof(char *);
608f4fcbbe9SPaul Mackerras if (state < num_states) {
609f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t",
610f4fcbbe9SPaul Mackerras ibm_drconnector[state]);
611f4fcbbe9SPaul Mackerras have_strings = 1;
612f4fcbbe9SPaul Mackerras }
613f4fcbbe9SPaul Mackerras break;
614f4fcbbe9SPaul Mackerras case IBM_POWERSUPPLY:
615f4fcbbe9SPaul Mackerras seq_printf(m, "Powersupply:\t");
616f4fcbbe9SPaul Mackerras break;
617f4fcbbe9SPaul Mackerras default:
618f4fcbbe9SPaul Mackerras seq_printf(m, "Unknown sensor (type %d), ignoring it\n",
619f4fcbbe9SPaul Mackerras s->token);
620f4fcbbe9SPaul Mackerras unknown = 1;
621f4fcbbe9SPaul Mackerras have_strings = 1;
622f4fcbbe9SPaul Mackerras break;
623f4fcbbe9SPaul Mackerras }
624f4fcbbe9SPaul Mackerras if (have_strings == 0) {
625f4fcbbe9SPaul Mackerras if (temperature) {
626f4fcbbe9SPaul Mackerras seq_printf(m, "%4d /%4d\t", state, cel_to_fahr(state));
627f4fcbbe9SPaul Mackerras } else
628f4fcbbe9SPaul Mackerras seq_printf(m, "%10d\t", state);
629f4fcbbe9SPaul Mackerras }
630f4fcbbe9SPaul Mackerras if (unknown == 0) {
631f4fcbbe9SPaul Mackerras seq_printf(m, "%s\t", ppc_rtas_process_error(error));
632f4fcbbe9SPaul Mackerras get_location_code(m, s, loc);
633f4fcbbe9SPaul Mackerras }
634f4fcbbe9SPaul Mackerras }
635f4fcbbe9SPaul Mackerras
636f4fcbbe9SPaul Mackerras /* ****************************************************************** */
637f4fcbbe9SPaul Mackerras
check_location(struct seq_file * m,const char * c)638a7f67bdfSJeremy Kerr static void check_location(struct seq_file *m, const char *c)
639f4fcbbe9SPaul Mackerras {
640f4fcbbe9SPaul Mackerras switch (c[0]) {
641f4fcbbe9SPaul Mackerras case LOC_PLANAR:
642f4fcbbe9SPaul Mackerras seq_printf(m, "Planar #%c", c[1]);
643f4fcbbe9SPaul Mackerras break;
644f4fcbbe9SPaul Mackerras case LOC_CPU:
645f4fcbbe9SPaul Mackerras seq_printf(m, "CPU #%c", c[1]);
646f4fcbbe9SPaul Mackerras break;
647f4fcbbe9SPaul Mackerras case LOC_FAN:
648f4fcbbe9SPaul Mackerras seq_printf(m, "Fan #%c", c[1]);
649f4fcbbe9SPaul Mackerras break;
650f4fcbbe9SPaul Mackerras case LOC_RACKMOUNTED:
651f4fcbbe9SPaul Mackerras seq_printf(m, "Rack #%c", c[1]);
652f4fcbbe9SPaul Mackerras break;
653f4fcbbe9SPaul Mackerras case LOC_VOLTAGE:
654f4fcbbe9SPaul Mackerras seq_printf(m, "Voltage #%c", c[1]);
655f4fcbbe9SPaul Mackerras break;
656f4fcbbe9SPaul Mackerras case LOC_LCD:
657f4fcbbe9SPaul Mackerras seq_printf(m, "LCD #%c", c[1]);
658f4fcbbe9SPaul Mackerras break;
659f4fcbbe9SPaul Mackerras case '.':
660f4fcbbe9SPaul Mackerras seq_printf(m, "- %c", c[1]);
661f4fcbbe9SPaul Mackerras break;
662f4fcbbe9SPaul Mackerras default:
663f4fcbbe9SPaul Mackerras seq_printf(m, "Unknown location");
664f4fcbbe9SPaul Mackerras break;
665f4fcbbe9SPaul Mackerras }
666f4fcbbe9SPaul Mackerras }
667f4fcbbe9SPaul Mackerras
668f4fcbbe9SPaul Mackerras
669f4fcbbe9SPaul Mackerras /* ****************************************************************** */
670f4fcbbe9SPaul Mackerras /*
671f4fcbbe9SPaul Mackerras * Format:
672f4fcbbe9SPaul Mackerras * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
673027dfac6SMichael Ellerman * the '.' may be an abbreviation
674f4fcbbe9SPaul Mackerras */
check_location_string(struct seq_file * m,const char * c)675a7f67bdfSJeremy Kerr static void check_location_string(struct seq_file *m, const char *c)
676f4fcbbe9SPaul Mackerras {
677f4fcbbe9SPaul Mackerras while (*c) {
678f4fcbbe9SPaul Mackerras if (isalpha(*c) || *c == '.')
679f4fcbbe9SPaul Mackerras check_location(m, c);
680f4fcbbe9SPaul Mackerras else if (*c == '/' || *c == '-')
681f4fcbbe9SPaul Mackerras seq_printf(m, " at ");
682f4fcbbe9SPaul Mackerras c++;
683f4fcbbe9SPaul Mackerras }
684f4fcbbe9SPaul Mackerras }
685f4fcbbe9SPaul Mackerras
686f4fcbbe9SPaul Mackerras
687f4fcbbe9SPaul Mackerras /* ****************************************************************** */
688f4fcbbe9SPaul Mackerras
get_location_code(struct seq_file * m,struct individual_sensor * s,const char * loc)689a7f67bdfSJeremy Kerr static void get_location_code(struct seq_file *m, struct individual_sensor *s,
690a7f67bdfSJeremy Kerr const char *loc)
691f4fcbbe9SPaul Mackerras {
692f4fcbbe9SPaul Mackerras if (!loc || !*loc) {
693f4fcbbe9SPaul Mackerras seq_printf(m, "---");/* does not have a location */
694f4fcbbe9SPaul Mackerras } else {
695f4fcbbe9SPaul Mackerras check_location_string(m, loc);
696f4fcbbe9SPaul Mackerras }
697f4fcbbe9SPaul Mackerras seq_putc(m, ' ');
698f4fcbbe9SPaul Mackerras }
699f4fcbbe9SPaul Mackerras /* ****************************************************************** */
700f4fcbbe9SPaul Mackerras /* INDICATORS - Tone Frequency */
701f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_tone_freq_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)702f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_tone_freq_write(struct file *file,
703f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos)
704f4fcbbe9SPaul Mackerras {
7052dc20f45SArnd Bergmann u64 freq;
706f4fcbbe9SPaul Mackerras int error = parse_number(buf, count, &freq);
707f4fcbbe9SPaul Mackerras if (error)
708f4fcbbe9SPaul Mackerras return error;
709f4fcbbe9SPaul Mackerras
710f4fcbbe9SPaul Mackerras rtas_tone_frequency = freq; /* save it for later */
711*08273c9fSNathan Lynch error = rtas_call(rtas_function_token(RTAS_FN_SET_INDICATOR), 3, 1, NULL,
712f4fcbbe9SPaul Mackerras TONE_FREQUENCY, 0, freq);
713f4fcbbe9SPaul Mackerras if (error)
714f4fcbbe9SPaul Mackerras printk(KERN_WARNING "error: setting tone frequency returned: %s\n",
715f4fcbbe9SPaul Mackerras ppc_rtas_process_error(error));
716f4fcbbe9SPaul Mackerras return count;
717f4fcbbe9SPaul Mackerras }
718f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_tone_freq_show(struct seq_file * m,void * v)719f4fcbbe9SPaul Mackerras static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v)
720f4fcbbe9SPaul Mackerras {
721f4fcbbe9SPaul Mackerras seq_printf(m, "%lu\n", rtas_tone_frequency);
722f4fcbbe9SPaul Mackerras return 0;
723f4fcbbe9SPaul Mackerras }
724f4fcbbe9SPaul Mackerras /* ****************************************************************** */
725f4fcbbe9SPaul Mackerras /* INDICATORS - Tone Volume */
726f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_tone_volume_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)727f4fcbbe9SPaul Mackerras static ssize_t ppc_rtas_tone_volume_write(struct file *file,
728f4fcbbe9SPaul Mackerras const char __user *buf, size_t count, loff_t *ppos)
729f4fcbbe9SPaul Mackerras {
7302dc20f45SArnd Bergmann u64 volume;
731f4fcbbe9SPaul Mackerras int error = parse_number(buf, count, &volume);
732f4fcbbe9SPaul Mackerras if (error)
733f4fcbbe9SPaul Mackerras return error;
734f4fcbbe9SPaul Mackerras
735f4fcbbe9SPaul Mackerras if (volume > 100)
736f4fcbbe9SPaul Mackerras volume = 100;
737f4fcbbe9SPaul Mackerras
738f4fcbbe9SPaul Mackerras rtas_tone_volume = volume; /* save it for later */
739*08273c9fSNathan Lynch error = rtas_call(rtas_function_token(RTAS_FN_SET_INDICATOR), 3, 1, NULL,
740f4fcbbe9SPaul Mackerras TONE_VOLUME, 0, volume);
741f4fcbbe9SPaul Mackerras if (error)
742f4fcbbe9SPaul Mackerras printk(KERN_WARNING "error: setting tone volume returned: %s\n",
743f4fcbbe9SPaul Mackerras ppc_rtas_process_error(error));
744f4fcbbe9SPaul Mackerras return count;
745f4fcbbe9SPaul Mackerras }
746f4fcbbe9SPaul Mackerras /* ****************************************************************** */
ppc_rtas_tone_volume_show(struct seq_file * m,void * v)747f4fcbbe9SPaul Mackerras static int ppc_rtas_tone_volume_show(struct seq_file *m, void *v)
748f4fcbbe9SPaul Mackerras {
749f4fcbbe9SPaul Mackerras seq_printf(m, "%lu\n", rtas_tone_volume);
750f4fcbbe9SPaul Mackerras return 0;
751f4fcbbe9SPaul Mackerras }
752f4fcbbe9SPaul Mackerras
753c13ff6f3SNathan Lynch /**
754c13ff6f3SNathan Lynch * ppc_rtas_rmo_buf_show() - Describe RTAS-addressable region for user space.
755c13ff6f3SNathan Lynch *
756c13ff6f3SNathan Lynch * Base + size description of a range of RTAS-addressable memory set
757c13ff6f3SNathan Lynch * aside for user space to use as work area(s) for certain RTAS
758c13ff6f3SNathan Lynch * functions. User space accesses this region via /dev/mem. Apart from
759c13ff6f3SNathan Lynch * security policies, the kernel does not arbitrate or serialize
760c13ff6f3SNathan Lynch * access to this region, and user space must ensure that concurrent
761c13ff6f3SNathan Lynch * users do not interfere with each other.
762c13ff6f3SNathan Lynch */
ppc_rtas_rmo_buf_show(struct seq_file * m,void * v)763f4fcbbe9SPaul Mackerras static int ppc_rtas_rmo_buf_show(struct seq_file *m, void *v)
764f4fcbbe9SPaul Mackerras {
765e5d56763SNathan Lynch seq_printf(m, "%016lx %x\n", rtas_rmo_buf, RTAS_USER_REGION_SIZE);
766f4fcbbe9SPaul Mackerras return 0;
767f4fcbbe9SPaul Mackerras }
768