0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/delay.h>
0010 #include <linux/slab.h>
0011 #include <linux/align.h>
0012
0013 #include "hwio.h"
0014 #include "wfx.h"
0015 #include "bus.h"
0016 #include "traces.h"
0017
0018 #define WFX_HIF_BUFFER_SIZE 0x2000
0019
0020 static int wfx_read32(struct wfx_dev *wdev, int reg, u32 *val)
0021 {
0022 int ret;
0023 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
0024
0025 *val = ~0;
0026 if (!tmp)
0027 return -ENOMEM;
0028 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
0029 if (ret >= 0)
0030 *val = le32_to_cpu(*tmp);
0031 kfree(tmp);
0032 if (ret)
0033 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
0034 return ret;
0035 }
0036
0037 static int wfx_write32(struct wfx_dev *wdev, int reg, u32 val)
0038 {
0039 int ret;
0040 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
0041
0042 if (!tmp)
0043 return -ENOMEM;
0044 *tmp = cpu_to_le32(val);
0045 ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
0046 kfree(tmp);
0047 if (ret)
0048 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
0049 return ret;
0050 }
0051
0052 static int wfx_read32_locked(struct wfx_dev *wdev, int reg, u32 *val)
0053 {
0054 int ret;
0055
0056 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0057 ret = wfx_read32(wdev, reg, val);
0058 _trace_io_read32(reg, *val);
0059 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0060 return ret;
0061 }
0062
0063 static int wfx_write32_locked(struct wfx_dev *wdev, int reg, u32 val)
0064 {
0065 int ret;
0066
0067 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0068 ret = wfx_write32(wdev, reg, val);
0069 _trace_io_write32(reg, val);
0070 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0071 return ret;
0072 }
0073
0074 static int wfx_write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val)
0075 {
0076 int ret;
0077 u32 val_r, val_w;
0078
0079 WARN_ON(~mask & val);
0080 val &= mask;
0081 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0082 ret = wfx_read32(wdev, reg, &val_r);
0083 _trace_io_read32(reg, val_r);
0084 if (ret < 0)
0085 goto err;
0086 val_w = (val_r & ~mask) | val;
0087 if (val_w != val_r) {
0088 ret = wfx_write32(wdev, reg, val_w);
0089 _trace_io_write32(reg, val_w);
0090 }
0091 err:
0092 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0093 return ret;
0094 }
0095
0096 static int wfx_indirect_read(struct wfx_dev *wdev, int reg, u32 addr, void *buf, size_t len)
0097 {
0098 int ret;
0099 int i;
0100 u32 cfg;
0101 u32 prefetch;
0102
0103 WARN_ON(len >= WFX_HIF_BUFFER_SIZE);
0104 WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
0105
0106 if (reg == WFX_REG_AHB_DPORT)
0107 prefetch = CFG_PREFETCH_AHB;
0108 else if (reg == WFX_REG_SRAM_DPORT)
0109 prefetch = CFG_PREFETCH_SRAM;
0110 else
0111 return -ENODEV;
0112
0113 ret = wfx_write32(wdev, WFX_REG_BASE_ADDR, addr);
0114 if (ret < 0)
0115 goto err;
0116
0117 ret = wfx_read32(wdev, WFX_REG_CONFIG, &cfg);
0118 if (ret < 0)
0119 goto err;
0120
0121 ret = wfx_write32(wdev, WFX_REG_CONFIG, cfg | prefetch);
0122 if (ret < 0)
0123 goto err;
0124
0125 for (i = 0; i < 20; i++) {
0126 ret = wfx_read32(wdev, WFX_REG_CONFIG, &cfg);
0127 if (ret < 0)
0128 goto err;
0129 if (!(cfg & prefetch))
0130 break;
0131 usleep_range(200, 250);
0132 }
0133 if (i == 20) {
0134 ret = -ETIMEDOUT;
0135 goto err;
0136 }
0137
0138 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len);
0139
0140 err:
0141 if (ret < 0)
0142 memset(buf, 0xFF, len);
0143 return ret;
0144 }
0145
0146 static int wfx_indirect_write(struct wfx_dev *wdev, int reg, u32 addr,
0147 const void *buf, size_t len)
0148 {
0149 int ret;
0150
0151 WARN_ON(len >= WFX_HIF_BUFFER_SIZE);
0152 WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
0153 ret = wfx_write32(wdev, WFX_REG_BASE_ADDR, addr);
0154 if (ret < 0)
0155 return ret;
0156
0157 return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len);
0158 }
0159
0160 static int wfx_indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr,
0161 void *buf, size_t len)
0162 {
0163 int ret;
0164
0165 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0166 ret = wfx_indirect_read(wdev, reg, addr, buf, len);
0167 _trace_io_ind_read(reg, addr, buf, len);
0168 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0169 return ret;
0170 }
0171
0172 static int wfx_indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr,
0173 const void *buf, size_t len)
0174 {
0175 int ret;
0176
0177 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0178 ret = wfx_indirect_write(wdev, reg, addr, buf, len);
0179 _trace_io_ind_write(reg, addr, buf, len);
0180 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0181 return ret;
0182 }
0183
0184 static int wfx_indirect_read32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 *val)
0185 {
0186 int ret;
0187 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
0188
0189 if (!tmp)
0190 return -ENOMEM;
0191 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0192 ret = wfx_indirect_read(wdev, reg, addr, tmp, sizeof(u32));
0193 *val = le32_to_cpu(*tmp);
0194 _trace_io_ind_read32(reg, addr, *val);
0195 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0196 kfree(tmp);
0197 return ret;
0198 }
0199
0200 static int wfx_indirect_write32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 val)
0201 {
0202 int ret;
0203 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);
0204
0205 if (!tmp)
0206 return -ENOMEM;
0207 *tmp = cpu_to_le32(val);
0208 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0209 ret = wfx_indirect_write(wdev, reg, addr, tmp, sizeof(u32));
0210 _trace_io_ind_write32(reg, addr, val);
0211 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0212 kfree(tmp);
0213 return ret;
0214 }
0215
0216 int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len)
0217 {
0218 int ret;
0219
0220 WARN(!IS_ALIGNED((uintptr_t)buf, 4), "unaligned buffer");
0221 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0222 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
0223 _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len);
0224 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0225 if (ret)
0226 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
0227 return ret;
0228 }
0229
0230 int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len)
0231 {
0232 int ret;
0233
0234 WARN(!IS_ALIGNED((uintptr_t)buf, 4), "unaligned buffer");
0235 wdev->hwbus_ops->lock(wdev->hwbus_priv);
0236 ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
0237 _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len);
0238 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
0239 if (ret)
0240 dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
0241 return ret;
0242 }
0243
0244 int wfx_sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
0245 {
0246 return wfx_indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
0247 }
0248
0249 int wfx_ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
0250 {
0251 return wfx_indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
0252 }
0253
0254 int wfx_sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
0255 {
0256 return wfx_indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
0257 }
0258
0259 int wfx_ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
0260 {
0261 return wfx_indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
0262 }
0263
0264 int wfx_sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
0265 {
0266 return wfx_indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
0267 }
0268
0269 int wfx_ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
0270 {
0271 return wfx_indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
0272 }
0273
0274 int wfx_sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
0275 {
0276 return wfx_indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
0277 }
0278
0279 int wfx_ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
0280 {
0281 return wfx_indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
0282 }
0283
0284 int wfx_config_reg_read(struct wfx_dev *wdev, u32 *val)
0285 {
0286 return wfx_read32_locked(wdev, WFX_REG_CONFIG, val);
0287 }
0288
0289 int wfx_config_reg_write(struct wfx_dev *wdev, u32 val)
0290 {
0291 return wfx_write32_locked(wdev, WFX_REG_CONFIG, val);
0292 }
0293
0294 int wfx_config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
0295 {
0296 return wfx_write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val);
0297 }
0298
0299 int wfx_control_reg_read(struct wfx_dev *wdev, u32 *val)
0300 {
0301 return wfx_read32_locked(wdev, WFX_REG_CONTROL, val);
0302 }
0303
0304 int wfx_control_reg_write(struct wfx_dev *wdev, u32 val)
0305 {
0306 return wfx_write32_locked(wdev, WFX_REG_CONTROL, val);
0307 }
0308
0309 int wfx_control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
0310 {
0311 return wfx_write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val);
0312 }
0313
0314 int wfx_igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val)
0315 {
0316 int ret;
0317
0318 *val = ~0;
0319 ret = wfx_write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24);
0320 if (ret)
0321 return ret;
0322 ret = wfx_read32_locked(wdev, WFX_REG_SET_GEN_R_W, val);
0323 if (ret)
0324 return ret;
0325 *val &= IGPR_VALUE;
0326 return ret;
0327 }
0328
0329 int wfx_igpr_reg_write(struct wfx_dev *wdev, int index, u32 val)
0330 {
0331 return wfx_write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val);
0332 }