1ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/*
2ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * drivers/misc/iwmc3200top/debufs.c
4ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
5ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Copyright (C) 2009 Intel Corporation. All rights reserved.
6ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
7ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * This program is free software; you can redistribute it and/or
8ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * modify it under the terms of the GNU General Public License version
9ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * 2 as published by the Free Software Foundation.
10ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
11ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * This program is distributed in the hope that it will be useful,
12ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * GNU General Public License for more details.
15ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
16ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * You should have received a copy of the GNU General Public License
17ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * along with this program; if not, write to the Free Software
18ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * 02110-1301, USA.
20ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
21ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
22ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
23ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *  -
24ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
25ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler */
26ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
27ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/kernel.h>
285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
29ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/string.h>
30ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/ctype.h>
31ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/mmc/sdio_func.h>
32ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/mmc/sdio.h>
33ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/debugfs.h>
34ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
35ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include "iwmc3200top.h"
36ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include "fw-msg.h"
37ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include "log.h"
38ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include "debugfs.h"
39ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
40ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
41ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
42ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/*      Constants definition        */
43ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define HEXADECIMAL_RADIX	16
44ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
45ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/*      Functions definition        */
46ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
47ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
48ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_ADD(name, parent) do {					\
49ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	dbgfs->dbgfs_##parent##_files.file_##name =			\
50ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv,	\
51ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler				&iwmct_dbgfs_##name##_ops);		\
52ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler} while (0)
53ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
54ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_RM(name)  do {		\
55ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	debugfs_remove(name);		\
56ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	name = NULL;			\
57ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler} while (0)
58ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
59ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_READ_FUNC(name)						\
60ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklerssize_t iwmct_dbgfs_##name##_read(struct file *file,			\
61ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler				  char __user *user_buf,		\
62ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler				  size_t count, loff_t *ppos);
63ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
64ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_WRITE_FUNC(name)					\
65ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklerssize_t iwmct_dbgfs_##name##_write(struct file *file,			\
66ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler				   const char __user *user_buf,		\
67ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler				   size_t count, loff_t *ppos);
68ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
69ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_READ_FILE_OPS(name)					\
70ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	DEBUGFS_READ_FUNC(name)						\
71ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
72ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.read = iwmct_dbgfs_##name##_read,			\
73ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.open = iwmct_dbgfs_open_file_generic,			\
742b18ab36cf7e956fb5b5ee12847e94fc66d496f4Arnd Bergmann		.llseek = generic_file_llseek,				\
75ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	};
76ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
77ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_WRITE_FILE_OPS(name)					\
78ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	DEBUGFS_WRITE_FUNC(name)					\
79ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
80ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.write = iwmct_dbgfs_##name##_write,			\
81ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.open = iwmct_dbgfs_open_file_generic,			\
822b18ab36cf7e956fb5b5ee12847e94fc66d496f4Arnd Bergmann		.llseek = generic_file_llseek,				\
83ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	};
84ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
85ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define DEBUGFS_READ_WRITE_FILE_OPS(name)				\
86ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	DEBUGFS_READ_FUNC(name)						\
87ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	DEBUGFS_WRITE_FUNC(name)					\
88ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	static const struct file_operations iwmct_dbgfs_##name##_ops = {\
89ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.write = iwmct_dbgfs_##name##_write,			\
90ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.read = iwmct_dbgfs_##name##_read,			\
91ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		.open = iwmct_dbgfs_open_file_generic,			\
922b18ab36cf7e956fb5b5ee12847e94fc66d496f4Arnd Bergmann		.llseek = generic_file_llseek,				\
93ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	};
94ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
95ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
96ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/*      Debugfs file ops definitions        */
97ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
98ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/*
99ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Create the debugfs files and directories
100ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
101ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler */
102ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklervoid iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
103ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler{
104ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	struct iwmct_debugfs *dbgfs;
105ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
106ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	dbgfs = kzalloc(sizeof(struct iwmct_debugfs), GFP_KERNEL);
107ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	if (!dbgfs) {
108ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		LOG_ERROR(priv, DEBUGFS, "failed to allocate %zd bytes\n",
109ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler					sizeof(struct iwmct_debugfs));
110ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		return;
111ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	}
112ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
113ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	priv->dbgfs = dbgfs;
114ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	dbgfs->name = name;
115ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	dbgfs->dir_drv = debugfs_create_dir(name, NULL);
116ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	if (!dbgfs->dir_drv) {
117ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		LOG_ERROR(priv, DEBUGFS, "failed to create debugfs dir\n");
118ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		return;
119ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	}
120ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
121ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	return;
122ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler}
123ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
124ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/**
125ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Remove the debugfs files and directories
126ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler *
127ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler */
128ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklervoid iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
129ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler{
130ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	if (!dbgfs)
131ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler		return;
132ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
133ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	DEBUGFS_RM(dbgfs->dir_drv);
134ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	kfree(dbgfs);
135ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler	dbgfs = NULL;
136ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler}
137ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler
138