Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Low-level I/O functions.
0004  *
0005  * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
0006  * Copyright (c) 2010, ST-Ericsson
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; /* Never return undefined value */
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); /* Never return undefined value */
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; /* Never return undefined value */
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 }