drivers/net/wireless/silabs/wfx/hwio.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/silabs/wfx/hwio.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/silabs/wfx/hwio.c
Extension
.c
Size
8438 bytes
Lines
333
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// 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);
	}

Annotation

Implementation Notes