Root/
Source at commit ef60fc3200a68f7ebd2a5a9fff585073f233bb5e created 14 years 3 months ago. By xiangfu, file | |
---|---|
1 | /* |
2 | * linux/arch/mips/jz4740/proc.c |
3 | * |
4 | * /proc/jz/ procfs for jz4740 on-chip modules. |
5 | * |
6 | * Copyright (C) 2006 Ingenic Semiconductor Inc. |
7 | * Author: <jlwei@ingenic.cn> |
8 | * |
9 | * This program is free software; you can distribute it and/or modify it |
10 | * under the terms of the GNU General Public License (Version 2) as |
11 | * published by the Free Software Foundation. |
12 | * |
13 | * This program is distributed in the hope it will be useful, but WITHOUT |
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
16 | * for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License along |
19 | * with this program; if not, write to the Free Software Foundation, Inc., |
20 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. |
21 | * |
22 | */ |
23 | #include <linux/kernel.h> |
24 | #include <linux/init.h> |
25 | #include <linux/interrupt.h> |
26 | #include <linux/irq.h> |
27 | #include <linux/sysctl.h> |
28 | #include <linux/proc_fs.h> |
29 | #include <linux/page-flags.h> |
30 | #include <asm/uaccess.h> |
31 | #include <asm/pgtable.h> |
32 | #include <asm/mach-jz4740/regs.h> |
33 | #include <asm/mach-jz4740/clock.h> |
34 | #include <asm/mach-jz4740/ops.h> |
35 | |
36 | //#define DEBUG 1 |
37 | #undef DEBUG |
38 | |
39 | |
40 | struct proc_dir_entry *proc_jz_root; |
41 | |
42 | |
43 | /* |
44 | * EMC Modules |
45 | */ |
46 | static int emc_read_proc (char *page, char **start, off_t off, |
47 | int count, int *eof, void *data) |
48 | { |
49 | int len = 0; |
50 | |
51 | len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); |
52 | len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); |
53 | len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); |
54 | len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); |
55 | len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); |
56 | return len; |
57 | } |
58 | |
59 | /* |
60 | * Power Manager Module |
61 | */ |
62 | static int pmc_read_proc (char *page, char **start, off_t off, |
63 | int count, int *eof, void *data) |
64 | { |
65 | int len = 0; |
66 | unsigned long lcr = REG_CPM_LCR; |
67 | unsigned long clkgr = REG_CPM_CLKGR; |
68 | |
69 | len += sprintf (page+len, "Low Power Mode : %s\n", |
70 | ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? |
71 | "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? |
72 | "SLEEP" : "HIBERNATE")); |
73 | len += sprintf (page+len, "Doze Mode : %s\n", |
74 | (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); |
75 | if (lcr & CPM_LCR_DOZE_ON) |
76 | len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); |
77 | len += sprintf (page+len, "IPU : %s\n", |
78 | (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); |
79 | len += sprintf (page+len, "DMAC : %s\n", |
80 | (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); |
81 | len += sprintf (page+len, "UHC : %s\n", |
82 | (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); |
83 | len += sprintf (page+len, "UDC : %s\n", |
84 | (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); |
85 | len += sprintf (page+len, "LCD : %s\n", |
86 | (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); |
87 | len += sprintf (page+len, "CIM : %s\n", |
88 | (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); |
89 | len += sprintf (page+len, "SADC : %s\n", |
90 | (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); |
91 | len += sprintf (page+len, "MSC : %s\n", |
92 | (clkgr & CPM_CLKGR_MSC) ? "stopped" : "running"); |
93 | len += sprintf (page+len, "AIC1 : %s\n", |
94 | (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); |
95 | len += sprintf (page+len, "AIC2 : %s\n", |
96 | (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); |
97 | len += sprintf (page+len, "SSI : %s\n", |
98 | (clkgr & CPM_CLKGR_SSI) ? "stopped" : "running"); |
99 | len += sprintf (page+len, "I2C : %s\n", |
100 | (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); |
101 | len += sprintf (page+len, "RTC : %s\n", |
102 | (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); |
103 | len += sprintf (page+len, "TCU : %s\n", |
104 | (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); |
105 | len += sprintf (page+len, "UART1 : %s\n", |
106 | (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); |
107 | len += sprintf (page+len, "UART0 : %s\n", |
108 | (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); |
109 | return len; |
110 | } |
111 | |
112 | static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) |
113 | { |
114 | REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); |
115 | return count; |
116 | } |
117 | |
118 | /* |
119 | * Clock Generation Module |
120 | */ |
121 | #define TO_MHZ(x) (x/1000000),(x%1000000)/10000 |
122 | #define TO_KHZ(x) (x/1000),(x%1000)/10 |
123 | |
124 | static int cgm_read_proc (char *page, char **start, off_t off, |
125 | int count, int *eof, void *data) |
126 | { |
127 | int len = 0; |
128 | unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ |
129 | unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ |
130 | unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; |
131 | unsigned int od[4] = {1, 2, 2, 4}; |
132 | |
133 | len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); |
134 | len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); |
135 | len += sprintf (page+len, "PLL : %s\n", |
136 | (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); |
137 | len += sprintf (page+len, "m:n:o : %d:%d:%d\n", |
138 | __cpm_get_pllm() + 2, |
139 | __cpm_get_plln() + 2, |
140 | od[__cpm_get_pllod()] |
141 | ); |
142 | len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", |
143 | div[__cpm_get_cdiv()], |
144 | div[__cpm_get_hdiv()], |
145 | div[__cpm_get_mdiv()], |
146 | div[__cpm_get_pdiv()] |
147 | ); |
148 | len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); |
149 | len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); |
150 | len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); |
151 | len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); |
152 | len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); |
153 | len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); |
154 | len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); |
155 | len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); |
156 | len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); |
157 | len += sprintf (page+len, "MSCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk())); |
158 | len += sprintf (page+len, "EXTALCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); |
159 | len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); |
160 | |
161 | return len; |
162 | } |
163 | |
164 | static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) |
165 | { |
166 | REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); |
167 | return count; |
168 | } |
169 | |
170 | |
171 | extern void local_flush_tlb_all(void); |
172 | |
173 | /* CP0 hazard avoidance. */ |
174 | #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ |
175 | "nop; nop; nop; nop; nop; nop;\n\t" \ |
176 | ".set reorder\n\t") |
177 | void show_tlb(void) |
178 | { |
179 | #define ASID_MASK 0xFF |
180 | |
181 | unsigned long flags; |
182 | unsigned int old_ctx; |
183 | unsigned int entry; |
184 | unsigned int entrylo0, entrylo1, entryhi; |
185 | unsigned int pagemask; |
186 | |
187 | local_irq_save(flags); |
188 | |
189 | /* Save old context */ |
190 | old_ctx = (read_c0_entryhi() & 0xff); |
191 | |
192 | printk("TLB content:\n"); |
193 | entry = 0; |
194 | while(entry < 32) { |
195 | write_c0_index(entry); |
196 | BARRIER; |
197 | tlb_read(); |
198 | BARRIER; |
199 | entryhi = read_c0_entryhi(); |
200 | entrylo0 = read_c0_entrylo0(); |
201 | entrylo1 = read_c0_entrylo1(); |
202 | pagemask = read_c0_pagemask(); |
203 | printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); |
204 | printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); |
205 | printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); |
206 | |
207 | printk("\t\tpagemask=0x%08x", pagemask); |
208 | printk("\tentryhi=0x%08x\n", entryhi); |
209 | printk("\t\tentrylo0=0x%08x", entrylo0); |
210 | printk("\tentrylo1=0x%08x\n", entrylo1); |
211 | |
212 | entry++; |
213 | } |
214 | BARRIER; |
215 | write_c0_entryhi(old_ctx); |
216 | |
217 | local_irq_restore(flags); |
218 | } |
219 | |
220 | /* |
221 | * UDC hotplug |
222 | */ |
223 | #ifdef CONFIG_JZ_UDC_HOTPLUG |
224 | extern int jz_udc_active; /* defined in drivers/char/jzchar/jz_udc_hotplug.c */ |
225 | #endif |
226 | |
227 | #ifndef GPIO_UDC_HOTPLUG |
228 | #define GPIO_UDC_HOTPLUG 86 |
229 | #endif |
230 | |
231 | static int udc_read_proc(char *page, char **start, off_t off, |
232 | int count, int *eof, void *data) |
233 | { |
234 | int len = 0; |
235 | |
236 | if (__gpio_get_pin(GPIO_UDC_HOTPLUG)) { |
237 | |
238 | #ifdef CONFIG_JZ_UDC_HOTPLUG |
239 | |
240 | /* Cable has connected, wait for disconnection. */ |
241 | __gpio_as_irq_fall_edge(GPIO_UDC_HOTPLUG); |
242 | |
243 | if (jz_udc_active) |
244 | len += sprintf (page+len, "CONNECT_CABLE\n"); |
245 | else |
246 | len += sprintf (page+len, "CONNECT_POWER\n"); |
247 | #else |
248 | len += sprintf (page+len, "CONNECT\n"); |
249 | #endif |
250 | } |
251 | else { |
252 | |
253 | #ifdef CONFIG_JZ_UDC_HOTPLUG |
254 | /* Cable has disconnected, wait for connection. */ |
255 | __gpio_as_irq_rise_edge(GPIO_UDC_HOTPLUG); |
256 | #endif |
257 | |
258 | len += sprintf (page+len, "REMOVE\n"); |
259 | } |
260 | |
261 | return len; |
262 | } |
263 | |
264 | /* |
265 | * /proc/jz/xxx entry |
266 | * |
267 | */ |
268 | static int __init jz_proc_init(void) |
269 | { |
270 | struct proc_dir_entry *res; |
271 | unsigned int virt_addr, i; |
272 | |
273 | proc_jz_root = proc_mkdir("jz", 0); |
274 | |
275 | /* External Memory Controller */ |
276 | res = create_proc_entry("emc", 0644, proc_jz_root); |
277 | if (res) { |
278 | res->read_proc = emc_read_proc; |
279 | res->write_proc = NULL; |
280 | res->data = NULL; |
281 | } |
282 | |
283 | /* Power Management Controller */ |
284 | res = create_proc_entry("pmc", 0644, proc_jz_root); |
285 | if (res) { |
286 | res->read_proc = pmc_read_proc; |
287 | res->write_proc = pmc_write_proc; |
288 | res->data = NULL; |
289 | } |
290 | |
291 | /* Clock Generation Module */ |
292 | res = create_proc_entry("cgm", 0644, proc_jz_root); |
293 | if (res) { |
294 | res->read_proc = cgm_read_proc; |
295 | res->write_proc = cgm_write_proc; |
296 | res->data = NULL; |
297 | } |
298 | |
299 | /* udc hotplug */ |
300 | res = create_proc_entry("udc", 0644, proc_jz_root); |
301 | if (res) { |
302 | res->read_proc = udc_read_proc; |
303 | res->write_proc = NULL; |
304 | res->data = NULL; |
305 | } |
306 | |
307 | return 0; |
308 | } |
309 | |
310 | __initcall(jz_proc_init); |
311 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9