Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.21-rc6 248 lines 5.1 kB view raw
1/* 2 * Sky CPU State Driver 3 * 4 * Copyright (C) 2002 Brian Waite 5 * 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. 9 * 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. 14 * 15 */ 16 17#include <linux/module.h> 18#include <linux/kernel.h> 19#include <linux/spinlock.h> 20#include <linux/miscdevice.h> 21#include <linux/pci.h> 22#include <linux/proc_fs.h> 23#include <linux/platform_device.h> 24#include <asm/uaccess.h> 25#include <linux/hdpu_features.h> 26 27#define SKY_CPUSTATE_VERSION "1.1" 28 29static int hdpu_cpustate_probe(struct platform_device *pdev); 30static int hdpu_cpustate_remove(struct platform_device *pdev); 31 32struct cpustate_t cpustate; 33 34static int cpustate_get_ref(int excl) 35{ 36 37 int retval = -EBUSY; 38 39 spin_lock(&cpustate.lock); 40 41 if (cpustate.excl) 42 goto out_busy; 43 44 if (excl) { 45 if (cpustate.open_count) 46 goto out_busy; 47 cpustate.excl = 1; 48 } 49 50 cpustate.open_count++; 51 retval = 0; 52 53 out_busy: 54 spin_unlock(&cpustate.lock); 55 return retval; 56} 57 58static int cpustate_free_ref(void) 59{ 60 61 spin_lock(&cpustate.lock); 62 63 cpustate.excl = 0; 64 cpustate.open_count--; 65 66 spin_unlock(&cpustate.lock); 67 return 0; 68} 69 70unsigned char cpustate_get_state(void) 71{ 72 73 return cpustate.cached_val; 74} 75 76void cpustate_set_state(unsigned char new_state) 77{ 78 unsigned int state = (new_state << 21); 79 80#ifdef DEBUG_CPUSTATE 81 printk("CPUSTATE -> 0x%x\n", new_state); 82#endif 83 spin_lock(&cpustate.lock); 84 cpustate.cached_val = new_state; 85 writel((0xff << 21), cpustate.clr_addr); 86 writel(state, cpustate.set_addr); 87 spin_unlock(&cpustate.lock); 88} 89 90/* 91 * Now all the various file operations that we export. 92 */ 93 94static ssize_t cpustate_read(struct file *file, char *buf, 95 size_t count, loff_t * ppos) 96{ 97 unsigned char data; 98 99 if (count < 0) 100 return -EFAULT; 101 if (count == 0) 102 return 0; 103 104 data = cpustate_get_state(); 105 if (copy_to_user(buf, &data, sizeof(unsigned char))) 106 return -EFAULT; 107 return sizeof(unsigned char); 108} 109 110static ssize_t cpustate_write(struct file *file, const char *buf, 111 size_t count, loff_t * ppos) 112{ 113 unsigned char data; 114 115 if (count < 0) 116 return -EFAULT; 117 118 if (count == 0) 119 return 0; 120 121 if (copy_from_user((unsigned char *)&data, buf, sizeof(unsigned char))) 122 return -EFAULT; 123 124 cpustate_set_state(data); 125 return sizeof(unsigned char); 126} 127 128static int cpustate_open(struct inode *inode, struct file *file) 129{ 130 return cpustate_get_ref((file->f_flags & O_EXCL)); 131} 132 133static int cpustate_release(struct inode *inode, struct file *file) 134{ 135 return cpustate_free_ref(); 136} 137 138/* 139 * Info exported via "/proc/sky_cpustate". 140 */ 141static int cpustate_read_proc(char *page, char **start, off_t off, 142 int count, int *eof, void *data) 143{ 144 char *p = page; 145 int len = 0; 146 147 p += sprintf(p, "CPU State: %04x\n", cpustate_get_state()); 148 len = p - page; 149 150 if (len <= off + count) 151 *eof = 1; 152 *start = page + off; 153 len -= off; 154 if (len > count) 155 len = count; 156 if (len < 0) 157 len = 0; 158 return len; 159} 160 161static struct platform_driver hdpu_cpustate_driver = { 162 .probe = hdpu_cpustate_probe, 163 .remove = hdpu_cpustate_remove, 164 .driver = { 165 .name = HDPU_CPUSTATE_NAME, 166 }, 167}; 168 169/* 170 * The various file operations we support. 171 */ 172static const struct file_operations cpustate_fops = { 173 owner:THIS_MODULE, 174 open:cpustate_open, 175 release:cpustate_release, 176 read:cpustate_read, 177 write:cpustate_write, 178 fasync:NULL, 179 poll:NULL, 180 ioctl:NULL, 181 llseek:no_llseek, 182 183}; 184 185static struct miscdevice cpustate_dev = { 186 MISC_DYNAMIC_MINOR, 187 "sky_cpustate", 188 &cpustate_fops 189}; 190 191static int hdpu_cpustate_probe(struct platform_device *pdev) 192{ 193 struct resource *res; 194 struct proc_dir_entry *proc_de; 195 int ret; 196 197 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 198 cpustate.set_addr = (unsigned long *)res->start; 199 cpustate.clr_addr = (unsigned long *)res->end - 1; 200 201 ret = misc_register(&cpustate_dev); 202 if (ret) { 203 printk(KERN_WARNING "sky_cpustate: Unable to register misc " 204 "device.\n"); 205 cpustate.set_addr = NULL; 206 cpustate.clr_addr = NULL; 207 return ret; 208 } 209 210 proc_de = create_proc_read_entry("sky_cpustate", 0, 0, 211 cpustate_read_proc, NULL); 212 if (proc_de == NULL) 213 printk(KERN_WARNING "sky_cpustate: Unable to create proc " 214 "dir entry\n"); 215 216 printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n"); 217 return 0; 218} 219 220static int hdpu_cpustate_remove(struct platform_device *pdev) 221{ 222 223 cpustate.set_addr = NULL; 224 cpustate.clr_addr = NULL; 225 226 remove_proc_entry("sky_cpustate", NULL); 227 misc_deregister(&cpustate_dev); 228 return 0; 229 230} 231 232static int __init cpustate_init(void) 233{ 234 int rc; 235 rc = platform_driver_register(&hdpu_cpustate_driver); 236 return rc; 237} 238 239static void __exit cpustate_exit(void) 240{ 241 platform_driver_unregister(&hdpu_cpustate_driver); 242} 243 244module_init(cpustate_init); 245module_exit(cpustate_exit); 246 247MODULE_AUTHOR("Brian Waite"); 248MODULE_LICENSE("GPL");