drivers/hwmon/sbtsi_temp.c
Source file repositories/reference/linux-study-clean/drivers/hwmon/sbtsi_temp.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/hwmon/sbtsi_temp.c- Extension
.c- Size
- 6739 bytes
- Lines
- 251
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/err.hlinux/i2c.hlinux/init.hlinux/hwmon.hlinux/module.hlinux/of.hlinux/bitfield.h
Detected Declarations
struct sbtsi_datafunction sbtsi_reg_to_mcfunction sbtsi_mc_to_regfunction sbtsi_readfunction sbtsi_writefunction sbtsi_is_visiblefunction sbtsi_probe
Annotated Snippet
struct sbtsi_data {
struct i2c_client *client;
bool ext_range_mode;
bool read_order;
};
/*
* From SB-TSI spec: CPU temperature readings and limit registers encode the
* temperature in increments of 0.125 from 0 to 255.875. The "high byte"
* register encodes the base-2 of the integer portion, and the upper 3 bits of
* the "low byte" encode in base-2 the decimal portion.
*
* e.g. INT=0x19, DEC=0x20 represents 25.125 degrees Celsius
*
* Therefore temperature in millidegree Celsius =
* (INT + DEC / 256) * 1000 = (INT * 8 + DEC / 32) * 125
*/
static inline int sbtsi_reg_to_mc(s32 integer, s32 decimal)
{
return ((integer << 3) + (decimal >> 5)) * 125;
}
/*
* Inversely, given temperature in millidegree Celsius
* INT = (TEMP / 125) / 8
* DEC = ((TEMP / 125) % 8) * 32
* Caller have to make sure temp doesn't exceed 255875, the max valid value.
*/
static inline void sbtsi_mc_to_reg(s32 temp, u8 *integer, u8 *decimal)
{
temp /= 125;
*integer = temp >> 3;
*decimal = (temp & 0x7) << 5;
}
static int sbtsi_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct sbtsi_data *data = dev_get_drvdata(dev);
s32 temp_int, temp_dec;
switch (attr) {
case hwmon_temp_input:
if (data->read_order) {
temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_DEC);
temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_INT);
} else {
temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_INT);
temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_DEC);
}
break;
case hwmon_temp_max:
temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_HIGH_INT);
temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_HIGH_DEC);
break;
case hwmon_temp_min:
temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_LOW_INT);
temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_LOW_DEC);
break;
default:
return -EINVAL;
}
if (temp_int < 0)
return temp_int;
if (temp_dec < 0)
return temp_dec;
*val = sbtsi_reg_to_mc(temp_int, temp_dec);
if (data->ext_range_mode)
*val -= SBTSI_TEMP_EXT_RANGE_ADJ;
return 0;
}
static int sbtsi_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct sbtsi_data *data = dev_get_drvdata(dev);
int reg_int, reg_dec, err;
u8 temp_int, temp_dec;
switch (attr) {
case hwmon_temp_max:
reg_int = SBTSI_REG_TEMP_HIGH_INT;
reg_dec = SBTSI_REG_TEMP_HIGH_DEC;
break;
case hwmon_temp_min:
reg_int = SBTSI_REG_TEMP_LOW_INT;
Annotation
- Immediate include surface: `linux/err.h`, `linux/i2c.h`, `linux/init.h`, `linux/hwmon.h`, `linux/module.h`, `linux/of.h`, `linux/bitfield.h`.
- Detected declarations: `struct sbtsi_data`, `function sbtsi_reg_to_mc`, `function sbtsi_mc_to_reg`, `function sbtsi_read`, `function sbtsi_write`, `function sbtsi_is_visible`, `function sbtsi_probe`.
- Atlas domain: Driver Families / drivers/hwmon.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.