1
2
3
4
5
6
7
8
9
10
11
12#include <linux/debugfs.h>
13#include <linux/i2c.h>
14#include <linux/regmap.h>
15#include <linux/slab.h>
16
17#include "clk-idt8t49n24x-debugfs.h"
18
19static struct clk_idt24x_chip *idt24x_chip_fordebugfs;
20
21static int idt24x_read_all_settings(
22 struct clk_idt24x_chip *chip, char *output_buffer, int count)
23{
24 u8 settings[NUM_CONFIG_REGISTERS];
25 int err = 0;
26 int x;
27
28 err = regmap_bulk_read(
29 chip->regmap, 0x0, settings, NUM_CONFIG_REGISTERS);
30 if (!err) {
31 output_buffer[0] = '\0';
32 for (x = 0; x < ARRAY_SIZE(settings); x++) {
33 char dbg[4];
34
35 if ((strlen(output_buffer) + 4) > count)
36 return -EINVAL;
37 sprintf(dbg, "%02x ", settings[x]);
38 strcat(output_buffer, dbg);
39 }
40 }
41 return err;
42}
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61static ssize_t idt24x_debugfs_writer_action(
62 struct file *fp, const char __user *user_buffer,
63 size_t count, loff_t *position)
64{
65 int err = 0;
66 int x;
67 u32 freq;
68 bool needs_update = true;
69 struct i2c_client *client = idt24x_chip_fordebugfs->i2c_client;
70
71 if (count > DEBUGFS_BUFFER_LENGTH)
72 return -EINVAL;
73
74 for (x = 0; x < NUM_OUTPUTS; x++) {
75 freq = idt24x_chip_fordebugfs->clk[x].debug_freq;
76 if (freq) {
77 needs_update = false;
78 dev_dbg(&client->dev,
79 "%s: calling clk_set_rate with debug frequency for Q%i",
80 __func__, x);
81 err = clk_set_rate(
82 idt24x_chip_fordebugfs->clk[x].hw.clk, freq);
83 if (err) {
84 dev_err(&client->dev,
85 "error calling clk_set_rate for Q%i (%i)\n",
86 x, err);
87 }
88 } else {
89 needs_update = true;
90 idt24x_chip_fordebugfs->clk[x].requested = 0;
91 dev_dbg(&client->dev,
92 "%s: debug frequency for Q%i not set; make sure clock is disabled",
93 __func__, x);
94 }
95 }
96
97 if (needs_update) {
98 dev_dbg(&client->dev,
99 "%s: calling idt24x_set_frequency to ensure any clocks that should be disabled are turned off.",
100 __func__);
101 err = idt24x_set_frequency(idt24x_chip_fordebugfs);
102 if (err) {
103 dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
104 "%s: error calling idt24x_set_frequency (%i)\n",
105 __func__, err);
106 return err;
107 }
108 }
109
110 return simple_write_to_buffer(
111 idt24x_chip_fordebugfs->dbg_cache, DEBUGFS_BUFFER_LENGTH,
112 position, user_buffer, count);
113}
114
115
116
117
118
119
120
121
122
123
124static ssize_t idt24x_debugfs_reader_action(
125 struct file *fp, char __user *user_buffer, size_t count,
126 loff_t *position)
127{
128 return simple_read_from_buffer(
129 user_buffer, count, position, idt24x_chip_fordebugfs->dbg_cache,
130 DEBUGFS_BUFFER_LENGTH);
131}
132
133
134
135
136
137
138
139
140
141
142
143
144
145static ssize_t idt24x_debugfs_reader_map(
146 struct file *fp, char __user *user_buffer, size_t count,
147 loff_t *position)
148{
149 int err = 0;
150 char *buf = kzalloc(5000, GFP_KERNEL);
151
152 dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
153 "calling idt24x_read_all_settings (count: %zu)\n", count);
154 err = idt24x_read_all_settings(idt24x_chip_fordebugfs, buf, 5000);
155 if (err) {
156 dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
157 "error calling idt24x_read_all_settings (%i)\n", err);
158 return 0;
159 }
160
161 err = simple_read_from_buffer(
162 user_buffer, count, position, buf, strlen(buf));
163 kfree(buf);
164 return err;
165}
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182static int idt24x_handle_i2c_debug_token(
183 const struct device *dev, char *token, unsigned int *reg,
184 u8 val[], u16 *nextbyte)
185{
186 int err = 0;
187
188 dev_dbg(dev, "got token (%s)\n", token);
189 if (*reg == -1) {
190 err = kstrtouint(token, 16, reg);
191 if (!err)
192 dev_dbg(dev, "hex register address == 0x%x\n", *reg);
193 } else {
194 u8 temp;
195
196 err = kstrtou8(token, 16, &temp);
197 if (!err) {
198 dev_dbg(dev, "data byte == 0x%x\n", temp);
199 val[*nextbyte] = temp;
200 *nextbyte += 1;
201 }
202 }
203 if (err == -ERANGE)
204 dev_err(dev, "ERANGE error when parsing data\n");
205 else if (err == -EINVAL)
206 dev_err(dev, "EINVAL error when parsing data\n");
207 else if (err)
208 dev_err(dev, "error when parsing data: %i\n", err);
209 return err;
210}
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230static ssize_t idt24x_debugfs_writer_i2c(struct file *fp,
231 const char __user *user_buffer,
232 size_t count, loff_t *position)
233{
234 int err = 0;
235 int x = 0;
236 int start = 0;
237 ssize_t written;
238 unsigned int reg = -1;
239 u8 val[WRITE_BLOCK_SIZE];
240 u16 nextbyte = 0;
241 char token[16];
242
243 if (count > DEBUGFS_BUFFER_LENGTH)
244 return -EINVAL;
245
246 written = simple_write_to_buffer(
247 idt24x_chip_fordebugfs->dbg_cache, DEBUGFS_BUFFER_LENGTH,
248 position, user_buffer, count);
249 if (written != count) {
250 dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
251 "write count != expected count");
252 return written;
253 }
254
255 for (x = 0; x < count; x++) {
256 token[x - start] = idt24x_chip_fordebugfs->dbg_cache[x];
257 if (idt24x_chip_fordebugfs->dbg_cache[x] == ' ') {
258 token[x - start] = '\0';
259 err = idt24x_handle_i2c_debug_token(
260 &idt24x_chip_fordebugfs->i2c_client->dev,
261 token, ®, val, &nextbyte);
262 if (err)
263 break;
264 start = x + 1;
265 }
266 }
267
268
269 if (!err) {
270 token[count - start] = '\0';
271 err = idt24x_handle_i2c_debug_token(
272 &idt24x_chip_fordebugfs->i2c_client->dev, token, ®,
273 val, &nextbyte);
274 }
275
276 if (!err && reg != -1 && nextbyte > 0) {
277 err = i2cwritebulk(
278 idt24x_chip_fordebugfs->i2c_client,
279 idt24x_chip_fordebugfs->regmap,
280 reg, val, nextbyte);
281 if (err) {
282 dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
283 "error writing data chip (%i)\n", err);
284 return err;
285 }
286 dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
287 "successfully wrote i2c data to chip");
288 }
289
290 return written;
291}
292
293static const struct file_operations idt24x_fops_debug_action = {
294 .read = idt24x_debugfs_reader_action,
295 .write = idt24x_debugfs_writer_action,
296};
297
298static const struct file_operations idt24x_fops_debug_map = {
299 .read = idt24x_debugfs_reader_map
300};
301
302static const struct file_operations idt24x_fops_debug_i2c = {
303 .write = idt24x_debugfs_writer_i2c,
304};
305
306
307
308
309
310
311
312
313
314int idt24x_expose_via_debugfs(struct i2c_client *client,
315 struct clk_idt24x_chip *chip)
316{
317 int output_num;
318
319
320
321
322 chip->debugfs_dirroot = debugfs_create_dir("idt24x", NULL);
323 if (!chip->debugfs_dirroot) {
324
325 return 0;
326 }
327
328
329
330
331
332 chip->debugfs_fileaction = debugfs_create_file(
333 "action", 0644, chip->debugfs_dirroot, NULL,
334 &idt24x_fops_debug_action);
335 if (!chip->debugfs_fileaction) {
336 dev_err(&client->dev,
337 "%s: error creating action file", __func__);
338 return (-ENODEV);
339 }
340
341 chip->debugfs_map = debugfs_create_file(
342 "map", 0444, chip->debugfs_dirroot, NULL,
343 &idt24x_fops_debug_map);
344 if (!chip->debugfs_map) {
345 dev_err(&client->dev,
346 "%s: error creating map file", __func__);
347 return (-ENODEV);
348 }
349
350 for (output_num = 0; output_num < NUM_OUTPUTS; output_num++) {
351 char name[5];
352
353 sprintf(name, "q%d", output_num);
354 debugfs_create_u64(name, 0644, chip->debugfs_dirroot,
355 &chip->clk[output_num].debug_freq);
356 }
357
358 chip->debugfs_filei2c = debugfs_create_file(
359 "i2c", 0644, chip->debugfs_dirroot, NULL,
360 &idt24x_fops_debug_i2c);
361 if (!chip->debugfs_filei2c) {
362 dev_err(&client->dev,
363 "%s: error creating i2c file", __func__);
364 return (-ENODEV);
365 }
366
367 dev_dbg(&client->dev, "%s: success", __func__);
368 idt24x_chip_fordebugfs = chip;
369 return 0;
370}
371
372void idt24x_cleanup_debugfs(struct clk_idt24x_chip *chip)
373{
374 debugfs_remove_recursive(chip->debugfs_dirroot);
375}
376