^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * adm9240.c Part of lm_sensors, Linux kernel modules for hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Philip Edelbrock <phil@netroedge.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2003 Michiel Rook <michiel@grendelproject.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2005 Grant Coady <gcoady.lk@gmail.com> with valuable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * guidance from Jean Delvare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Driver supports Analog Devices ADM9240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Dallas Semiconductor DS1780
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * National Semiconductor LM81
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * ADM9240 is the reference, DS1780 and LM81 are register compatibles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Voltage Six inputs are scaled by chip, VID also reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Temperature Chip temperature to 0.5'C, maximum and max_hysteris
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Fans 2 fans, low speed alarm, automatic fan clock divider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Alarms 16-bit map of active alarms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Analog Out 0..1250 mV output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Test hardware: Intel SE440BX-2 desktop motherboard --Grant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * LM81 extended temp reading not implemented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/hwmon-vid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Addresses to scan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) I2C_CLIENT_END };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) enum chips { adm9240, ds1780, lm81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* ADM9240 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ADM9240_REG_MAN_ID 0x3e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define ADM9240_REG_DIE_REV 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define ADM9240_REG_CONFIG 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ADM9240_REG_INT(nr) (0x41 + (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define ADM9240_REG_TEMP 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define ADM9240_REG_ANALOG_OUT 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ADM9240_REG_CHASSIS_CLEAR 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define ADM9240_REG_VID_FAN_DIV 0x47
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ADM9240_REG_I2C_ADDR 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define ADM9240_REG_VID4 0x49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define ADM9240_REG_TEMP_CONF 0x4b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* generalised scaling with integer rounding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static inline int SCALE(long val, int mul, int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return (val * mul - div / 2) / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return (val * mul + div / 2) / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* adm9240 internally scales voltage measurements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static inline unsigned int IN_FROM_REG(u8 reg, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return SCALE(reg, nom_mv[n], 192);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static inline u8 IN_TO_REG(unsigned long val, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) val = clamp_val(val, 0, nom_mv[n] * 255 / 192);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return SCALE(val, 192, nom_mv[n]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* temperature range: -40..125, 127 disables temperature alarm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static inline s8 TEMP_TO_REG(long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) val = clamp_val(val, -40000, 127000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return SCALE(val, 1, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* two fans, each with low fan speed limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!reg) /* error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (reg == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return SCALE(1350000, 1, reg * div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* analog out 0..1250mV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static inline u8 AOUT_TO_REG(unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) val = clamp_val(val, 0, 1250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return SCALE(val, 255, 1250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline unsigned int AOUT_FROM_REG(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return SCALE(reg, 1250, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* per client data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct adm9240_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct mutex update_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) char valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) unsigned long last_updated_measure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned long last_updated_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u8 in[6]; /* ro in0_input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u8 in_max[6]; /* rw in0_max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u8 in_min[6]; /* rw in0_min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u8 fan[2]; /* ro fan1_input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u8 fan_min[2]; /* rw fan1_min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 fan_div[2]; /* rw fan1_div, read-only accessor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) s16 temp; /* ro temp1_input, 9-bit sign-extended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) s8 temp_max[2]; /* rw 0 -> temp_max, 1 -> temp_max_hyst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u16 alarms; /* ro alarms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u8 aout; /* rw aout_output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u8 vid; /* ro vid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u8 vrm; /* -- vrm set on startup, no accessor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* write new fan div, callers must hold data->update_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int adm9240_write_fan_div(struct adm9240_data *data, int nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u8 fan_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned int reg, old, shift = (nr + 2) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) old = (reg >> shift) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) reg &= ~(3 << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) reg |= (fan_div << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) err = regmap_write(data->regmap, ADM9240_REG_VID_FAN_DIV, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) dev_dbg(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) "fan%d clock divider changed from %u to %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) nr + 1, 1 << old, 1 << fan_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int adm9240_update_measure(struct adm9240_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u8 regs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) err = regmap_bulk_read(data->regmap, ADM9240_REG_IN(0), &data->in[0], 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) err = regmap_bulk_read(data->regmap, ADM9240_REG_INT(0), ®s, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) data->alarms = regs[0] | regs[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * read temperature: assume temperature changes less than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * 0.5'C per two measurement cycles thus ignore possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * but unlikely aliasing error on lsb reading. --Grant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) err = regmap_read(data->regmap, ADM9240_REG_TEMP, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) data->temp = val << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) err = regmap_read(data->regmap, ADM9240_REG_TEMP_CONF, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) data->temp |= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) err = regmap_bulk_read(data->regmap, ADM9240_REG_FAN(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) &data->fan[0], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) for (i = 0; i < 2; i++) { /* read fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* adjust fan clock divider on overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (data->valid && data->fan[i] == 255 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) data->fan_div[i] < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) err = adm9240_write_fan_div(data, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ++data->fan_div[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* adjust fan_min if active, but not to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (data->fan_min[i] < 255 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) data->fan_min[i] >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) data->fan_min[i] /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int adm9240_update_config(struct adm9240_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) err = regmap_raw_read(data->regmap, ADM9240_REG_IN_MIN(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) &data->in_min[i], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) err = regmap_raw_read(data->regmap, ADM9240_REG_IN_MAX(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) &data->in_max[i], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) err = regmap_bulk_read(data->regmap, ADM9240_REG_FAN_MIN(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) &data->fan_min[0], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) err = regmap_bulk_read(data->regmap, ADM9240_REG_TEMP_MAX(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) &data->temp_max[0], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* read fan divs and 5-bit VID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) data->fan_div[0] = (val >> 4) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) data->fan_div[1] = (val >> 6) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) data->vid = val & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) err = regmap_read(data->regmap, ADM9240_REG_VID4, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) data->vid |= (val & 1) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* read analog out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) err = regmap_raw_read(data->regmap, ADM9240_REG_ANALOG_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) &data->aout, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static struct adm9240_data *adm9240_update_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* minimum measurement cycle: 1.75 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) || !data->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) err = adm9240_update_measure(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) data->valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) data->last_updated_measure = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* minimum config reading cycle: 300 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (time_after(jiffies, data->last_updated_config + (HZ * 300))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) || !data->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) err = adm9240_update_config(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) data->valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) data->last_updated_config = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) data->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /*** sysfs accessors ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static ssize_t temp1_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct device_attribute *dummy, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return sprintf(buf, "%d\n", data->temp / 128 * 500); /* 9-bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static ssize_t max_show(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static ssize_t max_store(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) data->temp_max[attr->index] = TEMP_TO_REG(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) err = regmap_write(data->regmap, ADM9240_REG_TEMP_MAX(attr->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) data->temp_max[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return err < 0 ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static DEVICE_ATTR_RO(temp1_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static SENSOR_DEVICE_ATTR_RW(temp1_max, max, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, max, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static ssize_t in_show(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) attr->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static ssize_t in_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) attr->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static ssize_t in_max_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) attr->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static ssize_t in_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct device_attribute *devattr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) data->in_min[attr->index] = IN_TO_REG(val, attr->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) err = regmap_write(data->regmap, ADM9240_REG_IN_MIN(attr->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) data->in_min[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return err < 0 ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static ssize_t in_max_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct device_attribute *devattr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) data->in_max[attr->index] = IN_TO_REG(val, attr->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) err = regmap_write(data->regmap, ADM9240_REG_IN_MAX(attr->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) data->in_max[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return err < 0 ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static SENSOR_DEVICE_ATTR_RO(in5_input, in, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 1 << data->fan_div[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static ssize_t fan_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 1 << data->fan_div[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static ssize_t fan_div_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * set fan speed low limit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * - value is zero: disable fan speed low limit alarm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * - value is below fan speed measurement range: enable fan speed low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * limit alarm to be asserted while fan speed too slow to measure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * - otherwise: select fan clock divider to suit fan speed low limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * measurement code may adjust registers to ensure fan speed reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static ssize_t fan_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct i2c_client *client = data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) int nr = attr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) u8 new_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) data->fan_min[nr] = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) new_div = data->fan_div[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) dev_dbg(&client->dev, "fan%u low limit set disabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) nr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) } else if (val < 1350000 / (8 * 254)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) new_div = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) data->fan_min[nr] = 254;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_dbg(&client->dev, "fan%u low limit set minimum %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) nr + 1, FAN_FROM_REG(254, 1 << new_div));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) unsigned int new_min = 1350000 / val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) new_div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) while (new_min > 192 && new_div < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) new_div++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) new_min /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (!new_min) /* keep > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) new_min++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) data->fan_min[nr] = new_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) nr + 1, FAN_FROM_REG(new_min, 1 << new_div));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (new_div != data->fan_div[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) data->fan_div[nr] = new_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) adm9240_write_fan_div(data, nr, new_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) err = regmap_write(data->regmap, ADM9240_REG_FAN_MIN(nr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) data->fan_min[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return err < 0 ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static SENSOR_DEVICE_ATTR_RO(fan1_div, fan_div, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static SENSOR_DEVICE_ATTR_RO(fan2_div, fan_div, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* alarms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static ssize_t alarms_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return sprintf(buf, "%u\n", data->alarms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static DEVICE_ATTR_RO(alarms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int bitnr = to_sensor_dev_attr(attr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* vid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) static ssize_t cpu0_vid_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static DEVICE_ATTR_RO(cpu0_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /* analog output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static ssize_t aout_output_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct adm9240_data *data = adm9240_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static ssize_t aout_output_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) data->aout = AOUT_TO_REG(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) err = regmap_write(data->regmap, ADM9240_REG_ANALOG_OUT, data->aout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return err < 0 ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static DEVICE_ATTR_RW(aout_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static ssize_t alarm_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct adm9240_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (kstrtoul(buf, 10, &val) || val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) err = regmap_write(data->regmap, ADM9240_REG_CHASSIS_CLEAR, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) data->valid = 0; /* Force cache refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dev_dbg(&data->client->dev, "chassis intrusion latch cleared\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static SENSOR_DEVICE_ATTR_RW(intrusion0_alarm, alarm, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static struct attribute *adm9240_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) &sensor_dev_attr_in0_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) &sensor_dev_attr_in0_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) &sensor_dev_attr_in0_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) &sensor_dev_attr_in0_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) &sensor_dev_attr_in1_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) &sensor_dev_attr_in1_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) &sensor_dev_attr_in1_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) &sensor_dev_attr_in1_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) &sensor_dev_attr_in2_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) &sensor_dev_attr_in2_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) &sensor_dev_attr_in2_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) &sensor_dev_attr_in2_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) &sensor_dev_attr_in3_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) &sensor_dev_attr_in3_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) &sensor_dev_attr_in3_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) &sensor_dev_attr_in3_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) &sensor_dev_attr_in4_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) &sensor_dev_attr_in4_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) &sensor_dev_attr_in4_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) &sensor_dev_attr_in4_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) &sensor_dev_attr_in5_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) &sensor_dev_attr_in5_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) &sensor_dev_attr_in5_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) &sensor_dev_attr_in5_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) &dev_attr_temp1_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) &sensor_dev_attr_temp1_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) &sensor_dev_attr_temp1_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) &sensor_dev_attr_fan1_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) &sensor_dev_attr_fan1_div.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) &sensor_dev_attr_fan1_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) &sensor_dev_attr_fan1_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) &sensor_dev_attr_fan2_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) &sensor_dev_attr_fan2_div.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) &sensor_dev_attr_fan2_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) &sensor_dev_attr_fan2_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) &dev_attr_alarms.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) &dev_attr_aout_output.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) &sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) &dev_attr_cpu0_vid.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ATTRIBUTE_GROUPS(adm9240);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /*** sensor chip detect and driver install ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* Return 0 if detection is successful, -ENODEV otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static int adm9240_detect(struct i2c_client *new_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct i2c_board_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct i2c_adapter *adapter = new_client->adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) const char *name = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int address = new_client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) u8 man_id, die_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) /* verify chip: reg address should match i2c address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) != address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) dev_err(&adapter->dev, "detect fail: address match, 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /* check known chip manufacturer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) man_id = i2c_smbus_read_byte_data(new_client, ADM9240_REG_MAN_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (man_id == 0x23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) name = "adm9240";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) } else if (man_id == 0xda) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) name = "ds1780";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) } else if (man_id == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) name = "lm81";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) dev_err(&adapter->dev, "detect fail: unknown manuf, 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) man_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* successful detect, print chip info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) die_rev = i2c_smbus_read_byte_data(new_client, ADM9240_REG_DIE_REV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dev_info(&adapter->dev, "found %s revision %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) man_id == 0x23 ? "ADM9240" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) man_id == 0xda ? "DS1780" : "LM81", die_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) strlcpy(info->type, name, I2C_NAME_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static int adm9240_init_client(struct i2c_client *client, struct adm9240_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) u8 conf, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) err = regmap_raw_read(data->regmap, ADM9240_REG_CONFIG, &conf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) err = regmap_raw_read(data->regmap, ADM9240_REG_TEMP_CONF, &mode, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) mode &= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) data->vrm = vid_which_vrm(); /* need this to report vid as mV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) data->vrm % 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (conf & 1) { /* measurement cycle running: report state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) dev_info(&client->dev, "status: config 0x%02x mode %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) conf, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) } else { /* cold start: open limits before starting chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) err = regmap_write(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) ADM9240_REG_IN_MIN(i), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) err = regmap_write(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) ADM9240_REG_IN_MAX(i), 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) err = regmap_write(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) ADM9240_REG_FAN_MIN(i), 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) err = regmap_write(data->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) ADM9240_REG_TEMP_MAX(i), 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /* start measurement cycle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) err = regmap_write(data->regmap, ADM9240_REG_CONFIG, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) "cold start: config was 0x%02x mode %u\n", conf, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static const struct regmap_config adm9240_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) .use_single_read = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) .use_single_write = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int adm9240_probe(struct i2c_client *new_client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct device *dev = &new_client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct adm9240_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) data->client = new_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) mutex_init(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) data->regmap = devm_regmap_init_i2c(new_client, &adm9240_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (IS_ERR(data->regmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return PTR_ERR(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) err = adm9240_init_client(new_client, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) hwmon_dev = devm_hwmon_device_register_with_groups(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) new_client->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) adm9240_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return PTR_ERR_OR_ZERO(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static const struct i2c_device_id adm9240_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) { "adm9240", adm9240 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) { "ds1780", ds1780 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) { "lm81", lm81 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) MODULE_DEVICE_TABLE(i2c, adm9240_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static struct i2c_driver adm9240_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .class = I2C_CLASS_HWMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .name = "adm9240",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .probe_new = adm9240_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .id_table = adm9240_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .detect = adm9240_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .address_list = normal_i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) module_i2c_driver(adm9240_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) "Grant Coady <gcoady.lk@gmail.com> and others");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) MODULE_LICENSE("GPL");