diff options
author | Ben Dooks <ben@simtec.co.uk> | 2009-07-30 18:23:42 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2009-07-30 18:22:56 -0400 |
commit | e6d197a6954c8a9ff85727c31ca61fc1da78628a (patch) | |
tree | 4f83b37f17499111ae9381746b3427996eb75007 /arch/arm/plat-s3c24xx | |
parent | dfff4e95d749c414af3f7350835139103408a50d (diff) |
ARM: S3C: CPUFREQ: Add debugfs support for cpufreq
Add debugfs support for the cpufreq driver to allow
information about the system state to be exported to
the user.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r-- | arch/arm/plat-s3c24xx/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/cpu-freq-debugfs.c | 199 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/cpu-freq.c | 12 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h | 24 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/s3c2410-iotiming.c | 45 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/s3c2412-iotiming.c | 24 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/s3c2440-cpufreq.c | 2 |
7 files changed, 307 insertions, 0 deletions
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index 8759c070fd9a..f34937515804 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile | |||
@@ -21,6 +21,7 @@ obj-y += clock.o | |||
21 | obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o | 21 | obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o |
22 | 22 | ||
23 | obj-$(CONFIG_CPU_FREQ_S3C24XX) += cpu-freq.o | 23 | obj-$(CONFIG_CPU_FREQ_S3C24XX) += cpu-freq.o |
24 | obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpu-freq-debugfs.o | ||
24 | 25 | ||
25 | # Architecture dependant builds | 26 | # Architecture dependant builds |
26 | 27 | ||
diff --git a/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c b/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c new file mode 100644 index 000000000000..a9276667c2fb --- /dev/null +++ b/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c | ||
2 | * | ||
3 | * Copyright (c) 2009 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C24XX CPU Frequency scaling - debugfs status support | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/ioport.h> | ||
18 | #include <linux/cpufreq.h> | ||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/err.h> | ||
22 | |||
23 | #include <plat/cpu-freq-core.h> | ||
24 | |||
25 | static struct dentry *dbgfs_root; | ||
26 | static struct dentry *dbgfs_file_io; | ||
27 | static struct dentry *dbgfs_file_info; | ||
28 | static struct dentry *dbgfs_file_board; | ||
29 | |||
30 | #define print_ns(x) ((x) / 10), ((x) % 10) | ||
31 | |||
32 | static void show_max(struct seq_file *seq, struct s3c_freq *f) | ||
33 | { | ||
34 | seq_printf(seq, "MAX: F=%lu, H=%lu, P=%lu, A=%lu\n", | ||
35 | f->fclk, f->hclk, f->pclk, f->armclk); | ||
36 | } | ||
37 | |||
38 | static int board_show(struct seq_file *seq, void *p) | ||
39 | { | ||
40 | struct s3c_cpufreq_config *cfg; | ||
41 | struct s3c_cpufreq_board *brd; | ||
42 | |||
43 | cfg = s3c_cpufreq_getconfig(); | ||
44 | if (!cfg) { | ||
45 | seq_printf(seq, "no configuration registered\n"); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | brd = cfg->board; | ||
50 | if (!brd) { | ||
51 | seq_printf(seq, "no board definition set?\n"); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | seq_printf(seq, "SDRAM refresh %u ns\n", brd->refresh); | ||
56 | seq_printf(seq, "auto_io=%u\n", brd->auto_io); | ||
57 | seq_printf(seq, "need_io=%u\n", brd->need_io); | ||
58 | |||
59 | show_max(seq, &brd->max); | ||
60 | |||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int fops_board_open(struct inode *inode, struct file *file) | ||
66 | { | ||
67 | return single_open(file, board_show, NULL); | ||
68 | } | ||
69 | |||
70 | static const struct file_operations fops_board = { | ||
71 | .open = fops_board_open, | ||
72 | .read = seq_read, | ||
73 | .llseek = seq_lseek, | ||
74 | .release = single_release, | ||
75 | .owner = THIS_MODULE, | ||
76 | }; | ||
77 | |||
78 | static int info_show(struct seq_file *seq, void *p) | ||
79 | { | ||
80 | struct s3c_cpufreq_config *cfg; | ||
81 | |||
82 | cfg = s3c_cpufreq_getconfig(); | ||
83 | if (!cfg) { | ||
84 | seq_printf(seq, "no configuration registered\n"); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | seq_printf(seq, " FCLK %ld Hz\n", cfg->freq.fclk); | ||
89 | seq_printf(seq, " HCLK %ld Hz (%lu.%lu ns)\n", | ||
90 | cfg->freq.hclk, print_ns(cfg->freq.hclk_tns)); | ||
91 | seq_printf(seq, " PCLK %ld Hz\n", cfg->freq.hclk); | ||
92 | seq_printf(seq, "ARMCLK %ld Hz\n", cfg->freq.armclk); | ||
93 | seq_printf(seq, "\n"); | ||
94 | |||
95 | show_max(seq, &cfg->max); | ||
96 | |||
97 | seq_printf(seq, "Divisors: P=%d, H=%d, A=%d, dvs=%s\n", | ||
98 | cfg->divs.h_divisor, cfg->divs.p_divisor, | ||
99 | cfg->divs.arm_divisor, cfg->divs.dvs ? "on" : "off"); | ||
100 | seq_printf(seq, "\n"); | ||
101 | |||
102 | seq_printf(seq, "lock_pll=%u\n", cfg->lock_pll); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int fops_info_open(struct inode *inode, struct file *file) | ||
108 | { | ||
109 | return single_open(file, info_show, NULL); | ||
110 | } | ||
111 | |||
112 | static const struct file_operations fops_info = { | ||
113 | .open = fops_info_open, | ||
114 | .read = seq_read, | ||
115 | .llseek = seq_lseek, | ||
116 | .release = single_release, | ||
117 | .owner = THIS_MODULE, | ||
118 | }; | ||
119 | |||
120 | static int io_show(struct seq_file *seq, void *p) | ||
121 | { | ||
122 | void (*show_bank)(struct seq_file *, struct s3c_cpufreq_config *, union s3c_iobank *); | ||
123 | struct s3c_cpufreq_config *cfg; | ||
124 | struct s3c_iotimings *iot; | ||
125 | union s3c_iobank *iob; | ||
126 | int bank; | ||
127 | |||
128 | cfg = s3c_cpufreq_getconfig(); | ||
129 | if (!cfg) { | ||
130 | seq_printf(seq, "no configuration registered\n"); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | show_bank = cfg->info->debug_io_show; | ||
135 | if (!show_bank) { | ||
136 | seq_printf(seq, "no code to show bank timing\n"); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | iot = s3c_cpufreq_getiotimings(); | ||
141 | if (!iot) { | ||
142 | seq_printf(seq, "no io timings registered\n"); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | seq_printf(seq, "hclk period is %lu.%lu ns\n", print_ns(cfg->freq.hclk_tns)); | ||
147 | |||
148 | for (bank = 0; bank < MAX_BANKS; bank++) { | ||
149 | iob = &iot->bank[bank]; | ||
150 | |||
151 | seq_printf(seq, "bank %d: ", bank); | ||
152 | |||
153 | if (!iob->io_2410) { | ||
154 | seq_printf(seq, "nothing set\n"); | ||
155 | continue; | ||
156 | } | ||
157 | |||
158 | show_bank(seq, cfg, iob); | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int fops_io_open(struct inode *inode, struct file *file) | ||
165 | { | ||
166 | return single_open(file, io_show, NULL); | ||
167 | } | ||
168 | |||
169 | static const struct file_operations fops_io = { | ||
170 | .open = fops_io_open, | ||
171 | .read = seq_read, | ||
172 | .llseek = seq_lseek, | ||
173 | .release = single_release, | ||
174 | .owner = THIS_MODULE, | ||
175 | }; | ||
176 | |||
177 | |||
178 | static int __init s3c_freq_debugfs_init(void) | ||
179 | { | ||
180 | dbgfs_root = debugfs_create_dir("s3c-cpufreq", NULL); | ||
181 | if (IS_ERR(dbgfs_root)) { | ||
182 | printk(KERN_ERR "%s: error creating debugfs root\n", __func__); | ||
183 | return PTR_ERR(dbgfs_root); | ||
184 | } | ||
185 | |||
186 | dbgfs_file_io = debugfs_create_file("io-timing", S_IRUGO, dbgfs_root, | ||
187 | NULL, &fops_io); | ||
188 | |||
189 | dbgfs_file_info = debugfs_create_file("info", S_IRUGO, dbgfs_root, | ||
190 | NULL, &fops_info); | ||
191 | |||
192 | dbgfs_file_board = debugfs_create_file("board", S_IRUGO, dbgfs_root, | ||
193 | NULL, &fops_board); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | late_initcall(s3c_freq_debugfs_init); | ||
199 | |||
diff --git a/arch/arm/plat-s3c24xx/cpu-freq.c b/arch/arm/plat-s3c24xx/cpu-freq.c index 40ff7e2569dc..4f1b789a1173 100644 --- a/arch/arm/plat-s3c24xx/cpu-freq.c +++ b/arch/arm/plat-s3c24xx/cpu-freq.c | |||
@@ -50,6 +50,18 @@ static struct clk *clk_hclk; | |||
50 | static struct clk *clk_pclk; | 50 | static struct clk *clk_pclk; |
51 | static struct clk *clk_arm; | 51 | static struct clk *clk_arm; |
52 | 52 | ||
53 | #ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS | ||
54 | struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void) | ||
55 | { | ||
56 | return &cpu_cur; | ||
57 | } | ||
58 | |||
59 | struct s3c_iotimings *s3c_cpufreq_getiotimings(void) | ||
60 | { | ||
61 | return &s3c24xx_iotiming; | ||
62 | } | ||
63 | #endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUGFS */ | ||
64 | |||
53 | static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg) | 65 | static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg) |
54 | { | 66 | { |
55 | unsigned long fclk, pclk, hclk, armclk; | 67 | unsigned long fclk, pclk, hclk, armclk; |
diff --git a/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h b/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h index f02b3c06c1e0..efeb025affc7 100644 --- a/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h +++ b/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include <plat/cpu-freq.h> | 14 | #include <plat/cpu-freq.h> |
15 | 15 | ||
16 | struct seq_file; | ||
17 | |||
16 | #define MAX_BANKS (8) | 18 | #define MAX_BANKS (8) |
17 | #define S3C2412_MAX_IO (8) | 19 | #define S3C2412_MAX_IO (8) |
18 | 20 | ||
@@ -181,6 +183,10 @@ struct s3c_cpufreq_info { | |||
181 | struct cpufreq_frequency_table *t, | 183 | struct cpufreq_frequency_table *t, |
182 | size_t table_size); | 184 | size_t table_size); |
183 | 185 | ||
186 | void (*debug_io_show)(struct seq_file *seq, | ||
187 | struct s3c_cpufreq_config *cfg, | ||
188 | union s3c_iobank *iob); | ||
189 | |||
184 | void (*set_refresh)(struct s3c_cpufreq_config *cfg); | 190 | void (*set_refresh)(struct s3c_cpufreq_config *cfg); |
185 | void (*set_fvco)(struct s3c_cpufreq_config *cfg); | 191 | void (*set_fvco)(struct s3c_cpufreq_config *cfg); |
186 | void (*set_divs)(struct s3c_cpufreq_config *cfg); | 192 | void (*set_divs)(struct s3c_cpufreq_config *cfg); |
@@ -191,6 +197,24 @@ extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info); | |||
191 | 197 | ||
192 | extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no); | 198 | extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no); |
193 | 199 | ||
200 | /* exports and utilities for debugfs */ | ||
201 | extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void); | ||
202 | extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void); | ||
203 | |||
204 | extern void s3c2410_iotiming_debugfs(struct seq_file *seq, | ||
205 | struct s3c_cpufreq_config *cfg, | ||
206 | union s3c_iobank *iob); | ||
207 | |||
208 | extern void s3c2412_iotiming_debugfs(struct seq_file *seq, | ||
209 | struct s3c_cpufreq_config *cfg, | ||
210 | union s3c_iobank *iob); | ||
211 | |||
212 | #ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS | ||
213 | #define s3c_cpufreq_debugfs_call(x) x | ||
214 | #else | ||
215 | #define s3c_cpufreq_debugfs_call(x) NULL | ||
216 | #endif | ||
217 | |||
194 | /* Useful utility functions. */ | 218 | /* Useful utility functions. */ |
195 | 219 | ||
196 | extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *); | 220 | extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *); |
diff --git a/arch/arm/plat-s3c24xx/s3c2410-iotiming.c b/arch/arm/plat-s3c24xx/s3c2410-iotiming.c index 26fe2129cf25..d0a3a145cd4d 100644 --- a/arch/arm/plat-s3c24xx/s3c2410-iotiming.c +++ b/arch/arm/plat-s3c24xx/s3c2410-iotiming.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/cpufreq.h> | 17 | #include <linux/cpufreq.h> |
18 | #include <linux/seq_file.h> | ||
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
19 | 20 | ||
20 | #include <mach/map.h> | 21 | #include <mach/map.h> |
@@ -304,6 +305,50 @@ void s3c2410_iotiming_getbank(struct s3c_cpufreq_config *cfg, | |||
304 | } | 305 | } |
305 | 306 | ||
306 | /** | 307 | /** |
308 | * s3c2410_iotiming_debugfs - debugfs show io bank timing information | ||
309 | * @seq: The seq_file to write output to using seq_printf(). | ||
310 | * @cfg: The current configuration. | ||
311 | * @iob: The IO bank information to decode. | ||
312 | */ | ||
313 | void s3c2410_iotiming_debugfs(struct seq_file *seq, | ||
314 | struct s3c_cpufreq_config *cfg, | ||
315 | union s3c_iobank *iob) | ||
316 | { | ||
317 | struct s3c2410_iobank_timing *bt = iob->io_2410; | ||
318 | unsigned long bankcon = bt->bankcon; | ||
319 | unsigned long hclk = cfg->freq.hclk_tns; | ||
320 | unsigned int tacs; | ||
321 | unsigned int tcos; | ||
322 | unsigned int tacc; | ||
323 | unsigned int tcoh; | ||
324 | unsigned int tcah; | ||
325 | |||
326 | seq_printf(seq, "BANKCON=0x%08lx\n", bankcon); | ||
327 | |||
328 | tcah = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcah_SHIFT); | ||
329 | tcoh = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcoh_SHIFT); | ||
330 | tcos = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcos_SHIFT); | ||
331 | tacs = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tacs_SHIFT); | ||
332 | tacc = get_tacc(hclk, bankcon >> S3C2410_BANKCON_Tacc_SHIFT); | ||
333 | |||
334 | seq_printf(seq, | ||
335 | "\tRead: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, Tcoh=%d.%d, Tcah=%d.%d\n", | ||
336 | print_ns(bt->tacs), | ||
337 | print_ns(bt->tcos), | ||
338 | print_ns(bt->tacc), | ||
339 | print_ns(bt->tcoh), | ||
340 | print_ns(bt->tcah)); | ||
341 | |||
342 | seq_printf(seq, | ||
343 | "\t Set: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, Tcoh=%d.%d, Tcah=%d.%d\n", | ||
344 | print_ns(tacs), | ||
345 | print_ns(tcos), | ||
346 | print_ns(tacc), | ||
347 | print_ns(tcoh), | ||
348 | print_ns(tcah)); | ||
349 | } | ||
350 | |||
351 | /** | ||
307 | * s3c2410_iotiming_calc - Calculate bank timing for frequency change. | 352 | * s3c2410_iotiming_calc - Calculate bank timing for frequency change. |
308 | * @cfg: The frequency configuration | 353 | * @cfg: The frequency configuration |
309 | * @iot: The IO timing information to fill out. | 354 | * @iot: The IO timing information to fill out. |
diff --git a/arch/arm/plat-s3c24xx/s3c2412-iotiming.c b/arch/arm/plat-s3c24xx/s3c2412-iotiming.c index a3648cba0eb9..fd45e47facbc 100644 --- a/arch/arm/plat-s3c24xx/s3c2412-iotiming.c +++ b/arch/arm/plat-s3c24xx/s3c2412-iotiming.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/ioport.h> | 17 | #include <linux/ioport.h> |
18 | #include <linux/cpufreq.h> | 18 | #include <linux/cpufreq.h> |
19 | #include <linux/seq_file.h> | ||
19 | #include <linux/sysdev.h> | 20 | #include <linux/sysdev.h> |
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
@@ -109,6 +110,29 @@ static int s3c2412_calc_bank(struct s3c_cpufreq_config *cfg, | |||
109 | } | 110 | } |
110 | 111 | ||
111 | /** | 112 | /** |
113 | * s3c2412_iotiming_debugfs - debugfs show io bank timing information | ||
114 | * @seq: The seq_file to write output to using seq_printf(). | ||
115 | * @cfg: The current configuration. | ||
116 | * @iob: The IO bank information to decode. | ||
117 | */ | ||
118 | void s3c2412_iotiming_debugfs(struct seq_file *seq, | ||
119 | struct s3c_cpufreq_config *cfg, | ||
120 | union s3c_iobank *iob) | ||
121 | { | ||
122 | struct s3c2412_iobank_timing *bt = iob->io_2412; | ||
123 | |||
124 | seq_printf(seq, | ||
125 | "\tRead: idcy=%d.%d wstrd=%d.%d wstwr=%d,%d" | ||
126 | "wstoen=%d.%d wstwen=%d.%d wstbrd=%d.%d\n", | ||
127 | print_ns(bt->idcy), | ||
128 | print_ns(bt->wstrd), | ||
129 | print_ns(bt->wstwr), | ||
130 | print_ns(bt->wstoen), | ||
131 | print_ns(bt->wstwen), | ||
132 | print_ns(bt->wstbrd)); | ||
133 | } | ||
134 | |||
135 | /** | ||
112 | * s3c2412_iotiming_calc - calculate all the bank divisor settings. | 136 | * s3c2412_iotiming_calc - calculate all the bank divisor settings. |
113 | * @cfg: The current frequency configuration. | 137 | * @cfg: The current frequency configuration. |
114 | * @iot: The bank timing information. | 138 | * @iot: The bank timing information. |
diff --git a/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c b/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c index c177a20319e2..ae2e6c604f27 100644 --- a/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c +++ b/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c | |||
@@ -266,6 +266,8 @@ struct s3c_cpufreq_info s3c2440_cpufreq_info = { | |||
266 | .calc_freqtable = s3c2440_cpufreq_calctable, | 266 | .calc_freqtable = s3c2440_cpufreq_calctable, |
267 | 267 | ||
268 | .resume_clocks = s3c244x_setup_clocks, | 268 | .resume_clocks = s3c244x_setup_clocks, |
269 | |||
270 | .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), | ||
269 | }; | 271 | }; |
270 | 272 | ||
271 | static int s3c2440_cpufreq_add(struct sys_device *sysdev) | 273 | static int s3c2440_cpufreq_add(struct sys_device *sysdev) |