drivers/platform/mellanox/mlxreg-io.c

Source file repositories/reference/linux-study-clean/drivers/platform/mellanox/mlxreg-io.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/mellanox/mlxreg-io.c
Extension
.c
Size
7648 bytes
Lines
287
Domain
Driver Families
Bucket
drivers/platform
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

struct mlxreg_io_priv_data {
	struct platform_device *pdev;
	struct mlxreg_core_platform_data *pdata;
	struct device *hwmon;
	struct attribute *mlxreg_io_attr[MLXREG_IO_ATT_NUM + 1];
	struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
	struct attribute_group group;
	const struct attribute_group *groups[2];
	int regsize;
	struct mutex io_lock; /* Protects user access. */
};

static int
mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
		  bool rw_flag, int regsize, u32 *regval)
{
	int i, val, ret;

	ret = regmap_read(regmap, data->reg, regval);
	if (ret)
		goto access_error;

	/*
	 * There are four kinds of attributes: single bit, full register's
	 * bits, bit sequence, bits in few registers For the first kind field
	 * mask indicates which bits are not related and field bit is set zero.
	 * For the second kind field mask is set to zero and field bit is set
	 * with all bits one. No special handling for such kind of attributes -
	 * pass value as is. For the third kind, the field mask indicates which
	 * bits are related and the field bit is set to the first bit number
	 * (from 1 to 32) is the bit sequence. For the fourth kind - the number
	 * of registers which should be read for getting an attribute are
	 * specified through 'data->regnum' field.
	 */
	if (!data->bit) {
		/* Single bit. */
		if (rw_flag) {
			/* For show: expose effective bit value as 0 or 1. */
			*regval = !!(*regval & ~data->mask);
		} else {
			/* For store: set effective bit value. */
			*regval &= data->mask;
			if (in_val)
				*regval |= ~data->mask;
		}
	} else if (data->mask) {
		/* Bit sequence. */
		if (rw_flag) {
			/* For show: mask and shift right. */
			*regval = ror32(*regval & data->mask, (data->bit - 1));
		} else {
			/* For store: shift to the position and mask. */
			in_val = rol32(in_val, data->bit - 1) & data->mask;
			/* Clear relevant bits and set them to new value. */
			*regval = (*regval & ~data->mask) | in_val;
		}
	} else {
		/*
		 * Some attributes could occupied few registers in case regmap
		 * bit size is 8 or 16. Compose such attributes from 'regnum'
		 * registers. Such attributes contain read-only data.
		 */
		for (i = 1; i < data->regnum; i++) {
			ret = regmap_read(regmap, data->reg + i, &val);
			if (ret)
				goto access_error;

			*regval |= rol32(val, regsize * i * 8);
		}
	}

access_error:
	return ret;
}

static ssize_t
mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
		    char *buf)
{
	struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
	int index = to_sensor_dev_attr(attr)->index;
	struct mlxreg_core_data *data = priv->pdata->data + index;
	u32 regval = 0;
	int ret;

	mutex_lock(&priv->io_lock);

	ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true,
				priv->regsize, &regval);
	if (ret)

Annotation

Implementation Notes