Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/wireless/silabs/wfx/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 8 kB image not shown  

Quelle  hwio.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Low-level I/O functions.
 *
 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
 * Copyright (c) 2010, ST-Ericsson
 */

#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/align.h>

#include "hwio.h"
#include "wfx.h"
#include "bus.h"
#include "traces.h"

#define WFX_HIF_BUFFER_SIZE 0x2000

static int wfx_read32(struct wfx_dev *wdev, int reg, u32 *val)
{
 int ret;
 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);

 *val = ~0; /* Never return undefined value */
 if (!tmp)
  return -ENOMEM;
 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
 if (ret >= 0)
  *val = le32_to_cpu(*tmp);
 kfree(tmp);
 if (ret)
  dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
 return ret;
}

static int wfx_write32(struct wfx_dev *wdev, int reg, u32 val)
{
 int ret;
 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);

 if (!tmp)
  return -ENOMEM;
 *tmp = cpu_to_le32(val);
 ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, tmp, sizeof(u32));
 kfree(tmp);
 if (ret)
  dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
 return ret;
}

static int wfx_read32_locked(struct wfx_dev *wdev, int reg, u32 *val)
{
 int ret;

 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_read32(wdev, reg, val);
 _trace_io_read32(reg, *val);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 return ret;
}

static int wfx_write32_locked(struct wfx_dev *wdev, int reg, u32 val)
{
 int ret;

 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_write32(wdev, reg, val);
 _trace_io_write32(reg, val);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 return ret;
}

static int wfx_write32_bits_locked(struct wfx_dev *wdev, int reg, u32 mask, u32 val)
{
 int ret;
 u32 val_r, val_w;

 WARN_ON(~mask & val);
 val &= mask;
 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_read32(wdev, reg, &val_r);
 _trace_io_read32(reg, val_r);
 if (ret < 0)
  goto err;
 val_w = (val_r & ~mask) | val;
 if (val_w != val_r) {
  ret = wfx_write32(wdev, reg, val_w);
  _trace_io_write32(reg, val_w);
 }
err:
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 return ret;
}

static int wfx_indirect_read(struct wfx_dev *wdev, int reg, u32 addr, void *buf, size_t len)
{
 int ret;
 int i;
 u32 cfg;
 u32 prefetch;

 WARN_ON(len >= WFX_HIF_BUFFER_SIZE);
 WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);

 if (reg == WFX_REG_AHB_DPORT)
  prefetch = CFG_PREFETCH_AHB;
 else if (reg == WFX_REG_SRAM_DPORT)
  prefetch = CFG_PREFETCH_SRAM;
 else
  return -ENODEV;

 ret = wfx_write32(wdev, WFX_REG_BASE_ADDR, addr);
 if (ret < 0)
  goto err;

 ret = wfx_read32(wdev, WFX_REG_CONFIG, &cfg);
 if (ret < 0)
  goto err;

 ret = wfx_write32(wdev, WFX_REG_CONFIG, cfg | prefetch);
 if (ret < 0)
  goto err;

 for (i = 0; i < 20; i++) {
  ret = wfx_read32(wdev, WFX_REG_CONFIG, &cfg);
  if (ret < 0)
   goto err;
  if (!(cfg & prefetch))
   break;
  usleep_range(200, 250);
 }
 if (i == 20) {
  ret = -ETIMEDOUT;
  goto err;
 }

 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, reg, buf, len);

err:
 if (ret < 0)
  memset(buf, 0xFF, len); /* Never return undefined value */
 return ret;
}

static int wfx_indirect_write(struct wfx_dev *wdev, int reg, u32 addr,
         const void *buf, size_t len)
{
 int ret;

 WARN_ON(len >= WFX_HIF_BUFFER_SIZE);
 WARN_ON(reg != WFX_REG_AHB_DPORT && reg != WFX_REG_SRAM_DPORT);
 ret = wfx_write32(wdev, WFX_REG_BASE_ADDR, addr);
 if (ret < 0)
  return ret;

 return wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, reg, buf, len);
}

static int wfx_indirect_read_locked(struct wfx_dev *wdev, int reg, u32 addr,
        void *buf, size_t len)
{
 int ret;

 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_indirect_read(wdev, reg, addr, buf, len);
 _trace_io_ind_read(reg, addr, buf, len);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 return ret;
}

static int wfx_indirect_write_locked(struct wfx_dev *wdev, int reg, u32 addr,
         const void *buf, size_t len)
{
 int ret;

 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_indirect_write(wdev, reg, addr, buf, len);
 _trace_io_ind_write(reg, addr, buf, len);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 return ret;
}

