]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c
UBUNTU: SAUCE: IPU driver release WW52
[mirror_ubuntu-jammy-kernel.git] / drivers / media / pci / intel / ipu6 / ipu6-isys-gpc.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2020 Intel Corporation
3
4 #ifdef CONFIG_DEBUG_FS
5 #include <linux/debugfs.h>
6 #include <linux/pm_runtime.h>
7
8 #include "ipu-isys.h"
9 #include "ipu-platform-regs.h"
10
11 #define IPU_ISYS_GPC_NUM 16
12
13 #ifndef CONFIG_PM
14 #define pm_runtime_get_sync(d) 0
15 #define pm_runtime_put(d) 0
16 #endif
17
18 struct ipu_isys_gpc {
19 bool enable;
20 unsigned int route;
21 unsigned int source;
22 unsigned int sense;
23 unsigned int gpcindex;
24 void *prit;
25 };
26
27 struct ipu_isys_gpcs {
28 bool gpc_enable;
29 struct ipu_isys_gpc gpc[IPU_ISYS_GPC_NUM];
30 void *prit;
31 };
32
33 static int ipu6_isys_gpc_global_enable_get(void *data, u64 *val)
34 {
35 struct ipu_isys_gpcs *isys_gpcs = data;
36 struct ipu_isys *isys = isys_gpcs->prit;
37
38 mutex_lock(&isys->mutex);
39
40 *val = isys_gpcs->gpc_enable;
41
42 mutex_unlock(&isys->mutex);
43 return 0;
44 }
45
46 static int ipu6_isys_gpc_global_enable_set(void *data, u64 val)
47 {
48 struct ipu_isys_gpcs *isys_gpcs = data;
49 struct ipu_isys *isys = isys_gpcs->prit;
50 void __iomem *base;
51 int i, ret;
52
53 if (val != 0 && val != 1)
54 return -EINVAL;
55
56 if (!isys || !isys->pdata || !isys->pdata->base)
57 return -EINVAL;
58
59 mutex_lock(&isys->mutex);
60
61 base = isys->pdata->base + IPU_ISYS_GPC_BASE;
62
63 ret = pm_runtime_get_sync(&isys->adev->dev);
64 if (ret < 0) {
65 pm_runtime_put(&isys->adev->dev);
66 mutex_unlock(&isys->mutex);
67 return ret;
68 }
69
70 if (!val) {
71 writel(0x0, base + IPU_ISYS_GPREG_TRACE_TIMER_RST);
72 writel(0x0, base + IPU_ISF_CDC_MMU_GPC_OVERALL_ENABLE);
73 writel(0xffff, base + IPU_ISF_CDC_MMU_GPC_SOFT_RESET);
74 isys_gpcs->gpc_enable = false;
75 for (i = 0; i < IPU_ISYS_GPC_NUM; i++) {
76 isys_gpcs->gpc[i].enable = 0;
77 isys_gpcs->gpc[i].sense = 0;
78 isys_gpcs->gpc[i].route = 0;
79 isys_gpcs->gpc[i].source = 0;
80 }
81 pm_runtime_mark_last_busy(&isys->adev->dev);
82 pm_runtime_put_autosuspend(&isys->adev->dev);
83 } else {
84 /*
85 * Set gpc reg and start all gpc here.
86 * RST free running local timer.
87 */
88 writel(0x0, base + IPU_ISYS_GPREG_TRACE_TIMER_RST);
89 writel(0x1, base + IPU_ISYS_GPREG_TRACE_TIMER_RST);
90
91 for (i = 0; i < IPU_ISYS_GPC_NUM; i++) {
92 /* Enable */
93 writel(isys_gpcs->gpc[i].enable,
94 base + IPU_ISF_CDC_MMU_GPC_ENABLE0 + 4 * i);
95 /* Setting (route/source/sense) */
96 writel((isys_gpcs->gpc[i].sense
97 << IPU_GPC_SENSE_OFFSET)
98 + (isys_gpcs->gpc[i].route
99 << IPU_GPC_ROUTE_OFFSET)
100 + (isys_gpcs->gpc[i].source
101 << IPU_GPC_SOURCE_OFFSET),
102 base + IPU_ISF_CDC_MMU_GPC_CNT_SEL0 + 4 * i);
103 }
104
105 /* Soft reset and Overall Enable. */
106 writel(0x0, base + IPU_ISF_CDC_MMU_GPC_OVERALL_ENABLE);
107 writel(0xffff, base + IPU_ISF_CDC_MMU_GPC_SOFT_RESET);
108 writel(0x1, base + IPU_ISF_CDC_MMU_GPC_OVERALL_ENABLE);
109
110 isys_gpcs->gpc_enable = true;
111 }
112
113 mutex_unlock(&isys->mutex);
114 return 0;
115 }
116
117 DEFINE_SIMPLE_ATTRIBUTE(isys_gpc_globe_enable_fops,
118 ipu6_isys_gpc_global_enable_get,
119 ipu6_isys_gpc_global_enable_set, "%llu\n");
120
121 static int ipu6_isys_gpc_count_get(void *data, u64 *val)
122 {
123 struct ipu_isys_gpc *isys_gpc = data;
124 struct ipu_isys *isys = isys_gpc->prit;
125 void __iomem *base;
126
127 if (!isys || !isys->pdata || !isys->pdata->base)
128 return -EINVAL;
129
130 spin_lock(&isys->power_lock);
131 if (isys->power) {
132 base = isys->pdata->base + IPU_ISYS_GPC_BASE;
133 *val = readl(base + IPU_ISF_CDC_MMU_GPC_VALUE0
134 + 4 * isys_gpc->gpcindex);
135 } else {
136 *val = 0;
137 }
138 spin_unlock(&isys->power_lock);
139
140 return 0;
141 }
142
143 DEFINE_SIMPLE_ATTRIBUTE(isys_gpc_count_fops, ipu6_isys_gpc_count_get,
144 NULL, "%llu\n");
145
146 int ipu_isys_gpc_init_debugfs(struct ipu_isys *isys)
147 {
148 struct dentry *gpcdir;
149 struct dentry *dir;
150 struct dentry *file;
151 int i;
152 char gpcname[10];
153 struct ipu_isys_gpcs *isys_gpcs;
154
155 isys_gpcs = devm_kzalloc(&isys->adev->dev, sizeof(*isys_gpcs),
156 GFP_KERNEL);
157 if (!isys_gpcs)
158 return -ENOMEM;
159
160 gpcdir = debugfs_create_dir("gpcs", isys->debugfsdir);
161 if (IS_ERR(gpcdir))
162 return -ENOMEM;
163
164 isys_gpcs->prit = isys;
165 file = debugfs_create_file("enable", 0600, gpcdir, isys_gpcs,
166 &isys_gpc_globe_enable_fops);
167 if (IS_ERR(file))
168 goto err;
169
170 for (i = 0; i < IPU_ISYS_GPC_NUM; i++) {
171 sprintf(gpcname, "gpc%d", i);
172 dir = debugfs_create_dir(gpcname, gpcdir);
173 if (IS_ERR(dir))
174 goto err;
175
176 file = debugfs_create_bool("enable", 0600, dir,
177 &isys_gpcs->gpc[i].enable);
178 if (IS_ERR(file))
179 goto err;
180
181 debugfs_create_u32("source", 0600, dir,
182 &isys_gpcs->gpc[i].source);
183
184 debugfs_create_u32("route", 0600, dir,
185 &isys_gpcs->gpc[i].route);
186
187 debugfs_create_u32("sense", 0600, dir,
188 &isys_gpcs->gpc[i].sense);
189
190 isys_gpcs->gpc[i].gpcindex = i;
191 isys_gpcs->gpc[i].prit = isys;
192 file = debugfs_create_file("count", 0400, dir,
193 &isys_gpcs->gpc[i],
194 &isys_gpc_count_fops);
195 if (IS_ERR(file))
196 goto err;
197 }
198
199 return 0;
200
201 err:
202 debugfs_remove_recursive(gpcdir);
203 return -ENOMEM;
204 }
205 #endif