• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Low-level I/O functions.
4  *
5  * Copyright (c) 2017-2020, 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 
read32(struct wfx_dev * wdev,int reg,u32 * val)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 
write32(struct wfx_dev * wdev,int reg,u32 val)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 
read32_locked(struct wfx_dev * wdev,int reg,u32 * val)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 
write32_locked(struct wfx_dev * wdev,int reg,u32 val)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 
write32_bits_locked(struct wfx_dev * wdev,int reg,u32 mask,u32 val)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 
indirect_read(struct wfx_dev * wdev,int reg,u32 addr,void * buf,size_t len)109 static int indirect_read(struct wfx_dev *wdev, int reg, u32 addr,
110 			 void *buf, 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 
indirect_write(struct wfx_dev * wdev,int reg,u32 addr,const void * buf,size_t len)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 
indirect_read_locked(struct wfx_dev * wdev,int reg,u32 addr,void * buf,size_t len)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 
indirect_write_locked(struct wfx_dev * wdev,int reg,u32 addr,const void * buf,size_t len)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 
indirect_read32_locked(struct wfx_dev * wdev,int reg,u32 addr,u32 * val)198 static int indirect_read32_locked(struct wfx_dev *wdev, int reg,
199 				  u32 addr, 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 = le32_to_cpu(*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 
indirect_write32_locked(struct wfx_dev * wdev,int reg,u32 addr,u32 val)215 static int indirect_write32_locked(struct wfx_dev *wdev, int reg,
216 				   u32 addr, 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 
wfx_data_read(struct wfx_dev * wdev,void * buf,size_t len)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 
wfx_data_write(struct wfx_dev * wdev,const void * buf,size_t len)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 
sram_buf_read(struct wfx_dev * wdev,u32 addr,void * buf,size_t len)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 
ahb_buf_read(struct wfx_dev * wdev,u32 addr,void * buf,size_t len)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 
sram_buf_write(struct wfx_dev * wdev,u32 addr,const void * buf,size_t len)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 
ahb_buf_write(struct wfx_dev * wdev,u32 addr,const void * buf,size_t len)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 
sram_reg_read(struct wfx_dev * wdev,u32 addr,u32 * val)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 
ahb_reg_read(struct wfx_dev * wdev,u32 addr,u32 * val)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 
sram_reg_write(struct wfx_dev * wdev,u32 addr,u32 val)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 
ahb_reg_write(struct wfx_dev * wdev,u32 addr,u32 val)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 
config_reg_read(struct wfx_dev * wdev,u32 * val)304 int config_reg_read(struct wfx_dev *wdev, u32 *val)
305 {
306 	return read32_locked(wdev, WFX_REG_CONFIG, val);
307 }
308 
config_reg_write(struct wfx_dev * wdev,u32 val)309 int config_reg_write(struct wfx_dev *wdev, u32 val)
310 {
311 	return write32_locked(wdev, WFX_REG_CONFIG, val);
312 }
313 
config_reg_write_bits(struct wfx_dev * wdev,u32 mask,u32 val)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 
control_reg_read(struct wfx_dev * wdev,u32 * val)319 int control_reg_read(struct wfx_dev *wdev, u32 *val)
320 {
321 	return read32_locked(wdev, WFX_REG_CONTROL, val);
322 }
323 
control_reg_write(struct wfx_dev * wdev,u32 val)324 int control_reg_write(struct wfx_dev *wdev, u32 val)
325 {
326 	return write32_locked(wdev, WFX_REG_CONTROL, val);
327 }
328 
control_reg_write_bits(struct wfx_dev * wdev,u32 mask,u32 val)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 
igpr_reg_read(struct wfx_dev * wdev,int index,u32 * val)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 
igpr_reg_write(struct wfx_dev * wdev,int index,u32 val)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 }
353