drm/rockchip: Don't change hdmi reference clock rate
[drm/drm-misc.git] / drivers / net / wireless / silabs / wfx / hwio.c
blob3f9750b470bef0f34ca97a580ec7b5197c4d7c5d
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Low-level I/O functions.
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 #include <linux/align.h>
13 #include "hwio.h"
14 #include "wfx.h"
15 #include "bus.h"
16 #include "traces.h"
18 #define WFX_HIF_BUFFER_SIZE 0x2000
20 static int wfx_read32(struct wfx_dev *wdev, int reg, u32 *val)
22 int ret;
23 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
25 *val = ~0; /* Never return undefined value */
26 if (!tmp)
27 return -ENOMEM;
28 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
29 if (ret >= 0)
30 *val = le32_to_cpu(*tmp);
31 kfree(tmp);
32 if (ret)
33 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
34 return ret;
37 static int wfx_write32(struct wfx_dev *wdev, int reg, u32 val)
39 int ret;
40 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
42 if (!tmp)
43 return -ENOMEM;
44 *tmp = cpu_to_le32(val);
45 ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
46 kfree(tmp);
47 if (ret)
48 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
49 return ret;
52 static int wfx_read32_locked(struct wfx_dev *wdev, int reg, u32 *val)
54 int ret;
56 wdev->hwbus_ops->lock(wdev->hwbus_priv);
57 ret = wfx_read32(wdev, reg, val);
58 _trace_io_read32(reg, *val);
59 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
60 return ret;
63 static int wfx_write32_locked(struct wfx_dev *wdev, int reg, u32 val)
65 int ret;
67 wdev->hwbus_ops->lock(wdev->hwbus_priv);
68 ret = wfx_write32(wdev, reg, val);
69 _trace_io_write32(reg, val);
70 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
71 return ret;
74 static int wfx_write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val)
76 int ret;
77 u32 val_r, val_w;
79 WARN_ON(~mask & val);
80 val &= mask;
81 wdev->hwbus_ops->lock(wdev->hwbus_priv);
82 ret = wfx_read32(wdev, reg, &val_r);
83 _trace_io_read32(reg, val_r);
84 if (ret < 0)
85 goto err;
86 val_w = (val_r & ~mask) | val;
87 if (val_w != val_r) {
88 ret = wfx_write32(wdev, reg, val_w);
89 _trace_io_write32(reg, val_w);
91 err:
92 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
93 return ret;
96 static int wfx_indirect_read(struct wfx_dev *wdev, int reg, u32 addr, void *buf, size_t len)
98 int ret;
99 int i;
100 u32 cfg;
101 u32 prefetch;
103 WARN_ON(len >= WFX_HIF_BUFFER_SIZE);
104 WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
106 if (reg == WFX_REG_AHB_DPORT)
107 prefetch = CFG_PREFETCH_AHB;
108 else if (reg == WFX_REG_SRAM_DPORT)
109 prefetch = CFG_PREFETCH_SRAM;
110 else
111 return -ENODEV;
113 ret = wfx_write32(wdev, WFX_REG_BASE_ADDR, addr);
114 if (ret < 0)
115 goto err;
117 ret = wfx_read32(wdev, WFX_REG_CONFIG, &cfg);
118 if (ret < 0)
119 goto err;
121 ret = wfx_write32(wdev, WFX_REG_CONFIG, cfg | prefetch);
122 if (ret < 0)
123 goto err;
125 for (i = 0; i < 20; i++) {
126 ret = wfx_read32(wdev, WFX_REG_CONFIG, &cfg);
127 if (ret < 0)
128 goto err;
129 if (!(cfg & prefetch))
130 break;
131 usleep_range(200, 250);
133 if (i == 20) {
134 ret = -ETIMEDOUT;
135 goto err;
138 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len);
140 err:
141 if (ret < 0)
142 memset(buf, 0xFF, len); /* Never return undefined value */
143 return ret;
146 static int wfx_indirect_write(struct wfx_dev *wdev, int reg, u32 addr,
147 const void *buf, size_t len)
149 int ret;
151 WARN_ON(len >= WFX_HIF_BUFFER_SIZE);
152 WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
153 ret = wfx_write32(wdev, WFX_REG_BASE_ADDR, addr);
154 if (ret < 0)
155 return ret;
157 return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len);
160 static int wfx_indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr,
161 void *buf, size_t len)
163 int ret;
165 wdev->hwbus_ops->lock(wdev->hwbus_priv);
166 ret = wfx_indirect_read(wdev, reg, addr, buf, len);
167 _trace_io_ind_read(reg, addr, buf, len);
168 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
169 return ret;
172 static int wfx_indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr,
173 const void *buf, size_t len)
175 int ret;
177 wdev->hwbus_ops->lock(wdev->hwbus_priv);
178 ret = wfx_indirect_write(wdev, reg, addr, buf, len);
179 _trace_io_ind_write(reg, addr, buf, len);
180 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
181 return ret;
184 static int wfx_indirect_read32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 *val)
186 int ret;
187 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
189 if (!tmp)
190 return -ENOMEM;
191 wdev->hwbus_ops->lock(wdev->hwbus_priv);
192 ret = wfx_indirect_read(wdev, reg, addr, tmp, sizeof(u32));
193 *val = le32_to_cpu(*tmp);
194 _trace_io_ind_read32(reg, addr, *val);
195 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
196 kfree(tmp);
197 return ret;
200 static int wfx_indirect_write32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 val)
202 int ret;
203 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
205 if (!tmp)
206 return -ENOMEM;
207 *tmp = cpu_to_le32(val);
208 wdev->hwbus_ops->lock(wdev->hwbus_priv);
209 ret = wfx_indirect_write(wdev, reg, addr, tmp, sizeof(u32));
210 _trace_io_ind_write32(reg, addr, val);
211 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
212 kfree(tmp);
213 return ret;
216 int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len)
218 int ret;
220 WARN(!IS_ALIGNED((uintptr_t)buf, 4), "unaligned buffer");
221 wdev->hwbus_ops->lock(wdev->hwbus_priv);
222 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
223 _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len);
224 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
225 if (ret)
226 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
227 return ret;
230 int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len)
232 int ret;
234 WARN(!IS_ALIGNED((uintptr_t)buf, 4), "unaligned buffer");
235 wdev->hwbus_ops->lock(wdev->hwbus_priv);
236 ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
237 _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len);
238 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
239 if (ret)
240 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
241 return ret;
244 int wfx_sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
246 return wfx_indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
249 int wfx_ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
251 return wfx_indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
254 int wfx_sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
256 return wfx_indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
259 int wfx_ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
261 return wfx_indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
264 int wfx_sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
266 return wfx_indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
269 int wfx_ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
271 return wfx_indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
274 int wfx_sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
276 return wfx_indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
279 int wfx_ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
281 return wfx_indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
284 int wfx_config_reg_read(struct wfx_dev *wdev, u32 *val)
286 return wfx_read32_locked(wdev, WFX_REG_CONFIG, val);
289 int wfx_config_reg_write(struct wfx_dev *wdev, u32 val)
291 return wfx_write32_locked(wdev, WFX_REG_CONFIG, val);
294 int wfx_config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
296 return wfx_write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val);
299 int wfx_control_reg_read(struct wfx_dev *wdev, u32 *val)
301 return wfx_read32_locked(wdev, WFX_REG_CONTROL, val);
304 int wfx_control_reg_write(struct wfx_dev *wdev, u32 val)
306 return wfx_write32_locked(wdev, WFX_REG_CONTROL, val);
309 int wfx_control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
311 return wfx_write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val);
314 int wfx_igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val)
316 int ret;
318 *val = ~0; /* Never return undefined value */
319 ret = wfx_write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24);
320 if (ret)
321 return ret;
322 ret = wfx_read32_locked(wdev, WFX_REG_SET_GEN_R_W, val);
323 if (ret)
324 return ret;
325 *val &= IGPR_VALUE;
326 return ret;
329 int wfx_igpr_reg_write(struct wfx_dev *wdev, int index, u32 val)
331 return wfx_write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val);