4 * Copyright (C) 2002 Brian Waite
6 * This driver allows use of the CPU state bits
7 * It exports the /dev/sky_cpustate and also
8 * /proc/sky_cpustate pseudo-file for status information.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
17 #include <linux/version.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/spinlock.h>
21 #include <linux/miscdevice.h>
22 #include <linux/pci.h>
23 #include <linux/proc_fs.h>
24 #include <linux/device.h>
25 #include <asm/uaccess.h>
26 #include <linux/hdpu_features.h>
28 #define SKY_CPUSTATE_VERSION "1.1"
30 static int hdpu_cpustate_probe(struct device
*ddev
);
31 static int hdpu_cpustate_remove(struct device
*ddev
);
33 struct cpustate_t cpustate
;
35 static int cpustate_get_ref(int excl
)
40 spin_lock(&cpustate
.lock
);
46 if (cpustate
.open_count
)
51 cpustate
.open_count
++;
55 spin_unlock(&cpustate
.lock
);
59 static int cpustate_free_ref(void)
62 spin_lock(&cpustate
.lock
);
65 cpustate
.open_count
--;
67 spin_unlock(&cpustate
.lock
);
71 unsigned char cpustate_get_state(void)
74 return cpustate
.cached_val
;
77 void cpustate_set_state(unsigned char new_state
)
79 unsigned int state
= (new_state
<< 21);
82 printk("CPUSTATE -> 0x%x\n", new_state
);
84 spin_lock(&cpustate
.lock
);
85 cpustate
.cached_val
= new_state
;
86 writel((0xff << 21), cpustate
.clr_addr
);
87 writel(state
, cpustate
.set_addr
);
88 spin_unlock(&cpustate
.lock
);
92 * Now all the various file operations that we export.
95 static ssize_t
cpustate_read(struct file
*file
, char *buf
,
96 size_t count
, loff_t
* ppos
)
105 data
= cpustate_get_state();
106 if (copy_to_user(buf
, &data
, sizeof(unsigned char)))
108 return sizeof(unsigned char);
111 static ssize_t
cpustate_write(struct file
*file
, const char *buf
,
112 size_t count
, loff_t
* ppos
)
122 if (copy_from_user((unsigned char *)&data
, buf
, sizeof(unsigned char)))
125 cpustate_set_state(data
);
126 return sizeof(unsigned char);
129 static int cpustate_open(struct inode
*inode
, struct file
*file
)
131 return cpustate_get_ref((file
->f_flags
& O_EXCL
));
134 static int cpustate_release(struct inode
*inode
, struct file
*file
)
136 return cpustate_free_ref();
140 * Info exported via "/proc/sky_cpustate".
142 static int cpustate_read_proc(char *page
, char **start
, off_t off
,
143 int count
, int *eof
, void *data
)
148 p
+= sprintf(p
, "CPU State: %04x\n", cpustate_get_state());
151 if (len
<= off
+ count
)
162 static struct device_driver hdpu_cpustate_driver
= {
163 .name
= HDPU_CPUSTATE_NAME
,
164 .bus
= &platform_bus_type
,
165 .probe
= hdpu_cpustate_probe
,
166 .remove
= hdpu_cpustate_remove
,
170 * The various file operations we support.
172 static struct file_operations cpustate_fops
= {
175 release
:cpustate_release
,
177 write
:cpustate_write
,
185 static struct miscdevice cpustate_dev
= {
191 static int hdpu_cpustate_probe(struct device
*ddev
)
193 struct platform_device
*pdev
= to_platform_device(ddev
);
194 struct resource
*res
;
196 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
197 cpustate
.set_addr
= (unsigned long *)res
->start
;
198 cpustate
.clr_addr
= (unsigned long *)res
->end
- 1;
200 misc_register(&cpustate_dev
);
201 create_proc_read_entry("sky_cpustate", 0, 0, cpustate_read_proc
, NULL
);
203 printk(KERN_INFO
"Sky CPU State Driver v" SKY_CPUSTATE_VERSION
"\n");
206 static int hdpu_cpustate_remove(struct device
*ddev
)
209 cpustate
.set_addr
= 0;
210 cpustate
.clr_addr
= 0;
212 remove_proc_entry("sky_cpustate", NULL
);
213 misc_deregister(&cpustate_dev
);
218 static int __init
cpustate_init(void)
221 rc
= driver_register(&hdpu_cpustate_driver
);
225 static void __exit
cpustate_exit(void)
227 driver_unregister(&hdpu_cpustate_driver
);
230 module_init(cpustate_init
);
231 module_exit(cpustate_exit
);
233 MODULE_AUTHOR("Brian Waite");
234 MODULE_LICENSE("GPL");