Merge branch 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / staging / wfx / hwio.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Low-level I/O functions.
4  *
5  * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
6  * Copyright (c) 2010, ST-Ericsson
7  */
8 #include <linux/kernel.h>
9 #include <linux/delay.h>
10 #include <linux/slab.h>
11
12 #include "hwio.h"
13 #include "wfx.h"
14 #include "bus.h"
15 #include "traces.h"
16
17 /*
18  * Internal helpers.
19  *
20  * About CONFIG_VMAP_STACK:
21  * When CONFIG_VMAP_STACK is enabled, it is not possible to run DMA on stack
22  * allocated data. Functions below that work with registers (aka functions
23  * ending with "32") automatically reallocate buffers with kmalloc. However,
24  * functions that work with arbitrary length buffers let's caller to handle
25  * memory location. In doubt, enable CONFIG_DEBUG_SG to detect badly located
26  * buffer.
27  */
28
29 static int read32(struct wfx_dev *wdev, int reg, u32 *val)
30 {
31         int ret;
32         __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
33
34         *val = ~0; // Never return undefined value
35         if (!tmp)
36                 return -ENOMEM;
37         ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp,
38                                             sizeof(u32));
39         if (ret >= 0)
40                 *val = le32_to_cpu(*tmp);
41         kfree(tmp);
42         if (ret)
43                 dev_err(wdev->dev, "%s: bus communication error: %d\n",
44                         __func__, ret);
45         return ret;
46 }
47
48 static int write32(struct wfx_dev *wdev, int reg, u32 val)
49 {
50         int ret;
51         __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
52
53         if (!tmp)
54                 return -ENOMEM;
55         *tmp = cpu_to_le32(val);
56         ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp,
57                                           sizeof(u32));
58         kfree(tmp);
59         if (ret)
60                 dev_err(wdev->dev, "%s: bus communication error: %d\n",
61                         __func__, ret);
62         return ret;
63 }
64
65 static int read32_locked(struct wfx_dev *wdev, int reg, u32 *val)
66 {
67         int ret;
68
69         wdev->hwbus_ops->lock(wdev->hwbus_priv);
70         ret = read32(wdev, reg, val);
71         _trace_io_read32(reg, *val);
72         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
73         return ret;
74 }
75
76 static int write32_locked(struct wfx_dev *wdev, int reg, u32 val)
77 {
78         int ret;
79
80         wdev->hwbus_ops->lock(wdev->hwbus_priv);
81         ret = write32(wdev, reg, val);
82         _trace_io_write32(reg, val);
83         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
84         return ret;
85 }
86
87 static int write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val)
88 {
89         int ret;
90         u32 val_r, val_w;
91
92         WARN_ON(~mask & val);
93         val &= mask;
94         wdev->hwbus_ops->lock(wdev->hwbus_priv);
95         ret = read32(wdev, reg, &val_r);
96         _trace_io_read32(reg, val_r);
97         if (ret < 0)
98                 goto err;
99         val_w = (val_r & ~mask) | val;
100         if (val_w != val_r) {
101                 ret = write32(wdev, reg, val_w);
102                 _trace_io_write32(reg, val_w);
103         }
104 err:
105         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
106         return ret;
107 }
108
109 static int indirect_read(struct wfx_dev *wdev, int reg, u32 addr, void *buf,
110                          size_t len)
111 {
112         int ret;
113         int i;
114         u32 cfg;
115         u32 prefetch;
116
117         WARN_ON(len >= 0x2000);
118         WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
119
120         if (reg == WFX_REG_AHB_DPORT)
121                 prefetch = CFG_PREFETCH_AHB;
122         else if (reg == WFX_REG_SRAM_DPORT)
123                 prefetch = CFG_PREFETCH_SRAM;
124         else
125                 return -ENODEV;
126
127         ret = write32(wdev, WFX_REG_BASE_ADDR, addr);
128         if (ret < 0)
129                 goto err;
130
131         ret = read32(wdev, WFX_REG_CONFIG, &cfg);
132         if (ret < 0)
133                 goto err;
134
135         ret = write32(wdev, WFX_REG_CONFIG, cfg | prefetch);
136         if (ret < 0)
137                 goto err;
138
139         for (i = 0; i < 20; i++) {
140                 ret = read32(wdev, WFX_REG_CONFIG, &cfg);
141                 if (ret < 0)
142                         goto err;
143                 if (!(cfg & prefetch))
144                         break;
145                 usleep_range(200, 250);
146         }
147         if (i == 20) {
148                 ret = -ETIMEDOUT;
149                 goto err;
150         }
151
152         ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len);
153
154 err:
155         if (ret < 0)
156                 memset(buf, 0xFF, len); // Never return undefined value
157         return ret;
158 }
159
160 static int indirect_write(struct wfx_dev *wdev, int reg, u32 addr,
161                           const void *buf, size_t len)
162 {
163         int ret;
164
165         WARN_ON(len >= 0x2000);
166         WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
167         ret = write32(wdev, WFX_REG_BASE_ADDR, addr);
168         if (ret < 0)
169                 return ret;
170
171         return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len);
172 }
173
174 static int indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr,
175                                 void *buf, size_t len)
176 {
177         int ret;
178
179         wdev->hwbus_ops->lock(wdev->hwbus_priv);
180         ret = indirect_read(wdev, reg, addr, buf, len);
181         _trace_io_ind_read(reg, addr, buf, len);
182         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
183         return ret;
184 }
185
186 static int indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr,
187                                  const void *buf, size_t len)
188 {
189         int ret;
190
191         wdev->hwbus_ops->lock(wdev->hwbus_priv);
192         ret = indirect_write(wdev, reg, addr, buf, len);
193         _trace_io_ind_write(reg, addr, buf, len);
194         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
195         return ret;
196 }
197
198 static int indirect_read32_locked(struct wfx_dev *wdev, int reg, u32 addr,
199                                   u32 *val)
200 {
201         int ret;
202         __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
203
204         if (!tmp)
205                 return -ENOMEM;
206         wdev->hwbus_ops->lock(wdev->hwbus_priv);
207         ret = indirect_read(wdev, reg, addr, tmp, sizeof(u32));
208         *val = cpu_to_le32(*tmp);
209         _trace_io_ind_read32(reg, addr, *val);
210         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
211         kfree(tmp);
212         return ret;
213 }
214
215 static int indirect_write32_locked(struct wfx_dev *wdev, int reg, u32 addr,
216                                    u32 val)
217 {
218         int ret;
219         __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
220
221         if (!tmp)
222                 return -ENOMEM;
223         *tmp = cpu_to_le32(val);
224         wdev->hwbus_ops->lock(wdev->hwbus_priv);
225         ret = indirect_write(wdev, reg, addr, tmp, sizeof(u32));
226         _trace_io_ind_write32(reg, addr, val);
227         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
228         kfree(tmp);
229         return ret;
230 }
231
232 int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len)
233 {
234         int ret;
235
236         WARN((long) buf & 3, "%s: unaligned buffer", __func__);
237         wdev->hwbus_ops->lock(wdev->hwbus_priv);
238         ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv,
239                                             WFX_REG_IN_OUT_QUEUE, buf, len);
240         _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len);
241         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
242         if (ret)
243                 dev_err(wdev->dev, "%s: bus communication error: %d\n",
244                         __func__, ret);
245         return ret;
246 }
247
248 int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len)
249 {
250         int ret;
251
252         WARN((long) buf & 3, "%s: unaligned buffer", __func__);
253         wdev->hwbus_ops->lock(wdev->hwbus_priv);
254         ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv,
255                                           WFX_REG_IN_OUT_QUEUE, buf, len);
256         _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len);
257         wdev->hwbus_ops->unlock(wdev->hwbus_priv);
258         if (ret)
259                 dev_err(wdev->dev, "%s: bus communication error: %d\n",
260                         __func__, ret);
261         return ret;
262 }
263
264 int sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
265 {
266         return indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
267 }
268
269 int ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
270 {
271         return indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
272 }
273
274 int sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
275 {
276         return indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
277 }
278
279 int ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
280 {
281         return indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
282 }
283
284 int sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
285 {
286         return indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
287 }
288
289 int ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
290 {
291         return indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
292 }
293
294 int sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
295 {
296         return indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
297 }
298
299 int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
300 {
301         return indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
302 }
303
304 int config_reg_read(struct wfx_dev *wdev, u32 *val)
305 {
306         return read32_locked(wdev, WFX_REG_CONFIG, val);
307 }
308
309 int config_reg_write(struct wfx_dev *wdev, u32 val)
310 {
311         return write32_locked(wdev, WFX_REG_CONFIG, val);
312 }
313
314 int config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
315 {
316         return write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val);
317 }
318
319 int control_reg_read(struct wfx_dev *wdev, u32 *val)
320 {
321         return read32_locked(wdev, WFX_REG_CONTROL, val);
322 }
323
324 int control_reg_write(struct wfx_dev *wdev, u32 val)
325 {
326         return write32_locked(wdev, WFX_REG_CONTROL, val);
327 }
328
329 int control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
330 {
331         return write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val);
332 }
333
334 int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val)
335 {
336         int ret;
337
338         *val = ~0; // Never return undefined value
339         ret = write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24);
340         if (ret)
341                 return ret;
342         ret = read32_locked(wdev, WFX_REG_SET_GEN_R_W, val);
343         if (ret)
344                 return ret;
345         *val &= IGPR_VALUE;
346         return ret;
347 }
348
349 int igpr_reg_write(struct wfx_dev *wdev, int index, u32 val)
350 {
351         return write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val);
352 }