Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.13-rc5 352 lines 8.6 kB view raw
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 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; // 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 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, 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 154err: 155 if (ret < 0) 156 memset(buf, 0xFF, len); // Never return undefined value 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, 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 215static 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 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; // 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 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}