drivers/hwmon/tmp401.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/tmp401.c
Extension
.c
Size
19769 bytes
Lines
765
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

struct tmp401_data {
	struct i2c_client *client;
	struct regmap *regmap;
	enum chips kind;

	bool extended_range;

	/* hwmon API configuration data */
	u32 chip_channel_config[4];
	struct hwmon_channel_info chip_info;
	u32 temp_channel_config[4];
	struct hwmon_channel_info temp_info;
	const struct hwmon_channel_info *info[3];
	struct hwmon_chip_info chip;
};

/* regmap */

static bool tmp401_regmap_is_volatile(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case 0:			/* local temp msb */
	case 1:			/* remote temp msb */
	case 2:			/* status */
	case 0x10:		/* remote temp lsb */
	case 0x15:		/* local temp lsb */
	case 0x1b:		/* status (tmp432) */
	case 0x23 ... 0x24:	/* remote temp 2 msb / lsb */
	case 0x30 ... 0x37:	/* lowest/highest temp; status (tmp432) */
		return true;
	default:
		return false;
	}
}

static int tmp401_reg_read(void *context, unsigned int reg, unsigned int *val)
{
	struct tmp401_data *data = context;
	struct i2c_client *client = data->client;
	int regval;

	switch (reg) {
	case 0:			/* local temp msb */
	case 1:			/* remote temp msb */
	case 5:			/* local temp high limit msb */
	case 6:			/* local temp low limit msb */
	case 7:			/* remote temp ligh limit msb */
	case 8:			/* remote temp low limit msb */
	case 0x15:		/* remote temp 2 high limit msb */
	case 0x16:		/* remote temp 2 low limit msb */
	case 0x23:		/* remote temp 2 msb */
	case 0x30:		/* local temp minimum, tmp411 */
	case 0x32:		/* local temp maximum, tmp411 */
	case 0x34:		/* remote temp minimum, tmp411 */
	case 0xf6:		/* remote temp maximum, tmp411 (really 0x36) */
		/* work around register overlap between TMP411 and TMP432 */
		if (reg == 0xf6)
			reg = 0x36;
		regval = i2c_smbus_read_word_swapped(client, reg);
		if (regval < 0)
			return regval;
		*val = regval;
		break;
	case 0x19:		/* critical limits, 8-bit registers */
	case 0x1a:
	case 0x20:
		regval = i2c_smbus_read_byte_data(client, reg);
		if (regval < 0)
			return regval;
		*val = regval << 8;
		break;
	case 0x1b:
	case 0x35 ... 0x37:
		if (data->kind == tmp432) {
			regval = i2c_smbus_read_byte_data(client, reg);
			if (regval < 0)
				return regval;
			*val = regval;
			break;
		}
		/* simulate TMP432 status registers */
		regval = i2c_smbus_read_byte_data(client, TMP401_STATUS);
		if (regval < 0)
			return regval;
		*val = 0;
		switch (reg) {
		case 0x1b:	/* open / fault */
			if (regval & TMP401_STATUS_REMOTE_OPEN)
				*val |= BIT(1);
			break;

Annotation

Implementation Notes