1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for atomisp driver sysfs interface
4 *
5 * Copyright (c) 2014 Intel Corporation. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *
17 */
18
19 #include <linux/device.h>
20 #include <linux/err.h>
21 #include <linux/kernel.h>
22
23 #include "atomisp_compat.h"
24 #include "atomisp_internal.h"
25 #include "atomisp_ioctl.h"
26 #include "atomisp_drvfs.h"
27 #include "hmm/hmm.h"
28 #include "ia_css_debug.h"
29
30 /*
31 * _iunit_debug:
32 * dbglvl: iunit css driver trace level
33 * dbgopt: iunit debug option:
34 * bit 0: binary list
35 * bit 1: running binary
36 * bit 2: memory statistic
37 */
38 struct _iunit_debug {
39 struct device_driver *drv;
40 struct atomisp_device *isp;
41 unsigned int dbglvl;
42 unsigned int dbgfun;
43 unsigned int dbgopt;
44 };
45
46 #define OPTION_BIN_LIST BIT(0)
47 #define OPTION_BIN_RUN BIT(1)
48 #define OPTION_VALID (OPTION_BIN_LIST \
49 | OPTION_BIN_RUN)
50
51 static struct _iunit_debug iunit_debug = {
52 .dbglvl = 0,
53 .dbgopt = OPTION_BIN_LIST,
54 };
55
iunit_dump_dbgopt(struct atomisp_device * isp,unsigned int opt)56 static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
57 unsigned int opt)
58 {
59 int ret = 0;
60
61 if (opt & OPTION_VALID) {
62 if (opt & OPTION_BIN_LIST) {
63 ret = atomisp_css_dump_blob_infor(isp);
64 if (ret) {
65 dev_err(isp->dev, "%s dump blob infor err[ret:%d]\n",
66 __func__, ret);
67 goto opt_err;
68 }
69 }
70
71 if (opt & OPTION_BIN_RUN) {
72 if (isp->asd.streaming) {
73 atomisp_css_dump_sp_raw_copy_linecount(true);
74 atomisp_css_debug_dump_isp_binary();
75 } else {
76 ret = -EPERM;
77 dev_err(isp->dev, "%s dump running bin err[ret:%d]\n",
78 __func__, ret);
79 goto opt_err;
80 }
81 }
82 } else {
83 ret = -EINVAL;
84 dev_err(isp->dev, "%s dump nothing[ret=%d]\n", __func__, ret);
85 }
86
87 opt_err:
88 return ret;
89 }
90
iunit_dbglvl_show(struct device_driver * drv,char * buf)91 static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf)
92 {
93 iunit_debug.dbglvl = dbg_level;
94 return sysfs_emit(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
95 }
96
iunit_dbglvl_store(struct device_driver * drv,const char * buf,size_t size)97 static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
98 size_t size)
99 {
100 if (kstrtouint(buf, 10, &iunit_debug.dbglvl)
101 || iunit_debug.dbglvl < 1
102 || iunit_debug.dbglvl > 9) {
103 return -ERANGE;
104 }
105 ia_css_debug_set_dtrace_level(iunit_debug.dbglvl);
106
107 return size;
108 }
109
iunit_dbgfun_show(struct device_driver * drv,char * buf)110 static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf)
111 {
112 iunit_debug.dbgfun = atomisp_get_css_dbgfunc();
113 return sysfs_emit(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
114 }
115
iunit_dbgfun_store(struct device_driver * drv,const char * buf,size_t size)116 static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
117 size_t size)
118 {
119 unsigned int opt;
120 int ret;
121
122 ret = kstrtouint(buf, 10, &opt);
123 if (ret)
124 return ret;
125
126 ret = atomisp_set_css_dbgfunc(iunit_debug.isp, opt);
127 if (ret)
128 return ret;
129
130 iunit_debug.dbgfun = opt;
131
132 return size;
133 }
134
iunit_dbgopt_show(struct device_driver * drv,char * buf)135 static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf)
136 {
137 return sysfs_emit(buf, "option:0x%x\n", iunit_debug.dbgopt);
138 }
139
iunit_dbgopt_store(struct device_driver * drv,const char * buf,size_t size)140 static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf,
141 size_t size)
142 {
143 unsigned int opt;
144 int ret;
145
146 ret = kstrtouint(buf, 10, &opt);
147 if (ret)
148 return ret;
149
150 iunit_debug.dbgopt = opt;
151 ret = iunit_dump_dbgopt(iunit_debug.isp, iunit_debug.dbgopt);
152 if (ret)
153 return ret;
154
155 return size;
156 }
157
158 static const struct driver_attribute iunit_drvfs_attrs[] = {
159 __ATTR(dbglvl, 0644, iunit_dbglvl_show, iunit_dbglvl_store),
160 __ATTR(dbgfun, 0644, iunit_dbgfun_show, iunit_dbgfun_store),
161 __ATTR(dbgopt, 0644, iunit_dbgopt_show, iunit_dbgopt_store),
162 };
163
iunit_drvfs_create_files(struct device_driver * drv)164 static int iunit_drvfs_create_files(struct device_driver *drv)
165 {
166 int i, ret = 0;
167
168 for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
169 ret |= driver_create_file(drv, &iunit_drvfs_attrs[i]);
170
171 return ret;
172 }
173
iunit_drvfs_remove_files(struct device_driver * drv)174 static void iunit_drvfs_remove_files(struct device_driver *drv)
175 {
176 int i;
177
178 for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
179 driver_remove_file(drv, &iunit_drvfs_attrs[i]);
180 }
181
atomisp_drvfs_init(struct atomisp_device * isp)182 int atomisp_drvfs_init(struct atomisp_device *isp)
183 {
184 struct device_driver *drv = isp->dev->driver;
185 int ret;
186
187 iunit_debug.isp = isp;
188 iunit_debug.drv = drv;
189
190 ret = iunit_drvfs_create_files(iunit_debug.drv);
191 if (ret) {
192 dev_err(isp->dev, "drvfs_create_files error: %d\n", ret);
193 iunit_drvfs_remove_files(iunit_debug.drv);
194 }
195
196 return ret;
197 }
198
atomisp_drvfs_exit(void)199 void atomisp_drvfs_exit(void)
200 {
201 iunit_drvfs_remove_files(iunit_debug.drv);
202 }
203