1 // SPDX-License-Identifier: GPL-2.0
2 /* clk-idt8t49n24x-debugfs.c - Debugfs support for 8T49N24x
4 * Copyright (C) 2018, Integrated Device Technology, Inc. <david.cater@idt.com>
6 * See https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
7 * This program is distributed "AS IS" and WITHOUT ANY WARRANTY;
8 * including the implied warranties of MERCHANTABILITY, FITNESS FOR
9 * A PARTICULAR PURPOSE, or NON-INFRINGEMENT.
12 #include <linux/debugfs.h>
13 #include <linux/i2c.h>
14 #include <linux/regmap.h>
15 #include <linux/slab.h>
17 #include "clk-idt8t49n24x-debugfs.h"
19 struct clk_idt24x_chip *idt24x_chip_fordebugfs;
21 static int idt24x_read_all_settings(
22 struct clk_idt24x_chip *chip, char *output_buffer, int count)
24 u8 settings[NUM_CONFIG_REGISTERS];
28 err = regmap_bulk_read(
29 chip->regmap, 0x0, settings, NUM_CONFIG_REGISTERS);
31 output_buffer[0] = '\0';
32 for (x = 0; x < ARRAY_SIZE(settings); x++) {
35 if ((strlen(output_buffer) + 4) > count)
37 sprintf(dbg, "%02x ", settings[x]);
38 strcat(output_buffer, dbg);
45 * idt24x_debugfs_writer_action - Write handler for the "action" debugfs file.
47 * @user_buffer: buffer of text written to file
48 * @count: size of text in buffer
49 * @position: pass in current position, return new position
51 * Return: result of call to simple_write_to_buffer
53 * Use the "action" file as a trigger for setting all requested
54 * rates. The driver doesn't get any notification when the files
55 * representing the Qx outputs are written to, so something else is
56 * needed to notify the driver that the device should be udpated.
58 * It doesn't matter what you write to the action debugs file. When the
59 * handler is called, the device will be updated.
61 static ssize_t idt24x_debugfs_writer_action(
62 struct file *fp, const char __user *user_buffer,
63 size_t count, loff_t *position)
68 bool needs_update = true;
69 struct i2c_client *client = idt24x_chip_fordebugfs->i2c_client;
71 if (count > DEBUGFS_BUFFER_LENGTH)
74 for (x = 0; x < NUM_OUTPUTS; x++) {
75 freq = idt24x_chip_fordebugfs->clk[x].debug_freq;
79 "%s: calling clk_set_rate with debug frequency for Q%i",
82 idt24x_chip_fordebugfs->clk[x].hw.clk, freq);
85 "error calling clk_set_rate for Q%i (%i)\n",
90 idt24x_chip_fordebugfs->clk[x].requested = 0;
92 "%s: debug frequency for Q%i not set; make sure clock is disabled",
99 "%s: calling idt24x_set_frequency to ensure any clocks that should be disabled are turned off.",
101 err = idt24x_set_frequency(idt24x_chip_fordebugfs);
103 dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
104 "%s: error calling idt24x_set_frequency (%i)\n",
110 return simple_write_to_buffer(
111 idt24x_chip_fordebugfs->dbg_cache, DEBUGFS_BUFFER_LENGTH,
112 position, user_buffer, count);
116 * idt24x_debugfs_reader_action - Read the "action" debugfs file.
118 * @user_buffer: buffer of text written to file
119 * @count: size of text in buffer
120 * @position: pass in current position, return new position
122 * Return: whatever was last written to the "action" debugfs file.
124 static ssize_t idt24x_debugfs_reader_action(
125 struct file *fp, char __user *user_buffer, size_t count,
128 return simple_read_from_buffer(
129 user_buffer, count, position, idt24x_chip_fordebugfs->dbg_cache,
130 DEBUGFS_BUFFER_LENGTH);
134 * idt24x_debugfs_reader_map - display the current registers on the device
136 * @user_buffer: buffer of text written to file
137 * @count: size of text in buffer
138 * @position: pass in current position, return new position
140 * Reads the current register map from the attached chip via I2C and
143 * Return: result of call to simple_read_from_buffer
145 static ssize_t idt24x_debugfs_reader_map(
146 struct file *fp, char __user *user_buffer, size_t count,
150 char *buf = kzalloc(5000, GFP_KERNEL);
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);
156 dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
157 "error calling idt24x_read_all_settings (%i)\n", err);
160 /* TMGCDR-1456. We're returning 1 byte too few. */
161 err = simple_read_from_buffer(
162 user_buffer, count, position, buf, strlen(buf));
168 * idt24x_handle_i2c_debug_token - process "token" written to the i2c file
169 * @dev: pointer to device structure
170 * @token: pointer to current char being examined
171 * @reg: pass in current register, or return register from token.
172 * @val: resulting array of bytes being parsed
173 * @nextbyte: position in val array to store next byte
175 * Utility function to operate on the current "token" (from within a
176 * space-delimited string) written to the i2c debugfs file. It will
177 * either be a register offset or a byte to be added to the val array.
178 * If it is added to the val array, auto-increment nextbyte.
180 * Return: 0 for success
182 static int idt24x_handle_i2c_debug_token(
183 const struct device *dev, char *token, unsigned int *reg,
184 u8 val[], u16 *nextbyte)
188 dev_dbg(dev, "got token (%s)\n", token);
190 err = kstrtouint(token, 16, reg);
192 dev_dbg(dev, "hex register address == 0x%x\n", *reg);
196 err = kstrtou8(token, 16, &temp);
198 dev_dbg(dev, "data byte == 0x%x\n", temp);
199 val[*nextbyte] = temp;
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");
208 dev_err(dev, "error when parsing data: %i\n", err);
213 * idt24x_debugfs_writer_i2c - debugfs handler for i2c file
215 * @user_buffer: buffer of text written to file
216 * @count: size of text in buffer
217 * @position: pass in current position, return new position
219 * Handler for the "i2c" debugfs file. Write to this file to write bytes
220 * via I2C to a particular offset.
222 * Usage: echo 006c 01 02 0D FF > i2c
224 * First 4 chars are the 2-byte i2c register offset. Then follow that
225 * with a sequence of 2-char bytes in hex format that you want to write
226 * starting at that offset.
228 * Return: result of simple_write_to_buffer
230 static ssize_t idt24x_debugfs_writer_i2c(struct file *fp,
231 const char __user *user_buffer,
232 size_t count, loff_t *position)
237 unsigned int reg = -1;
238 u8 val[WRITE_BLOCK_SIZE];
242 if (count > DEBUGFS_BUFFER_LENGTH)
245 for (x = 0; x < count; x++) {
246 token[x - start] = user_buffer[x];
247 if (user_buffer[x] == ' ') {
248 token[x - start] = '\0';
249 err = idt24x_handle_i2c_debug_token(
250 &idt24x_chip_fordebugfs->i2c_client->dev,
251 token, ®, val, &nextbyte);
258 /* handle the last token */
260 token[count - start] = '\0';
261 err = idt24x_handle_i2c_debug_token(
262 &idt24x_chip_fordebugfs->i2c_client->dev, token, ®,
266 if (!err && reg != -1 && nextbyte > 0) {
268 idt24x_chip_fordebugfs->i2c_client,
269 idt24x_chip_fordebugfs->regmap,
272 dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
273 "error writing data chip (%i)\n", err);
276 dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
277 "successfully wrote i2c data to chip");
280 return simple_write_to_buffer(
281 idt24x_chip_fordebugfs->dbg_cache, DEBUGFS_BUFFER_LENGTH,
282 position, user_buffer, count);
285 static const struct file_operations idt24x_fops_debug_action = {
286 .read = idt24x_debugfs_reader_action,
287 .write = idt24x_debugfs_writer_action,
290 static const struct file_operations idt24x_fops_debug_map = {
291 .read = idt24x_debugfs_reader_map
294 static const struct file_operations idt24x_fops_debug_i2c = {
295 .write = idt24x_debugfs_writer_i2c,
299 * idt24x_expose_via_debugfs - Set up all debugfs files
300 * @client: pointer to i2c_client structure
301 * @chip: Device data structure
303 * Sets up all debugfs files to use for debugging the driver.
304 * Return: error code. 0 if success or debugfs doesn't appear to be enabled.
306 int idt24x_expose_via_debugfs(struct i2c_client *client,
307 struct clk_idt24x_chip *chip)
312 * create root directory in /sys/kernel/debugfs
314 chip->debugfs_dirroot = debugfs_create_dir("idt24x", NULL);
315 if (!chip->debugfs_dirroot) {
316 /* debugfs probably not enabled. Don't fail the probe. */
321 * create files in the root directory. This requires read and
322 * write file operations
324 chip->debugfs_fileaction = debugfs_create_file(
325 "action", 0644, chip->debugfs_dirroot, NULL,
326 &idt24x_fops_debug_action);
327 if (!chip->debugfs_fileaction) {
328 dev_err(&client->dev,
329 "%s: error creating action file", __func__);
333 chip->debugfs_map = debugfs_create_file(
334 "map", 0444, chip->debugfs_dirroot, NULL,
335 &idt24x_fops_debug_map);
336 if (!chip->debugfs_map) {
337 dev_err(&client->dev,
338 "%s: error creating map file", __func__);
342 for (output_num = 0; output_num < NUM_OUTPUTS; output_num++) {
345 sprintf(name, "q%d", output_num);
346 chip->debugfs_fileqfreq[output_num] = debugfs_create_u64(
347 name, 0644, chip->debugfs_dirroot,
348 &chip->clk[output_num].debug_freq);
349 if (!chip->debugfs_fileqfreq[output_num]) {
350 dev_err(&client->dev,
351 "%s: error creating %s debugfs file",
357 chip->debugfs_filei2c = debugfs_create_file(
358 "i2c", 0644, chip->debugfs_dirroot, NULL,
359 &idt24x_fops_debug_i2c);
360 if (!chip->debugfs_filei2c) {
361 dev_err(&client->dev,
362 "%s: error creating i2c file", __func__);
366 dev_dbg(&client->dev, "%s: success", __func__);
367 idt24x_chip_fordebugfs = chip;
371 void idt24x_cleanup_debugfs(struct clk_idt24x_chip *chip)
373 debugfs_remove_recursive(chip->debugfs_dirroot);