1
2
3
4
5
6
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
19
20
21
22
23
24
25
26
27
28
29static 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;
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
48static 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
65static 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
76static 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
87static 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 }
104err:
105 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
106 return ret;
107}
108
109static 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 udelay(200);
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
154err:
155 if (ret < 0)
156 memset(buf, 0xFF, len);
157 return ret;
158}
159
160static 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
174static 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
186static 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
198static 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
215static 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
232int 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
248int 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
264int 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
269int 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
274int 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
279int 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
284int 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
289int 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
294int 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
299int 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
304int config_reg_read(struct wfx_dev *wdev, u32 *val)
305{
306 return read32_locked(wdev, WFX_REG_CONFIG, val);
307}
308
309int config_reg_write(struct wfx_dev *wdev, u32 val)
310{
311 return write32_locked(wdev, WFX_REG_CONFIG, val);
312}
313
314int 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
319int control_reg_read(struct wfx_dev *wdev, u32 *val)
320{
321 return read32_locked(wdev, WFX_REG_CONTROL, val);
322}
323
324int control_reg_write(struct wfx_dev *wdev, u32 val)
325{
326 return write32_locked(wdev, WFX_REG_CONTROL, val);
327}
328
329int 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
334int igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val)
335{
336 int ret;
337
338 *val = ~0;
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
349int 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