^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) * fschmd.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2007 - 2009 Hans de Goede <hdegoede@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Scylla, Heracles, Heimdall, Hades and Syleus chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * (candidate) fschmd drivers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2006 Thilo Cestonaro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * <thilo.cestonaro.external@fujitsu-siemens.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Copyright (C) 2003, 2004 Reinhard Nissl <rnissl@gmx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Copyright (c) 2001 Martin Knoblauch <mkn@teraport.de, knobi@knobisoft.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Copyright (C) 2000 Hermann Jung <hej@odn.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/watchdog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/kref.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Addresses to scan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Insmod parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static bool nowayout = WATCHDOG_NOWAYOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) module_param(nowayout, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) enum chips { fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * The FSCHMD registers and other defines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* chip identification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define FSCHMD_REG_IDENT_0 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define FSCHMD_REG_IDENT_1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define FSCHMD_REG_IDENT_2 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define FSCHMD_REG_REVISION 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* global control and status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define FSCHMD_REG_EVENT_STATE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define FSCHMD_REG_CONTROL 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define FSCHMD_CONTROL_ALERT_LED 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* watchdog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const u8 FSCHMD_REG_WDOG_CONTROL[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0x21, 0x21, 0x21, 0x21, 0x21, 0x28, 0x28 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const u8 FSCHMD_REG_WDOG_STATE[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const u8 FSCHMD_REG_WDOG_PRESET[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 0x28, 0x28, 0x28, 0x28, 0x28, 0x2a, 0x2a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define FSCHMD_WDOG_CONTROL_TRIGGER 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define FSCHMD_WDOG_CONTROL_STOP 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define FSCHMD_WDOG_CONTROL_RESOLUTION 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define FSCHMD_WDOG_STATE_CARDRESET 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* voltages, weird order is to keep the same order as the old drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const u8 FSCHMD_REG_VOLT[7][6] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { 0x45, 0x42, 0x48 }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { 0x45, 0x42, 0x48 }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { 0x45, 0x42, 0x48 }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { 0x45, 0x42, 0x48 }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { 0x45, 0x42, 0x48 }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { 0x21, 0x20, 0x22 }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { 0x21, 0x20, 0x22, 0x23, 0x24, 0x25 }, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static const int FSCHMD_NO_VOLT_SENSORS[7] = { 3, 3, 3, 3, 3, 3, 6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * minimum pwm at which the fan is driven (pwm can be increased depending on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * the temp. Notice that for the scy some fans share there minimum speed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Also notice that with the scy the sensor order is different than with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * other chips, this order was in the 2.4 driver and kept for consistency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const u8 FSCHMD_REG_FAN_MIN[7][7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { 0x55, 0x65 }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { 0x55, 0x65, 0xb5 }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb4 }, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* actual fan speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static const u8 FSCHMD_REG_FAN_ACT[7][7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { 0x0e, 0x6b, 0xab }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { 0x0e, 0x6b, 0xbb }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { 0x57, 0x67, 0x77, 0x87, 0x97, 0xa7, 0xb7 }, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* fan status registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static const u8 FSCHMD_REG_FAN_STATE[7][7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { 0x0d, 0x62, 0xa2 }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { 0x0d, 0x62, 0xb2 }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0 }, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* fan ripple / divider registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static const u8 FSCHMD_REG_FAN_RIPPLE[7][7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { 0x0f, 0x6f, 0xaf }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { 0x0f, 0x6f, 0xbf }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { 0x56, 0x66, 0x76, 0x86, 0x96, 0xa6, 0xb6 }, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static const int FSCHMD_NO_FAN_SENSORS[7] = { 3, 3, 6, 4, 5, 5, 7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* Fan status register bitmasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define FSCHMD_FAN_NOT_PRESENT 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define FSCHMD_FAN_DISABLED 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* actual temperature registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static const u8 FSCHMD_REG_TEMP_ACT[7][11] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { 0x64, 0x32, 0x35 }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { 0x64, 0x32, 0x35 }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { 0x64, 0xD0, 0x32, 0x35 }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { 0x64, 0x32, 0x35 }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 0xb8, 0xc8, 0xd8, 0xe8, 0xf8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* temperature state registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static const u8 FSCHMD_REG_TEMP_STATE[7][11] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { 0x71, 0x81, 0x91 }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { 0x71, 0x81, 0x91 }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { 0x71, 0xd1, 0x81, 0x91 }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { 0x71, 0x81, 0x91 }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { 0x59, 0x69, 0x79, 0x89, 0x99, 0xa9, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 0xb9, 0xc9, 0xd9, 0xe9, 0xf9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * temperature high limit registers, FSC does not document these. Proven to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * there with field testing on the fscher and fschrc, already supported / used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * at these addresses, but doesn't want to confirm they are the same as with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * the fscher??
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static const u8 FSCHMD_REG_TEMP_LIMIT[7][11] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { 0, 0, 0 }, /* pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { 0x76, 0x86, 0x96 }, /* her */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { 0x76, 0xd6, 0x86, 0x96 }, /* scy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { 0x76, 0x86, 0x96 }, /* hrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { 0x5a, 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, /* syl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 0xba, 0xca, 0xda, 0xea, 0xfa },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * These were found through experimenting with an fscher, currently they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * not used, but we keep them around for future reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * On the fscsyl AUTOP1 lives at 0x#c (so 0x5c for fan1, 0x6c for fan2, etc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * AUTOP2 lives at 0x#e, and 0x#1 is a bitmask defining which temps influence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * the fan speed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static const int FSCHMD_NO_TEMP_SENSORS[7] = { 3, 3, 4, 3, 5, 5, 11 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* temp status register bitmasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define FSCHMD_TEMP_WORKING 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define FSCHMD_TEMP_ALERT 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define FSCHMD_TEMP_DISABLED 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* there only really is an alarm if the sensor is working and alert == 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define FSCHMD_TEMP_ALARM_MASK \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Functions declarations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int fschmd_probe(struct i2c_client *client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int fschmd_detect(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct i2c_board_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int fschmd_remove(struct i2c_client *client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static struct fschmd_data *fschmd_update_device(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Driver data (common to all clients)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static const struct i2c_device_id fschmd_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { "fscpos", fscpos },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { "fscher", fscher },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) { "fscscy", fscscy },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { "fschrc", fschrc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) { "fschmd", fschmd },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { "fschds", fschds },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) { "fscsyl", fscsyl },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) MODULE_DEVICE_TABLE(i2c, fschmd_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static struct i2c_driver fschmd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .class = I2C_CLASS_HWMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .name = "fschmd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .probe_new = fschmd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .remove = fschmd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .id_table = fschmd_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .detect = fschmd_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .address_list = normal_i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Client data (each client gets its own)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct fschmd_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct mutex update_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct mutex watchdog_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct list_head list; /* member of the watchdog_data_list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct kref kref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct miscdevice watchdog_miscdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) enum chips kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) unsigned long watchdog_is_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) char watchdog_expect_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) char valid; /* zero until following fields are valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned long last_updated; /* in jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u8 revision; /* chip revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) u8 global_control; /* global control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u8 watchdog_control; /* watchdog control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u8 watchdog_state; /* watchdog status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u8 watchdog_preset; /* watchdog counter preset on trigger val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u8 volt[6]; /* voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) u8 temp_act[11]; /* temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 temp_status[11]; /* status of sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u8 temp_max[11]; /* high temp limit, notice: undocumented! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u8 fan_act[7]; /* fans revolutions per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u8 fan_status[7]; /* fan status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) u8 fan_min[7]; /* fan min value for rps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) u8 fan_ripple[7]; /* divider for rps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^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) * Global variables to hold information read from special DMI tables, which are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * available on FSC machines with an fscher or later chip. There is no need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * protect these with a lock as they are only modified from our attach function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * which always gets called with the i2c-core lock held and never accessed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * before the attach function is done with them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int dmi_mult[6] = { 490, 200, 100, 100, 200, 100 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static int dmi_offset[6] = { 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int dmi_vref = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Somewhat ugly :( global data pointer list with all fschmd devices, so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * we can find our device data as when using misc_register there is no other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * method to get to ones device data from the open fop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static LIST_HEAD(watchdog_data_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* Note this lock not only protect list access, but also data.kref access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static DEFINE_MUTEX(watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Release our data struct when we're detached from the i2c client *and* all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * references to our watchdog device are released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static void fschmd_release_resources(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct fschmd_data *data = container_of(ref, struct fschmd_data, kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^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) * Sysfs attr show / store functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static ssize_t in_value_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) const int max_reading[3] = { 14200, 6600, 3300 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (data->kind == fscher || data->kind >= fschrc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dmi_mult[index]) / 255 + dmi_offset[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return sprintf(buf, "%d\n", (data->volt[index] *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) max_reading[index] + 128) / 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #define TEMP_FROM_REG(val) (((val) - 128) * 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static ssize_t temp_value_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static ssize_t temp_max_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static ssize_t temp_max_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct fschmd_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) err = kstrtol(buf, 10, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) v = clamp_val(v / 1000, -128, 127) + 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) i2c_smbus_write_byte_data(to_i2c_client(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) FSCHMD_REG_TEMP_LIMIT[data->kind][index], v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) data->temp_max[index] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return count;
^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 temp_fault_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) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* bit 0 set means sensor working ok, so no fault! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (data->temp_status[index] & FSCHMD_TEMP_WORKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return sprintf(buf, "1\n");
^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 temp_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if ((data->temp_status[index] & FSCHMD_TEMP_ALARM_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) FSCHMD_TEMP_ALARM_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return sprintf(buf, "1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) #define RPM_FROM_REG(val) ((val) * 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static ssize_t fan_value_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static ssize_t fan_div_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* bits 2..7 reserved => mask with 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return sprintf(buf, "%d\n", 1 << (data->fan_ripple[index] & 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static ssize_t fan_div_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct fschmd_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* supported values: 2, 4, 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) err = kstrtoul(buf, 10, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) switch (v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) v = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) v = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) v = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) "fan_div value %lu not supported. Choose one of 2, 4 or 8!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) reg = i2c_smbus_read_byte_data(to_i2c_client(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) FSCHMD_REG_FAN_RIPPLE[data->kind][index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* bits 2..7 reserved => mask with 0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) reg &= ~0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) reg |= v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) i2c_smbus_write_byte_data(to_i2c_client(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) data->fan_ripple[index] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static ssize_t fan_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (data->fan_status[index] & FSCHMD_FAN_ALARM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return sprintf(buf, "1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static ssize_t fan_fault_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return sprintf(buf, "1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static ssize_t pwm_auto_point1_pwm_show(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) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) int val = data->fan_min[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* 0 = allow turning off (except on the syl), 1-255 = 50-100% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (val || data->kind == fscsyl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) val = val / 2 + 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return sprintf(buf, "%d\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static ssize_t pwm_auto_point1_pwm_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) int index = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct fschmd_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) err = kstrtoul(buf, 10, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (v || data->kind == fscsyl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) v = clamp_val(v, 128, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) v = (v - 128) * 2 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) i2c_smbus_write_byte_data(to_i2c_client(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) FSCHMD_REG_FAN_MIN[data->kind][index], v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) data->fan_min[index] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * The FSC hwmon family has the ability to force an attached alert led to flash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * from software, we export this as an alert_led sysfs attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static ssize_t alert_led_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct fschmd_data *data = fschmd_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (data->global_control & FSCHMD_CONTROL_ALERT_LED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return sprintf(buf, "1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static ssize_t alert_led_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct device_attribute *devattr, const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct fschmd_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) err = kstrtoul(buf, 10, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) reg |= FSCHMD_CONTROL_ALERT_LED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) reg &= ~FSCHMD_CONTROL_ALERT_LED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) data->global_control = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static DEVICE_ATTR_RW(alert_led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static struct sensor_device_attribute fschmd_attr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) SENSOR_ATTR_RO(in0_input, in_value, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) SENSOR_ATTR_RO(in1_input, in_value, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) SENSOR_ATTR_RO(in2_input, in_value, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) SENSOR_ATTR_RO(in3_input, in_value, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) SENSOR_ATTR_RO(in4_input, in_value, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) SENSOR_ATTR_RO(in5_input, in_value, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) static struct sensor_device_attribute fschmd_temp_attr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) SENSOR_ATTR_RO(temp1_input, temp_value, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) SENSOR_ATTR_RW(temp1_max, temp_max, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) SENSOR_ATTR_RO(temp1_fault, temp_fault, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) SENSOR_ATTR_RO(temp1_alarm, temp_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) SENSOR_ATTR_RO(temp2_input, temp_value, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) SENSOR_ATTR_RW(temp2_max, temp_max, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) SENSOR_ATTR_RO(temp2_fault, temp_fault, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) SENSOR_ATTR_RO(temp2_alarm, temp_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) SENSOR_ATTR_RO(temp3_input, temp_value, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) SENSOR_ATTR_RW(temp3_max, temp_max, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) SENSOR_ATTR_RO(temp3_fault, temp_fault, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) SENSOR_ATTR_RO(temp3_alarm, temp_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) SENSOR_ATTR_RO(temp4_input, temp_value, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) SENSOR_ATTR_RW(temp4_max, temp_max, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) SENSOR_ATTR_RO(temp4_fault, temp_fault, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) SENSOR_ATTR_RO(temp4_alarm, temp_alarm, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) SENSOR_ATTR_RO(temp5_input, temp_value, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) SENSOR_ATTR_RW(temp5_max, temp_max, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) SENSOR_ATTR_RO(temp5_fault, temp_fault, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) SENSOR_ATTR_RO(temp5_alarm, temp_alarm, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) SENSOR_ATTR_RO(temp6_input, temp_value, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) SENSOR_ATTR_RW(temp6_max, temp_max, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) SENSOR_ATTR_RO(temp6_fault, temp_fault, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) SENSOR_ATTR_RO(temp6_alarm, temp_alarm, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) SENSOR_ATTR_RO(temp7_input, temp_value, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) SENSOR_ATTR_RW(temp7_max, temp_max, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) SENSOR_ATTR_RO(temp7_fault, temp_fault, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) SENSOR_ATTR_RO(temp7_alarm, temp_alarm, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) SENSOR_ATTR_RO(temp8_input, temp_value, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) SENSOR_ATTR_RW(temp8_max, temp_max, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) SENSOR_ATTR_RO(temp8_fault, temp_fault, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) SENSOR_ATTR_RO(temp8_alarm, temp_alarm, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) SENSOR_ATTR_RO(temp9_input, temp_value, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) SENSOR_ATTR_RW(temp9_max, temp_max, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) SENSOR_ATTR_RO(temp9_fault, temp_fault, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) SENSOR_ATTR_RO(temp9_alarm, temp_alarm, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) SENSOR_ATTR_RO(temp10_input, temp_value, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) SENSOR_ATTR_RW(temp10_max, temp_max, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) SENSOR_ATTR_RO(temp10_fault, temp_fault, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) SENSOR_ATTR_RO(temp10_alarm, temp_alarm, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) SENSOR_ATTR_RO(temp11_input, temp_value, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) SENSOR_ATTR_RW(temp11_max, temp_max, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) SENSOR_ATTR_RO(temp11_fault, temp_fault, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) SENSOR_ATTR_RO(temp11_alarm, temp_alarm, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static struct sensor_device_attribute fschmd_fan_attr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) SENSOR_ATTR_RO(fan1_input, fan_value, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) SENSOR_ATTR_RW(fan1_div, fan_div, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) SENSOR_ATTR_RO(fan1_alarm, fan_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) SENSOR_ATTR_RO(fan1_fault, fan_fault, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) SENSOR_ATTR_RW(pwm1_auto_point1_pwm, pwm_auto_point1_pwm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) SENSOR_ATTR_RO(fan2_input, fan_value, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) SENSOR_ATTR_RW(fan2_div, fan_div, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) SENSOR_ATTR_RO(fan2_alarm, fan_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) SENSOR_ATTR_RO(fan2_fault, fan_fault, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) SENSOR_ATTR_RW(pwm2_auto_point1_pwm, pwm_auto_point1_pwm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) SENSOR_ATTR_RO(fan3_input, fan_value, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) SENSOR_ATTR_RW(fan3_div, fan_div, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) SENSOR_ATTR_RO(fan3_alarm, fan_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) SENSOR_ATTR_RO(fan3_fault, fan_fault, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) SENSOR_ATTR_RW(pwm3_auto_point1_pwm, pwm_auto_point1_pwm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) SENSOR_ATTR_RO(fan4_input, fan_value, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) SENSOR_ATTR_RW(fan4_div, fan_div, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) SENSOR_ATTR_RO(fan4_alarm, fan_alarm, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) SENSOR_ATTR_RO(fan4_fault, fan_fault, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) SENSOR_ATTR_RW(pwm4_auto_point1_pwm, pwm_auto_point1_pwm, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) SENSOR_ATTR_RO(fan5_input, fan_value, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) SENSOR_ATTR_RW(fan5_div, fan_div, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) SENSOR_ATTR_RO(fan5_alarm, fan_alarm, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) SENSOR_ATTR_RO(fan5_fault, fan_fault, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) SENSOR_ATTR_RW(pwm5_auto_point1_pwm, pwm_auto_point1_pwm, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) SENSOR_ATTR_RO(fan6_input, fan_value, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) SENSOR_ATTR_RW(fan6_div, fan_div, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) SENSOR_ATTR_RO(fan6_alarm, fan_alarm, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) SENSOR_ATTR_RO(fan6_fault, fan_fault, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) SENSOR_ATTR_RW(pwm6_auto_point1_pwm, pwm_auto_point1_pwm, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) SENSOR_ATTR_RO(fan7_input, fan_value, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) SENSOR_ATTR_RW(fan7_div, fan_div, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) SENSOR_ATTR_RO(fan7_alarm, fan_alarm, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) SENSOR_ATTR_RO(fan7_fault, fan_fault, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) SENSOR_ATTR_RW(pwm7_auto_point1_pwm, pwm_auto_point1_pwm, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * Watchdog routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static int watchdog_set_timeout(struct fschmd_data *data, int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int ret, resolution;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int kind = data->kind + 1; /* 0-x array index -> 1-x module param */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* 2 second or 60 second resolution? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (timeout <= 510 || kind == fscpos || kind == fscscy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) resolution = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) resolution = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (timeout < resolution || timeout > (resolution * 255))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) mutex_lock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (!data->client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) goto leave;
^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) if (resolution == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) data->watchdog_control |= FSCHMD_WDOG_CONTROL_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) data->watchdog_preset = DIV_ROUND_UP(timeout, resolution);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* Write new timeout value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) i2c_smbus_write_byte_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) FSCHMD_REG_WDOG_PRESET[data->kind], data->watchdog_preset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* Write new control register, do not trigger! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) i2c_smbus_write_byte_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) FSCHMD_REG_WDOG_CONTROL[data->kind],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ret = data->watchdog_preset * resolution;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) leave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) mutex_unlock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static int watchdog_get_timeout(struct fschmd_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) mutex_lock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (data->watchdog_control & FSCHMD_WDOG_CONTROL_RESOLUTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) timeout = data->watchdog_preset * 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) timeout = data->watchdog_preset * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) mutex_unlock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static int watchdog_trigger(struct fschmd_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) mutex_lock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (!data->client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) i2c_smbus_write_byte_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) FSCHMD_REG_WDOG_CONTROL[data->kind],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) data->watchdog_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) leave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) mutex_unlock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static int watchdog_stop(struct fschmd_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) mutex_lock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (!data->client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * Don't store the stop flag in our watchdog control register copy, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * its a write only bit (read always returns 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) i2c_smbus_write_byte_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) FSCHMD_REG_WDOG_CONTROL[data->kind],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) leave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) mutex_unlock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static int watchdog_open(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct fschmd_data *pos, *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) int watchdog_is_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * We get called from drivers/char/misc.c with misc_mtx hold, and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * call misc_register() from fschmd_probe() with watchdog_data_mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * hold, as misc_register() takes the misc_mtx lock, this is a possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * deadlock, so we use mutex_trylock here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (!mutex_trylock(&watchdog_data_mutex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) list_for_each_entry(pos, &watchdog_data_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (pos->watchdog_miscdev.minor == iminor(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) data = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /* Note we can never not have found data, so we don't check for this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (!watchdog_is_open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) kref_get(&data->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_unlock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (watchdog_is_open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* Start the watchdog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) watchdog_trigger(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) filp->private_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return stream_open(inode, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static int watchdog_release(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct fschmd_data *data = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (data->watchdog_expect_close) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) watchdog_stop(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) data->watchdog_expect_close = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) watchdog_trigger(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) dev_crit(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) "unexpected close, not stopping watchdog!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) clear_bit(0, &data->watchdog_is_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) mutex_lock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) kref_put(&data->kref, fschmd_release_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) mutex_unlock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static ssize_t watchdog_write(struct file *filp, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) size_t count, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) struct fschmd_data *data = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (!nowayout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* Clear it in case it was set with a previous write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) data->watchdog_expect_close = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) for (i = 0; i != count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (get_user(c, buf + i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (c == 'V')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) data->watchdog_expect_close = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) ret = watchdog_trigger(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) static long watchdog_ioctl(struct file *filp, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct watchdog_info ident = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) WDIOF_CARDRESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) .identity = "FSC watchdog"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct fschmd_data *data = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) case WDIOC_GETSUPPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ident.firmware_version = data->revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (!nowayout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) ident.options |= WDIOF_MAGICCLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case WDIOC_GETSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) ret = put_user(0, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) case WDIOC_GETBOOTSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (data->watchdog_state & FSCHMD_WDOG_STATE_CARDRESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) ret = put_user(WDIOF_CARDRESET, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) ret = put_user(0, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) case WDIOC_KEEPALIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ret = watchdog_trigger(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case WDIOC_GETTIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) i = watchdog_get_timeout(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ret = put_user(i, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) case WDIOC_SETTIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (get_user(i, (int __user *)arg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ret = watchdog_set_timeout(data, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ret = put_user(ret, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case WDIOC_SETOPTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (get_user(i, (int __user *)arg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (i & WDIOS_DISABLECARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ret = watchdog_stop(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) else if (i & WDIOS_ENABLECARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) ret = watchdog_trigger(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static const struct file_operations watchdog_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .open = watchdog_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) .release = watchdog_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) .write = watchdog_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) .unlocked_ioctl = watchdog_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .compat_ioctl = compat_ptr_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * Detect, register, unregister and update device functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * DMI decode routine to read voltage scaling factors from special DMI tables,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * which are available on FSC machines with an fscher or later chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * dmi code ugliness, we get passed the address of the contents of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * a complete DMI record, but in the form of a dmi_header pointer, in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) * reality this address holds header->length bytes of which the header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) * are the first 4 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) u8 *dmi_data = (u8 *)header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) /* We are looking for OEM-specific type 185 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (header->type != 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * we are looking for what Siemens calls "subtype" 19, the subtype
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * is stored in byte 5 of the dmi block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (header->length < 5 || dmi_data[4] != 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * After the subtype comes 1 unknown byte and then blocks of 5 bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * consisting of what Siemens calls an "Entity" number, followed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * 2 16-bit words in LSB first order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) for (i = 6; (i + 4) < header->length; i += 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) /* entity 1 - 3: voltage multiplier and offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (dmi_data[i] >= 1 && dmi_data[i] <= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* Our in sensors order and the DMI order differ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) const int shuffle[3] = { 1, 0, 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) int in = shuffle[dmi_data[i] - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* Check for twice the same entity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (found & (1 << in))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) mult[in] = dmi_data[i + 1] | (dmi_data[i + 2] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) offset[in] = dmi_data[i + 3] | (dmi_data[i + 4] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) found |= 1 << in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /* entity 7: reference voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (dmi_data[i] == 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* Check for twice the same entity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (found & 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) vref = dmi_data[i + 1] | (dmi_data[i + 2] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) found |= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (found == 0x0F) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) dmi_mult[i] = mult[i] * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) dmi_offset[i] = offset[i] * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * According to the docs there should be separate dmi entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * for the mult's and offsets of in3-5 of the syl, but on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * my test machine these are not present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) dmi_mult[3] = dmi_mult[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) dmi_mult[4] = dmi_mult[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) dmi_mult[5] = dmi_mult[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) dmi_offset[3] = dmi_offset[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) dmi_offset[4] = dmi_offset[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) dmi_offset[5] = dmi_offset[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) dmi_vref = vref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) static int fschmd_detect(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct i2c_board_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) enum chips kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct i2c_adapter *adapter = client->adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) char id[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /* Detect & Identify the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) id[0] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) id[1] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) id[2] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) id[3] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (!strcmp(id, "PEG"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) kind = fscpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) else if (!strcmp(id, "HER"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) kind = fscher;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) else if (!strcmp(id, "SCY"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) kind = fscscy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) else if (!strcmp(id, "HRC"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) kind = fschrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) else if (!strcmp(id, "HMD"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) kind = fschmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) else if (!strcmp(id, "HDS"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) kind = fschds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) else if (!strcmp(id, "SYL"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) kind = fscsyl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) strlcpy(info->type, fschmd_id[kind].name, I2C_NAME_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) static int fschmd_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct fschmd_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) "Heracles", "Heimdall", "Hades", "Syleus" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) enum chips kind = i2c_match_id(fschmd_id, client)->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) i2c_set_clientdata(client, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) mutex_init(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) mutex_init(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) INIT_LIST_HEAD(&data->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) kref_init(&data->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * Store client pointer in our data struct for watchdog usage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * (where the client is found through a data ptr instead of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * otherway around)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) data->kind = kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (kind == fscpos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * The Poseidon has hardwired temp limits, fill these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * in for the alarm resetting code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) data->temp_max[0] = 70 + 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) data->temp_max[1] = 50 + 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) data->temp_max[2] = 50 + 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* Read the special DMI table for fscher and newer chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) dmi_walk(fschmd_dmi_decode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (dmi_vref == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) dev_warn(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) "Couldn't get voltage scaling factors from "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) "BIOS DMI table, using builtin defaults\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) dmi_vref = 33;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) /* Read in some never changing registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) data->global_control = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) FSCHMD_REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) data->watchdog_control = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) FSCHMD_REG_WDOG_CONTROL[data->kind]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) data->watchdog_state = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) FSCHMD_REG_WDOG_STATE[data->kind]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) data->watchdog_preset = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) FSCHMD_REG_WDOG_PRESET[data->kind]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) err = device_create_file(&client->dev, &dev_attr_alert_led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) goto exit_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) err = device_create_file(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) &fschmd_attr[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) goto exit_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /* Poseidon doesn't have TEMP_LIMIT registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (kind == fscpos && fschmd_temp_attr[i].dev_attr.show ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) temp_max_show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (kind == fscsyl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (i % 4 == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) data->temp_status[i / 4] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) FSCHMD_REG_TEMP_STATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) [data->kind][i / 4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (data->temp_status[i / 4] & FSCHMD_TEMP_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) err = device_create_file(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) &fschmd_temp_attr[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) goto exit_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) /* Poseidon doesn't have a FAN_MIN register for its 3rd fan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (kind == fscpos &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) !strcmp(fschmd_fan_attr[i].dev_attr.attr.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) "pwm3_auto_point1_pwm"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (kind == fscsyl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (i % 5 == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) data->fan_status[i / 5] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) FSCHMD_REG_FAN_STATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) [data->kind][i / 5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (data->fan_status[i / 5] & FSCHMD_FAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) err = device_create_file(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) &fschmd_fan_attr[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) goto exit_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) data->hwmon_dev = hwmon_device_register(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (IS_ERR(data->hwmon_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) err = PTR_ERR(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) data->hwmon_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) goto exit_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * We take the data_mutex lock early so that watchdog_open() cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * run when misc_register() has completed, but we've not yet added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) * our data to the watchdog_data_list (and set the default timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) mutex_lock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* Register our watchdog part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) snprintf(data->watchdog_name, sizeof(data->watchdog_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) "watchdog%c", (i == 0) ? '\0' : ('0' + i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) data->watchdog_miscdev.name = data->watchdog_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) data->watchdog_miscdev.fops = &watchdog_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) data->watchdog_miscdev.minor = watchdog_minors[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) err = misc_register(&data->watchdog_miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (err == -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) data->watchdog_miscdev.minor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) "Registering watchdog chardev: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) list_add(&data->list, &watchdog_data_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) watchdog_set_timeout(data, 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) "Registered watchdog chardev major 10, minor: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) watchdog_minors[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (i == ARRAY_SIZE(watchdog_minors)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) data->watchdog_miscdev.minor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) dev_warn(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) "Couldn't register watchdog chardev (due to no free minor)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) mutex_unlock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) dev_info(&client->dev, "Detected FSC %s chip, revision: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) names[data->kind], (int) data->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) exit_detach:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) fschmd_remove(client); /* will also free data for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) static int fschmd_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) struct fschmd_data *data = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* Unregister the watchdog (if registered) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (data->watchdog_miscdev.minor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) misc_deregister(&data->watchdog_miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (data->watchdog_is_open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) dev_warn(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) "i2c client detached with watchdog open! "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) "Stopping watchdog.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) watchdog_stop(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) mutex_lock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) list_del(&data->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) mutex_unlock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) /* Tell the watchdog code the client is gone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) mutex_lock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) data->client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) mutex_unlock(&data->watchdog_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * Check if registered in case we're called from fschmd_detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * to cleanup after an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (data->hwmon_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) hwmon_device_unregister(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) device_remove_file(&client->dev, &dev_attr_alert_led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) for (i = 0; i < (FSCHMD_NO_VOLT_SENSORS[data->kind]); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) device_remove_file(&client->dev, &fschmd_attr[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) device_remove_file(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) &fschmd_temp_attr[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) device_remove_file(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) &fschmd_fan_attr[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) mutex_lock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) kref_put(&data->kref, fschmd_release_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) mutex_unlock(&watchdog_data_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static struct fschmd_data *fschmd_update_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) struct fschmd_data *data = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) for (i = 0; i < FSCHMD_NO_TEMP_SENSORS[data->kind]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) data->temp_act[i] = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) FSCHMD_REG_TEMP_ACT[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) data->temp_status[i] = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) FSCHMD_REG_TEMP_STATE[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) /* The fscpos doesn't have TEMP_LIMIT registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (FSCHMD_REG_TEMP_LIMIT[data->kind][i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) data->temp_max[i] = i2c_smbus_read_byte_data(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) FSCHMD_REG_TEMP_LIMIT[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * reset alarm if the alarm condition is gone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) * the chip doesn't do this itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if ((data->temp_status[i] & FSCHMD_TEMP_ALARM_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) FSCHMD_TEMP_ALARM_MASK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) data->temp_act[i] < data->temp_max[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) i2c_smbus_write_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) FSCHMD_REG_TEMP_STATE[data->kind][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) data->temp_status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) data->fan_act[i] = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) FSCHMD_REG_FAN_ACT[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) data->fan_status[i] = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) FSCHMD_REG_FAN_STATE[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) data->fan_ripple[i] = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) FSCHMD_REG_FAN_RIPPLE[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /* The fscpos third fan doesn't have a fan_min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (FSCHMD_REG_FAN_MIN[data->kind][i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) data->fan_min[i] = i2c_smbus_read_byte_data(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) FSCHMD_REG_FAN_MIN[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /* reset fan status if speed is back to > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if ((data->fan_status[i] & FSCHMD_FAN_ALARM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) data->fan_act[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) i2c_smbus_write_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) FSCHMD_REG_FAN_STATE[data->kind][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) data->fan_status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) data->volt[i] = i2c_smbus_read_byte_data(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) FSCHMD_REG_VOLT[data->kind][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) data->last_updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) data->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) module_i2c_driver(fschmd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles, Heimdall, Hades "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) "and Syleus driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) MODULE_LICENSE("GPL");