drivers/hwmon/pmbus/stpddc60.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/pmbus/stpddc60.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/pmbus/stpddc60.c
Extension
.c
Size
5905 bytes
Lines
250
Domain
Driver Families
Bucket
drivers/hwmon
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-or-later
/*
 * Hardware monitoring driver for the STPDDC60 controller
 *
 * Copyright (c) 2021 Flextronics International Sweden AB.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/pmbus.h>
#include "pmbus.h"

#define STPDDC60_MFR_READ_VOUT		0xd2
#define STPDDC60_MFR_OV_LIMIT_OFFSET	0xe5
#define STPDDC60_MFR_UV_LIMIT_OFFSET	0xe6

static const struct i2c_device_id stpddc60_id[] = {
	{ .name = "stpddc60" },
	{ .name = "bmr481" },
	{ }
};
MODULE_DEVICE_TABLE(i2c, stpddc60_id);

static struct pmbus_driver_info stpddc60_info = {
	.pages = 1,
	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
		| PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
		| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
		| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
		| PMBUS_HAVE_POUT,
};

/*
 * Calculate the closest absolute offset between commanded vout value
 * and limit value in steps of 50mv in the range 0 (50mv) to 7 (400mv).
 * Return 0 if the upper limit is lower than vout or if the lower limit
 * is higher than vout.
 */
static u8 stpddc60_get_offset(int vout, u16 limit, bool over)
{
	int offset;
	long v, l;

	v = 250 + (vout - 1) * 5; /* Convert VID to mv */
	l = (limit * 1000L) >> 8; /* Convert LINEAR to mv */

	if (over == (l < v))
		return 0;

	offset = DIV_ROUND_CLOSEST(abs(l - v), 50);

	if (offset > 0)
		offset--;

	return clamp_val(offset, 0, 7);
}

/*
 * Adjust the linear format word to use the given fixed exponent.
 */
static u16 stpddc60_adjust_linear(u16 word, s16 fixed)
{
	s16 e, m, d;

	e = ((s16)word) >> 11;
	m = ((s16)((word & 0x7ff) << 5)) >> 5;
	d = e - fixed;

	if (d >= 0)
		m <<= d;
	else
		m >>= -d;

	return clamp_val(m, 0, 0x3ff) | ((fixed << 11) & 0xf800);
}

/*
 * The VOUT_COMMAND register uses the VID format but the vout alarm limit
 * registers use the LINEAR format so we override VOUT_MODE here to force
 * LINEAR format for all registers.
 */
static int stpddc60_read_byte_data(struct i2c_client *client, int page, int reg)
{
	int ret;

	if (page > 0)
		return -ENXIO;

Annotation

Implementation Notes