static int wfx_indirect_read32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 *val)
{
 int ret;
 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);

 if (!tmp)
  return -ENOMEM;
 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_indirect_read(wdev, reg, addr, tmp, sizeof(u32));
 *val = le32_to_cpu(*tmp);
 _trace_io_ind_read32(reg, addr, *val);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 kfree(tmp);
 return ret;
}

static int wfx_indirect_write32_locked(struct wfx_dev *wdev, int reg, u32 addr, u32 val)
{
 int ret;
 __le32 *tmp = kmalloc(sizeof(u32), GFP_KERNEL);

 if (!tmp)
  return -ENOMEM;
 *tmp = cpu_to_le32(val);
 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wfx_indirect_write(wdev, reg, addr, tmp, sizeof(u32));
 _trace_io_ind_write32(reg, addr, val);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 kfree(tmp);
 return ret;
}

int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t len)
{
 int ret;

 WARN(!IS_ALIGNED((uintptr_t)buf, 4), "unaligned buffer");
 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wdev->hwbus_ops->copy_from_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
 _trace_io_read(WFX_REG_IN_OUT_QUEUE, buf, len);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 if (ret)
  dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
 return ret;
}

int wfx_data_write(struct wfx_dev *wdev, const void *buf, size_t len)
{
 int ret;

 WARN(!IS_ALIGNED((uintptr_t)buf, 4), "unaligned buffer");
 wdev->hwbus_ops->lock(wdev->hwbus_priv);
 ret = wdev->hwbus_ops->copy_to_io(wdev->hwbus_priv, WFX_REG_IN_OUT_QUEUE, buf, len);
 _trace_io_write(WFX_REG_IN_OUT_QUEUE, buf, len);
 wdev->hwbus_ops->unlock(wdev->hwbus_priv);
 if (ret)
  dev_err(wdev->dev, "%s: bus communication error: %d\n", __func__, ret);
 return ret;
}

int wfx_sram_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
{
 return wfx_indirect_read_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
}

int wfx_ahb_buf_read(struct wfx_dev *wdev, u32 addr, void *buf, size_t len)
{
 return wfx_indirect_read_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
}

int wfx_sram_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
{
 return wfx_indirect_write_locked(wdev, WFX_REG_SRAM_DPORT, addr, buf, len);
}

int wfx_ahb_buf_write(struct wfx_dev *wdev, u32 addr, const void *buf, size_t len)
{
 return wfx_indirect_write_locked(wdev, WFX_REG_AHB_DPORT, addr, buf, len);
}

int wfx_sram_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
{
 return wfx_indirect_read32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
}

int wfx_ahb_reg_read(struct wfx_dev *wdev, u32 addr, u32 *val)
{
 return wfx_indirect_read32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
}

int wfx_sram_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
{
 return wfx_indirect_write32_locked(wdev, WFX_REG_SRAM_DPORT, addr, val);
}

int wfx_ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val)
{
 return wfx_indirect_write32_locked(wdev, WFX_REG_AHB_DPORT, addr, val);
}

int wfx_config_reg_read(struct wfx_dev *wdev, u32 *val)
{
 return wfx_read32_locked(wdev, WFX_REG_CONFIG, val);
}

int wfx_config_reg_write(struct wfx_dev *wdev, u32 val)
{
 return wfx_write32_locked(wdev, WFX_REG_CONFIG, val);
}

int wfx_config_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
{
 return wfx_write32_bits_locked(wdev, WFX_REG_CONFIG, mask, val);
}

int wfx_control_reg_read(struct wfx_dev *wdev, u32 *val)
{
 return wfx_read32_locked(wdev, WFX_REG_CONTROL, val);
}

int wfx_control_reg_write(struct wfx_dev *wdev, u32 val)
{
 return wfx_write32_locked(wdev, WFX_REG_CONTROL, val);
}

int wfx_control_reg_write_bits(struct wfx_dev *wdev, u32 mask, u32 val)
{
 return wfx_write32_bits_locked(wdev, WFX_REG_CONTROL, mask, val);
}

int wfx_igpr_reg_read(struct wfx_dev *wdev, int index, u32 *val)
{
 int ret;

 *val = ~0; /* Never return undefined value */
 ret = wfx_write32_locked(wdev, WFX_REG_SET_GEN_R_W, IGPR_RW | index << 24);
 if (ret)
  return ret;
 ret = wfx_read32_locked(wdev, WFX_REG_SET_GEN_R_W, val);
 if (ret)
  return ret;
 *val &= IGPR_VALUE;
 return ret;
}

int wfx_igpr_reg_write(struct wfx_dev *wdev, int index, u32 val)
{
 return wfx_write32_locked(wdev, WFX_REG_SET_GEN_R_W, index << 24 | val);
}

Messung V0.5
C=98 H=94 G=95

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.