fix build on some compilers
[pandora-kernel.git] / arch / arm / kernel / sysfs_v7.c
1 /*
2  *  linux/arch/arm/kernel/sysfs.c
3  *
4  *  Copyright (C) 2008 Mans Rullgard
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/cpu.h>
13 #include <linux/sysdev.h>
14 #include <linux/fs.h>
15
16 asm(".arch_extension sec\n");
17
18 #define SETBITS(val, bits, new)                 \
19         do {                                    \
20                 val &= ~bits;                   \
21                 val |= new & bits;              \
22         } while (0)
23
24 #define SHOW_REG(name, opc1, crn, crm, opc2)                            \
25 static ssize_t name##_show(struct sys_device *dev,                      \
26                            struct sysdev_attribute *attr,               \
27                            char *buf)                                   \
28 {                                                                       \
29         unsigned val;                                                   \
30         asm ("mrc p15,"#opc1", %0,"#crn","#crm","#opc2 : "=r"(val));    \
31         return snprintf(buf, PAGE_SIZE, "%08x\n", val);                 \
32 }
33
34 #define STORE_REG(name, opc1, crn, crm, opc2, bits)                     \
35 static ssize_t name##_store(struct sys_device *dev,                     \
36                             struct sysdev_attribute *attr,              \
37                             const char *buf, size_t size)               \
38 {                                                                       \
39         char *end;                                                      \
40         unsigned new = simple_strtoul(buf, &end, 0);                    \
41         unsigned val;                                                   \
42                                                                         \
43         if (end == buf)                                                 \
44                 return -EINVAL;                                         \
45                                                                         \
46         asm ("mrc p15,"#opc1", %0,"#crn","#crm","#opc2 : "=r"(val));    \
47         SETBITS(val, bits, new);                                        \
48         asm ("mcr p15,"#opc1", %0,"#crn","#crm","#opc2 :: "r"(val));    \
49                                                                         \
50         return end - buf;                                               \
51 }
52
53 #define RD_REG(name, opc1, crn, crm, opc2)                              \
54         SHOW_REG(name, opc1, crn, crm, opc2)                            \
55         static SYSDEV_ATTR(name, S_IRUGO|S_IWUSR, name##_show, NULL)
56
57 #define RDWR_REG(name, opc1, crn, crm, opc2, bits)                      \
58         SHOW_REG(name, opc1, crn, crm, opc2)                            \
59         STORE_REG(name, opc1, crn, crm, opc2, bits)                     \
60         static SYSDEV_ATTR(name, S_IRUGO|S_IWUSR, name##_show, name##_store)
61
62 RDWR_REG(control, 0, c1, c0, 0, 0x802);
63
64 SHOW_REG(aux_ctl, 0, c1, c0, 1)
65
66 #ifdef CONFIG_ARCH_OMAP34XX
67 static ssize_t aux_ctl_store(struct sys_device *dev,
68                              struct sysdev_attribute *attr,
69                              const char *buf, size_t size)
70 {
71         char *end;
72         unsigned new = simple_strtoul(buf, &end, 0);
73         unsigned val;
74
75         if (end == buf)
76                 return -EINVAL;
77
78         asm ("mrc p15, 0, %0, c1, c0, 1" : "=r"(val));
79         SETBITS(val, 0xff8, new);
80         val &= ~2;
81         asm ("mov r0,  %0       \n\t"
82              "mov r12, #3       \n\t"
83              "smc #0            \n\t"
84              :: "r"(val) : "r0", "r12");
85
86         return end - buf;
87 }
88 #define AUX_WR S_IWUSR
89 #else
90 #define aux_ctl_store NULL
91 #define AUX_WR 0
92 #endif
93
94 static SYSDEV_ATTR(aux_control, S_IRUGO|AUX_WR, aux_ctl_show, aux_ctl_store);
95
96 SHOW_REG(l2_aux_ctl, 1, c9, c0, 2)
97
98 #ifdef CONFIG_ARCH_OMAP34XX
99 static ssize_t l2_aux_ctl_store(struct sys_device *dev,
100                                 struct sysdev_attribute *attr,
101                                 const char *buf, size_t size)
102 {
103         char *end;
104         unsigned new = simple_strtoul(buf, &end, 0);
105         unsigned val;
106
107         if (end == buf)
108                 return -EINVAL;
109
110         asm ("mrc p15, 1, %0, c9, c0, 2" : "=r"(val));
111         SETBITS(val, 0xbc00000, new);
112         asm ("mov r0,  %0       \n\t"
113              "mov r12, #2       \n\t"
114              "smc #0            \n\t"
115              :: "r"(val) : "r0", "r12");
116
117         return end - buf;
118 }
119 #define L2AUX_WR S_IWUSR
120 #else
121 #define l2_aux_ctl_store NULL
122 #define L2AUX_WR 0
123 #endif
124
125 static SYSDEV_ATTR(l2_aux_control, S_IRUGO|L2AUX_WR,
126                    l2_aux_ctl_show, l2_aux_ctl_store);
127
128 RDWR_REG(pmon_pmnc,   0, c9, c12, 0, 0x3f)
129 RDWR_REG(pmon_cntens, 0, c9, c12, 1, 0x8000000f)
130 RDWR_REG(pmon_cntenc, 0, c9, c12, 2, 0x8000000f)
131 RDWR_REG(pmon_ccnt,   0, c9, c13, 0, 0xffffffff)
132 RDWR_REG(pmon_useren, 0, c9, c14, 0, 1)
133
134 #define REG_ATTR(sysdev, name)                                          \
135         do {                                                            \
136                 int err = sysfs_create_file(&sysdev->kobj, &name.attr); \
137                 WARN_ON(err != 0);                                      \
138         } while (0)
139
140 static int __init cpu_sysfs_init(void)
141 {
142         struct sys_device *sysdev;
143         int cpu;
144
145         for_each_possible_cpu(cpu) {
146                 sysdev = get_cpu_sysdev(cpu);
147                 REG_ATTR(sysdev, attr_control);
148                 REG_ATTR(sysdev, attr_aux_control);
149                 REG_ATTR(sysdev, attr_l2_aux_control);
150                 REG_ATTR(sysdev, attr_pmon_pmnc);
151                 REG_ATTR(sysdev, attr_pmon_cntens);
152                 REG_ATTR(sysdev, attr_pmon_cntenc);
153                 REG_ATTR(sysdev, attr_pmon_ccnt);
154                 REG_ATTR(sysdev, attr_pmon_useren);
155         }
156
157         return 0;
158 }
159 device_initcall(cpu_sysfs_init);