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