^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) * nct6775 - Driver for the hardware monitoring functionality of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Nuvoton NCT677x Super-I/O chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Derived from w83627ehf driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2006 Yuan Mu (Winbond),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Rudolf Marek <r.marek@assembler.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * David Hubbard <david.c.hubbard@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Daniel J Blueman <daniel.blueman@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Shamelessly ripped from the w83627hf driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Copyright (C) 2003 Mark Studebaker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Supports the following chips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Chip #vin #fan #pwm #temp chip IDs man ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * nct6116d 9 5 5 3+3 0xd280 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * nct6792d 15 6 6 2+6 0xc910 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * nct6793d 15 6 6 2+6 0xd120 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * nct6795d 14 6 6 2+6 0xd350 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * nct6796d 14 7 7 2+6 0xd420 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * nct6797d 14 7 7 2+6 0xd450 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * (0xd451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * (0xd429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * #temp lists the number of monitored temperature sources (first value) plus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * the number of directly connectable temperature sensors (second value).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/hwmon-vid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include "lm75.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define USE_ALTERNATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) nct6793, nct6795, nct6796, nct6797, nct6798 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* used to set data->name = nct6775_device_names[data->sio_kind] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static const char * const nct6775_device_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "nct6106",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "nct6116",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) "nct6775",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) "nct6776",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) "nct6779",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "nct6791",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) "nct6792",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "nct6793",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) "nct6795",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) "nct6796",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) "nct6797",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "nct6798",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static const char * const nct6775_sio_names[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "NCT6106D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "NCT6116D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "NCT6775F",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "NCT6776D/F",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) "NCT6779D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "NCT6791D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "NCT6792D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "NCT6793D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) "NCT6795D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) "NCT6796D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) "NCT6797D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) "NCT6798D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static unsigned short force_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) module_param(force_id, ushort, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) MODULE_PARM_DESC(force_id, "Override the detected device ID");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static unsigned short fan_debounce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) module_param(fan_debounce, ushort, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define DRVNAME "nct6775"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * Super-I/O constants and functions
^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) #define NCT6775_LD_ACPI 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define NCT6775_LD_HWM 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define NCT6775_LD_VID 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define NCT6775_LD_12 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define SIO_REG_LDSEL 0x07 /* Logical device select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define SIO_REG_ENABLE 0x30 /* Logical device enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define SIO_NCT6106_ID 0xc450
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define SIO_NCT6116_ID 0xd280
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define SIO_NCT6775_ID 0xb470
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define SIO_NCT6776_ID 0xc330
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define SIO_NCT6779_ID 0xc560
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define SIO_NCT6791_ID 0xc800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define SIO_NCT6792_ID 0xc910
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define SIO_NCT6793_ID 0xd120
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define SIO_NCT6795_ID 0xd350
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define SIO_NCT6796_ID 0xd420
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define SIO_NCT6797_ID 0xd450
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define SIO_NCT6798_ID 0xd428
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define SIO_ID_MASK 0xFFF8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) superio_outb(int ioreg, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) outb(reg, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) outb(val, ioreg + 1);
^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 inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) superio_inb(int ioreg, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) outb(reg, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return inb(ioreg + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) superio_select(int ioreg, int ld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) outb(SIO_REG_LDSEL, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) outb(ld, ioreg + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) superio_enter(int ioreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!request_muxed_region(ioreg, 2, DRVNAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) outb(0x87, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) outb(0x87, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) superio_exit(int ioreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) outb(0xaa, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) outb(0x02, ioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) outb(0x02, ioreg + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) release_region(ioreg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * ISA constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define IOREGION_ALIGNMENT (~7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define IOREGION_OFFSET 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define IOREGION_LENGTH 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define ADDR_REG_OFFSET 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define DATA_REG_OFFSET 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define NCT6775_REG_BANK 0x4E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define NCT6775_REG_CONFIG 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * Not currently used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * REG_MAN_ID has the value 0x5ca3 for all supported chips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * REG_MAN_ID is at port 0x4f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * REG_CHIP_ID is at port 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #define NUM_REG_ALARM 7 /* Max number of alarm registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define NUM_REG_BEEP 5 /* Max number of beep registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define NUM_FAN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Common and NCT6775 specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Voltage min/max registers for nr=7..14 are in bank 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static const u16 NCT6775_REG_IN_MAX[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 0x55c, 0x55e, 0x560, 0x562 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static const u16 NCT6775_REG_IN_MIN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 0x55d, 0x55f, 0x561, 0x563 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static const u16 NCT6775_REG_IN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
^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) #define NCT6775_REG_VBAT 0x5D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define NCT6775_REG_DIODE 0x5E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define NCT6775_DIODE_MASK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define NCT6775_REG_FANDIV1 0x506
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define NCT6775_REG_FANDIV2 0x507
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static const s8 NCT6775_ALARM_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 6, 7, 11, -1, -1, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 12, -1 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #define FAN_ALARM_BASE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define TEMP_ALARM_BASE 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #define INTRUSION_ALARM_BASE 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * 30..31 intrusion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static const s8 NCT6775_BEEP_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 21, /* global beep enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 6, 7, 11, 28, -1, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 12, -1 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define BEEP_ENABLE_BASE 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* DC or PWM output fan configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Advanced Fan control, some values are common for all fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static const u16 NCT6775_REG_TARGET[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01, 0xb01 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static const u16 NCT6775_REG_FAN_MODE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02, 0xb02 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03, 0xb03 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04, 0xb04 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05, 0xb05 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06, 0xb06 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07, 0xb07 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static const u16 NCT6775_REG_PWM[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09, 0xb09 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static const u16 NCT6775_REG_PWM_READ[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09, 0xb09 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static const u16 NCT6775_REG_FAN_PULSES[NUM_FAN] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 0x641, 0x642, 0x643, 0x644 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static const u16 NCT6775_FAN_PULSE_SHIFT[NUM_FAN] = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static const u16 NCT6775_REG_TEMP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static const u16 NCT6775_REG_TEMP_SEL[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00, 0xb00 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static const u16 NCT6775_REG_AUTO_TEMP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21, 0xb21 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static const u16 NCT6775_REG_AUTO_PWM[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27, 0xb27 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) #define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38, 0xb38 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static const char *const nct6775_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) "AUXTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) "AMD SB-TSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) "PECI Agent 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) "PECI Agent 3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) "PECI Agent 4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) "PECI Agent 5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) "PECI Agent 6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) "PECI Agent 7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) "PCH_DIM0_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) "PCH_DIM1_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) "PCH_DIM2_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) "PCH_DIM3_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #define NCT6775_TEMP_MASK 0x001ffffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) #define NCT6775_VIRT_TEMP_MASK 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static const u16 NCT6775_REG_TEMP_ALTERNATE[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) [13] = 0x661,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) [14] = 0x662,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) [15] = 0x664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static const u16 NCT6775_REG_TEMP_CRIT[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) [4] = 0xa00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) [5] = 0xa01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) [6] = 0xa02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) [7] = 0xa03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) [8] = 0xa04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) [9] = 0xa05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) [10] = 0xa06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) [11] = 0xa07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* NCT6776 specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* STEP_UP_TIME and STEP_DOWN_TIME regs are swapped for all chips but NCT6775 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) #define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) #define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static const s8 NCT6776_ALARM_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 6, 7, 11, 10, 23, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 12, 9 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static const s8 NCT6776_BEEP_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 24, /* global beep enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 25, 26, 27, 28, 29, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 30, 31 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static const u16 NCT6776_REG_TOLERANCE_H[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static const u16 NCT6776_REG_FAN_MIN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 0x63a, 0x63c, 0x63e, 0x640, 0x642, 0x64a, 0x64c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static const u16 NCT6776_REG_FAN_PULSES[NUM_FAN] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static const char *const nct6776_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) "AUXTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) "SMBUSMASTER 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) "SMBUSMASTER 3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) "SMBUSMASTER 4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) "SMBUSMASTER 5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) "SMBUSMASTER 6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) "SMBUSMASTER 7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) "PCH_DIM0_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) "PCH_DIM1_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) "PCH_DIM2_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) "PCH_DIM3_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) "BYTE_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) #define NCT6776_TEMP_MASK 0x007ffffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) #define NCT6776_VIRT_TEMP_MASK 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static const u16 NCT6776_REG_TEMP_ALTERNATE[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) [14] = 0x401,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) [15] = 0x402,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) [16] = 0x404,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static const u16 NCT6776_REG_TEMP_CRIT[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) [11] = 0x709,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) [12] = 0x70a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* NCT6779 specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static const u16 NCT6779_REG_IN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 0x459, 0x45A, 0x45B, 0x568 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static const s8 NCT6779_ALARM_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 6, 7, 11, 10, 23, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 12, 9 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static const s8 NCT6779_BEEP_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 24, /* global beep enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 25, 26, 27, 28, 29, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 30, 31 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static const u16 NCT6779_REG_FAN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static const u16 NCT6779_REG_FAN_PULSES[NUM_FAN] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 0x644, 0x645, 0x646, 0x647, 0x648, 0x649, 0x64f };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36, 0xb36 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) #define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static const u16 NCT6779_REG_CRITICAL_PWM[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37, 0xb37 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 0x18, 0x152 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 0x3a, 0x153 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 0x39, 0x155 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static const u16 NCT6779_REG_TEMP_OFFSET[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static const char *const nct6779_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) "AUXTIN0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) "AUXTIN1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) "AUXTIN2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) "AUXTIN3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) "SMBUSMASTER 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) "SMBUSMASTER 3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) "SMBUSMASTER 4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) "SMBUSMASTER 5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) "SMBUSMASTER 6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) "SMBUSMASTER 7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) "PCH_DIM0_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) "PCH_DIM1_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) "PCH_DIM2_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) "PCH_DIM3_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) "BYTE_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) "Virtual_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) #define NCT6779_TEMP_MASK 0x07ffff7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) #define NCT6779_VIRT_TEMP_MASK 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) #define NCT6791_TEMP_MASK 0x87ffff7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) #define NCT6791_VIRT_TEMP_MASK 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static const u16 NCT6779_REG_TEMP_ALTERNATE[32]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 0, 0, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 0x408, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static const u16 NCT6779_REG_TEMP_CRIT[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) [15] = 0x709,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) [16] = 0x70a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* NCT6791 specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) #define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[NUM_FAN] = { 0, 0x239 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[NUM_FAN] = { 0, 0x23a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[NUM_FAN] = { 0, 0x23b };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[NUM_FAN] = { 0, 0x23c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[NUM_FAN] = { 0, 0x23d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 0x459, 0x45A, 0x45B, 0x568, 0x45D };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static const s8 NCT6791_ALARM_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 12, 9 }; /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* NCT6792/NCT6793 specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static const u16 NCT6792_REG_TEMP_MON[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static const char *const nct6792_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) "AUXTIN0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) "AUXTIN1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) "AUXTIN2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) "AUXTIN3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) "SMBUSMASTER 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) "SMBUSMASTER 3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) "SMBUSMASTER 4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) "SMBUSMASTER 5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) "SMBUSMASTER 6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) "SMBUSMASTER 7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) "PCH_DIM0_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) "PCH_DIM1_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) "PCH_DIM2_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) "PCH_DIM3_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) "BYTE_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) "PECI Agent 0 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) "PECI Agent 1 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) "Virtual_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) #define NCT6792_TEMP_MASK 0x9fffff7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) #define NCT6792_VIRT_TEMP_MASK 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static const char *const nct6793_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) "AUXTIN0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) "AUXTIN1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) "AUXTIN2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) "AUXTIN3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) "Agent0 Dimm0 ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) "Agent0 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) "Agent1 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) "Agent1 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) "BYTE_TEMP0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) "BYTE_TEMP1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) "PECI Agent 0 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) "PECI Agent 1 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) "Virtual_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) #define NCT6793_TEMP_MASK 0xbfff037e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) #define NCT6793_VIRT_TEMP_MASK 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static const char *const nct6795_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) "AUXTIN0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) "AUXTIN1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) "AUXTIN2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) "AUXTIN3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) "SMBUSMASTER 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) "SMBUSMASTER 3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) "SMBUSMASTER 4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) "SMBUSMASTER 5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) "SMBUSMASTER 6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) "SMBUSMASTER 7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) "Agent0 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) "Agent0 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) "Agent1 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) "Agent1 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) "BYTE_TEMP0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) "BYTE_TEMP1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) "PECI Agent 0 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) "PECI Agent 1 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) "Virtual_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) #define NCT6795_TEMP_MASK 0xbfffff7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) #define NCT6795_VIRT_TEMP_MASK 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static const char *const nct6796_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) "AUXTIN0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) "AUXTIN1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) "AUXTIN2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) "AUXTIN3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) "AUXTIN4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) "Virtual_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) "Virtual_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) "",
^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) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) "Agent0 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) "Agent0 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) "Agent1 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) "Agent1 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) "BYTE_TEMP0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) "BYTE_TEMP1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) "PECI Agent 0 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) "PECI Agent 1 Calibration",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) "Virtual_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) #define NCT6796_TEMP_MASK 0xbfff0ffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) #define NCT6796_VIRT_TEMP_MASK 0x80000c00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static const char *const nct6798_temp_label[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) "SYSTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) "CPUTIN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) "AUXTIN0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) "AUXTIN1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) "AUXTIN2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) "AUXTIN3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) "AUXTIN4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) "SMBUSMASTER 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) "SMBUSMASTER 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) "Virtual_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) "Virtual_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) "PECI Agent 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) "PECI Agent 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) "PCH_CHIP_CPU_MAX_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) "PCH_CHIP_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) "PCH_CPU_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) "PCH_MCH_TEMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) "Agent0 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) "Agent0 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) "Agent1 Dimm0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) "Agent1 Dimm1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) "BYTE_TEMP0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) "BYTE_TEMP1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) "PECI Agent 0 Calibration", /* undocumented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) "PECI Agent 1 Calibration", /* undocumented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) "Virtual_TEMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) #define NCT6798_TEMP_MASK 0xbfff0ffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) #define NCT6798_VIRT_TEMP_MASK 0x80000c00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* NCT6102D/NCT6106D specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) #define NCT6106_REG_VBAT 0x318
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) #define NCT6106_REG_DIODE 0x319
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) #define NCT6106_DIODE_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static const u16 NCT6106_REG_IN_MAX[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static const u16 NCT6106_REG_IN_MIN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static const u16 NCT6106_REG_IN[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static const u16 NCT6106_REG_TEMP_HYST[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static const u16 NCT6106_REG_TEMP_OVER[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static const u16 NCT6106_REG_TEMP_CONFIG[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static const u16 NCT6106_REG_TEMP_SOURCE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 0x11b, 0x12b, 0x13b };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) #define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x18b };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static const s8 NCT6106_ALARM_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 32, 33, 34, -1, -1, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 48, -1 /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static const s8 NCT6106_BEEP_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 32, /* global beep enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 24, 25, 26, 27, 28, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 34, -1 /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) [14] = 0x51,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) [15] = 0x52,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) [16] = 0x54,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static const u16 NCT6106_REG_TEMP_CRIT[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) [11] = 0x204,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) [12] = 0x205,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* NCT6112D/NCT6114D/NCT6116D specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static const u16 NCT6116_REG_FAN[] = { 0x20, 0x22, 0x24, 0x26, 0x28 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static const u16 NCT6116_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4, 0xe6, 0xe8 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static const u16 NCT6116_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0xf6, 0xf5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static const u16 NCT6116_FAN_PULSE_SHIFT[] = { 0, 2, 4, 6, 6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static const u16 NCT6116_REG_PWM[] = { 0x119, 0x129, 0x139, 0x199, 0x1a9 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static const u16 NCT6116_REG_FAN_MODE[] = { 0x113, 0x123, 0x133, 0x193, 0x1a3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static const u16 NCT6116_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130, 0x190, 0x1a0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static const u16 NCT6116_REG_TEMP_SOURCE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 0xb0, 0xb1, 0xb2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static const u16 NCT6116_REG_CRITICAL_TEMP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 0x11a, 0x12a, 0x13a, 0x19a, 0x1aa };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static const u16 NCT6116_REG_CRITICAL_TEMP_TOLERANCE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 0x11b, 0x12b, 0x13b, 0x19b, 0x1ab };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static const u16 NCT6116_REG_CRITICAL_PWM_ENABLE[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 0x11c, 0x12c, 0x13c, 0x19c, 0x1ac };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static const u16 NCT6116_REG_CRITICAL_PWM[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 0x11d, 0x12d, 0x13d, 0x19d, 0x1ad };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static const u16 NCT6116_REG_FAN_STEP_UP_TIME[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 0x114, 0x124, 0x134, 0x194, 0x1a4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static const u16 NCT6116_REG_FAN_STEP_DOWN_TIME[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 0x115, 0x125, 0x135, 0x195, 0x1a5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static const u16 NCT6116_REG_FAN_STOP_OUTPUT[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 0x116, 0x126, 0x136, 0x196, 0x1a6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) static const u16 NCT6116_REG_FAN_START_OUTPUT[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 0x117, 0x127, 0x137, 0x197, 0x1a7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static const u16 NCT6116_REG_FAN_STOP_TIME[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 0x118, 0x128, 0x138, 0x198, 0x1a8 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static const u16 NCT6116_REG_TOLERANCE_H[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 0x112, 0x122, 0x132, 0x192, 0x1a2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static const u16 NCT6116_REG_TARGET[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 0x111, 0x121, 0x131, 0x191, 0x1a1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static const u16 NCT6116_REG_AUTO_TEMP[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 0x160, 0x170, 0x180, 0x1d0, 0x1e0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) static const u16 NCT6116_REG_AUTO_PWM[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 0x164, 0x174, 0x184, 0x1d4, 0x1e4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static const s8 NCT6116_ALARM_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 9, -1, -1, -1, -1, -1, -1, /* in8..in9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) 32, 33, 34, 35, 36, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) 16, 17, 18, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 48, -1 /* intrusion0, intrusion1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static const s8 NCT6116_BEEP_BITS[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 32, /* global beep enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 24, 25, 26, 27, 28, /* fan1..fan5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) -1, -1, -1, /* unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) 16, 17, 18, -1, -1, -1, /* temp1..temp6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 34, -1 /* intrusion0, intrusion1 */
^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) static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (mode == 0 && pwm == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return mode + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static int pwm_enable_to_reg(enum pwm_enable mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (mode == off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return mode - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * Conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* 1 is DC mode, output in ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static unsigned int step_time_from_reg(u8 reg, u8 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return mode ? 400 * reg : 100 * reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) static u8 step_time_to_reg(unsigned int msec, u8 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return clamp_val((mode ? (msec + 200) / 400 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) (msec + 50) / 100), 1, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (reg == 0 || reg == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return 1350000U / (reg << divreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if ((reg & 0xff1f) == 0xff1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (reg == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return 1350000U / reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (reg == 0 || reg == 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * Even though the registers are 16 bit wide, the fan divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * still applies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return 1350000U / (reg << divreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static unsigned int fan_from_reg_rpm(u16 reg, unsigned int divreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static u16 fan_to_reg(u32 fan, unsigned int divreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!fan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return (1350000U / fan) >> divreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static inline unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) div_from_reg(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return BIT(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * Some of the voltage inputs have internal scaling, the tables below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * contain 8 (the ADC LSB in mV) * scaling factor * 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static const u16 scale_in[15] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 800, 800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static inline long in_from_reg(u8 reg, u8 nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) static inline u8 in_to_reg(u32 val, u8 nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * Data structures and manipulation thereof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct nct6775_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int addr; /* IO base of hw monitor block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) int sioreg; /* SIO register address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) enum kinds kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) const struct attribute_group *groups[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * 3=temp_crit, 4=temp_lcrit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) u8 temp_src[NUM_TEMP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) u16 reg_temp_config[NUM_TEMP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) const char * const *temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) u32 temp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) u32 virt_temp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) u16 REG_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) u16 REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) u16 REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) u8 DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) const s8 *ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) const s8 *BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) const u16 *REG_VIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) const u16 *REG_IN_MINMAX[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) const u16 *REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) const u16 *REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) const u16 *REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) const u16 *REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) const u16 *REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) const u16 *FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) const u16 *REG_FAN_TIME[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) const u16 *REG_TOLERANCE_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) const u8 *REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) const u8 *PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * [3]=pwm_max, [4]=pwm_step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * [5]=weight_duty_step, [6]=weight_duty_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) const u16 *REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) const u16 *REG_CRITICAL_PWM_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) u8 CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) const u16 *REG_CRITICAL_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) const u16 *REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) const u16 *REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) const u16 *REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) const u16 *REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) const u16 *REG_TEMP_SOURCE; /* temp register sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) const u16 *REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) const u16 *REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) const u16 *REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) const u16 *REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) const u16 *REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct mutex update_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) bool valid; /* true if following fields are valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) unsigned long last_updated; /* In jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* Register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) u8 bank; /* current register bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) u8 in_num; /* number of in inputs we have */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) unsigned int rpm[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) u16 fan_min[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) u8 fan_pulses[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) u8 fan_div[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) u8 has_pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) u8 has_fan; /* some fan inputs can be disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) u8 has_fan_min; /* some fans don't have min register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) bool has_fan_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) u8 num_temp_alarms; /* 2, 3, or 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) u8 num_temp_beeps; /* 2, 3, or 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) u8 temp_fixed_num; /* 3 or 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) u8 temp_type[NUM_TEMP_FIXED];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) s8 temp_offset[NUM_TEMP_FIXED];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * 3=temp_crit, 4=temp_lcrit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) u64 alarms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) u64 beeps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) u8 pwm_num; /* number of pwm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) u8 pwm_mode[NUM_FAN]; /* 0->DC variable voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * 1->PWM variable duty cycle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) enum pwm_enable pwm_enable[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) /* 0->off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * 1->manual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * 2->thermal cruise mode (also called SmartFan I)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) * 3->fan speed cruise mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * 4->SmartFan III
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * 5->enhanced variable thermal cruise (SmartFan IV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * [3]=pwm_max, [4]=pwm_step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) * [5]=weight_duty_step, [6]=weight_duty_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) u8 target_temp[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) u8 target_temp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) u32 target_speed[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) u32 target_speed_tolerance[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) u8 speed_tolerance_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) u8 temp_tolerance[2][NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) u8 tolerance_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) /* Automatic fan speed control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) int auto_pwm_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) u8 auto_pwm[NUM_FAN][7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) u8 auto_temp[NUM_FAN][7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) u8 pwm_temp_sel[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) u8 pwm_weight_temp_sel[NUM_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) * 2->temp_base
^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) u8 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) u8 vrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) bool have_vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) u16 have_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) u16 have_temp_fixed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) u16 have_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /* Remember extra register values over suspend/resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) u8 vbat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) u8 fandiv1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) u8 fandiv2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) u8 sio_reg_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct nct6775_sio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int sioreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) enum kinds kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) struct sensor_device_template {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) struct device_attribute dev_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) u8 nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) } s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) } u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) bool s2; /* true if both index and nr are used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) struct sensor_device_attr_u {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) struct sensor_device_attribute a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) struct sensor_device_attribute_2 a2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) } u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) #define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .attr = {.name = _template, .mode = _mode }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) .show = _show, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .store = _store, \
^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) #define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) .u.index = _index, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .s2 = false }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) #define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) _nr, _index) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) .u.s.index = _index, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) .u.s.nr = _nr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) .s2 = true }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) #define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) static struct sensor_device_template sensor_dev_template_##_name \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) _index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) #define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) _nr, _index) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) static struct sensor_device_template sensor_dev_template_##_name \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) _nr, _index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) struct sensor_template_group {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct sensor_device_template **templates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) umode_t (*is_visible)(struct kobject *, struct attribute *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static struct attribute_group *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) nct6775_create_attr_group(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) const struct sensor_template_group *tg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int repeat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) struct attribute_group *group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) struct sensor_device_attr_u *su;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) struct sensor_device_attribute *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) struct sensor_device_attribute_2 *a2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) struct attribute **attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct sensor_device_template **t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) int i, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (repeat <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) t = tg->templates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) for (count = 0; *t; t++, count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (group == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (attrs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (su == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) group->attrs = attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) group->is_visible = tg->is_visible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) for (i = 0; i < repeat; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) t = tg->templates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) while (*t != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) snprintf(su->name, sizeof(su->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) (*t)->dev_attr.attr.name, tg->base + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if ((*t)->s2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) a2 = &su->u.a2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) sysfs_attr_init(&a2->dev_attr.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) a2->dev_attr.attr.name = su->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) a2->nr = (*t)->u.s.nr + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) a2->index = (*t)->u.s.index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) a2->dev_attr.attr.mode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) (*t)->dev_attr.attr.mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) a2->dev_attr.show = (*t)->dev_attr.show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) a2->dev_attr.store = (*t)->dev_attr.store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) *attrs = &a2->dev_attr.attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) a = &su->u.a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) sysfs_attr_init(&a->dev_attr.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) a->dev_attr.attr.name = su->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) a->index = (*t)->u.index + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) a->dev_attr.attr.mode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) (*t)->dev_attr.attr.mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) a->dev_attr.show = (*t)->dev_attr.show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) a->dev_attr.store = (*t)->dev_attr.store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) *attrs = &a->dev_attr.attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) attrs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) su++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) t++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) static bool is_word_sized(struct nct6775_data *data, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) case nct6106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) reg == 0x111 || reg == 0x121 || reg == 0x131;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) case nct6116:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) reg == 0x26 || reg == 0x28 || reg == 0xe0 || reg == 0xe2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) reg == 0xe4 || reg == 0xe6 || reg == 0xe8 || reg == 0x111 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) reg == 0x121 || reg == 0x131 || reg == 0x191 || reg == 0x1a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) case nct6775:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return (((reg & 0xff00) == 0x100 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) (reg & 0xff00) == 0x200) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) ((reg & 0x00ff) == 0x50 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) (reg & 0x00ff) == 0x53 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) (reg & 0x00ff) == 0x55)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) (reg & 0xfff0) == 0x630 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) reg == 0x640 || reg == 0x642 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) reg == 0x662 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) reg == 0x73 || reg == 0x75 || reg == 0x77;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) case nct6776:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) return (((reg & 0xff00) == 0x100 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) (reg & 0xff00) == 0x200) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ((reg & 0x00ff) == 0x50 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) (reg & 0x00ff) == 0x53 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) (reg & 0x00ff) == 0x55)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) (reg & 0xfff0) == 0x630 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) reg == 0x402 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) reg == 0x640 || reg == 0x642 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) reg == 0x73 || reg == 0x75 || reg == 0x77;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) case nct6779:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) (reg & 0xfff0) == 0x4c0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) reg == 0x402 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) reg == 0x63a || reg == 0x63c || reg == 0x63e ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) reg == 0x640 || reg == 0x642 || reg == 0x64a ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) reg == 0x64c ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) reg == 0x7b || reg == 0x7d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * On older chips, only registers 0x50-0x5f are banked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) * On more recent chips, all registers are banked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * Assume that is the case and set the bank number for each access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * Cache the bank number so it only needs to be set if it changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) u8 bank = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (data->bank != bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) outb_p(bank, data->addr + DATA_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) data->bank = bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) int res, word_sized = is_word_sized(data, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) nct6775_set_bank(data, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) res = inb_p(data->addr + DATA_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if (word_sized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) outb_p((reg & 0xff) + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) data->addr + ADDR_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) int word_sized = is_word_sized(data, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) nct6775_set_bank(data, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) if (word_sized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) outb_p((reg & 0xff) + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) data->addr + ADDR_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) /* We left-align 8-bit temperature values to make the code simpler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) u16 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) res = nct6775_read_value(data, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (!is_word_sized(data, reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) res <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (!is_word_sized(data, reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) value >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return nct6775_write_value(data, reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /* This function assumes that the caller holds data->update_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) switch (nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) | (data->fan_div[0] & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) | ((data->fan_div[1] << 4) & 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) | (data->fan_div[2] & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) | ((data->fan_div[3] << 4) & 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (data->kind == nct6775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) nct6775_write_fan_div(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) static void nct6775_update_fan_div(struct nct6775_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) data->fan_div[0] = i & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) data->fan_div[1] = (i & 0x70) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) data->fan_div[2] = i & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) if (data->has_fan & BIT(3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) data->fan_div[3] = (i & 0x70) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) static void nct6775_update_fan_div_common(struct nct6775_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (data->kind == nct6775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) nct6775_update_fan_div(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) static void nct6775_init_fan_div(struct nct6775_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) nct6775_update_fan_div_common(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * For all fans, start with highest divider value if the divider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * register is not initialized. This ensures that we get a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * reading from the fan count register, even if it is not optimal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * We'll compute a better divider later on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (!(data->has_fan & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (data->fan_div[i] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) data->fan_div[i] = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) nct6775_write_fan_div_common(data, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) static void nct6775_init_fan_common(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) struct nct6775_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (data->has_fan_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) nct6775_init_fan_div(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) * If fan_min is not set (0), set it to 0xff to disable it. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) * prevents the unnecessary warning when fanX_min is reported as 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (data->has_fan_min & BIT(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (!reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) nct6775_write_value(data, data->REG_FAN_MIN[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) data->has_fan_div ? 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) : 0xff1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) static void nct6775_select_fan_div(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) struct nct6775_data *data, int nr, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) u8 fan_div = data->fan_div[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) u16 fan_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (!data->has_fan_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) * If we failed to measure the fan speed, or the reported value is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) * in the optimal range, and the clock divider can be modified,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) * let's try that for next time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (reg == 0x00 && fan_div < 0x07)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) fan_div++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) fan_div--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) if (fan_div != data->fan_div[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) nr + 1, div_from_reg(data->fan_div[nr]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) div_from_reg(fan_div));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) /* Preserve min limit if possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) if (data->has_fan_min & BIT(nr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) fan_min = data->fan_min[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (fan_div > data->fan_div[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (fan_min != 255 && fan_min > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) fan_min >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) if (fan_min != 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) fan_min <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) if (fan_min > 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) fan_min = 254;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (fan_min != data->fan_min[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) data->fan_min[nr] = fan_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) nct6775_write_value(data, data->REG_FAN_MIN[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) fan_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) data->fan_div[nr] = fan_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) nct6775_write_fan_div_common(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) static void nct6775_update_pwm(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) int fanmodecfg, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) bool duty_is_dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) for (i = 0; i < data->pwm_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (!(data->has_pwm & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) duty_is_dc = data->REG_PWM_MODE[i] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) (nct6775_read_value(data, data->REG_PWM_MODE[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) & data->PWM_MODE_MASK[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) data->pwm_mode[i] = !duty_is_dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) data->pwm[j][i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) data->REG_PWM[j][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) (fanmodecfg >> 4) & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (!data->temp_tolerance[0][i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) data->pwm_enable[i] != speed_cruise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) if (!data->target_speed_tolerance[i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) data->pwm_enable[i] == speed_cruise) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) u8 t = fanmodecfg & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (data->REG_TOLERANCE_H) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) t |= (nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) data->target_speed_tolerance[i] = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) data->temp_tolerance[1][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) data->REG_CRITICAL_TEMP_TOLERANCE[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) data->pwm_temp_sel[i] = reg & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) /* If fan can stop, report floor as 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if (reg & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) data->pwm[2][i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) if (!data->REG_WEIGHT_TEMP_SEL[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) data->pwm_weight_temp_sel[i] = reg & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) /* If weight is disabled, report weight source as 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) if (!(reg & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) data->pwm_weight_temp_sel[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) /* Weight temp data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) data->weight_temp[j][i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) data->REG_WEIGHT_TEMP[j][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) static void nct6775_update_pwm_limits(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) u16 reg_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) for (i = 0; i < data->pwm_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) if (!(data->has_pwm & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) data->fan_time[j][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) /* Update only in matching mode or if never updated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) if (!data->target_temp[i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) data->pwm_enable[i] == thermal_cruise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) data->target_temp[i] = reg_t & data->target_temp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) if (!data->target_speed[i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) data->pwm_enable[i] == speed_cruise) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (data->REG_TOLERANCE_H) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) reg_t |= (nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) data->target_speed[i] = reg_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) for (j = 0; j < data->auto_pwm_num; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) data->auto_pwm[i][j] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) NCT6775_AUTO_PWM(data, i, j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) data->auto_temp[i][j] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) NCT6775_AUTO_TEMP(data, i, j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) /* critical auto_pwm temperature data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) data->auto_temp[i][data->auto_pwm_num] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) case nct6775:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) reg = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) NCT6775_REG_CRITICAL_ENAB[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) data->auto_pwm[i][data->auto_pwm_num] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) (reg & 0x02) ? 0xff : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) case nct6776:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) data->auto_pwm[i][data->auto_pwm_num] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) case nct6106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) case nct6116:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) case nct6779:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) reg = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) data->REG_CRITICAL_PWM_ENABLE[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) if (reg & data->CRITICAL_PWM_ENABLE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) reg = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) data->REG_CRITICAL_PWM[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) reg = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) data->auto_pwm[i][data->auto_pwm_num] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) static struct nct6775_data *nct6775_update_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) || !data->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) /* Fan clock dividers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) nct6775_update_fan_div_common(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) /* Measured voltages and limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) for (i = 0; i < data->in_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (!(data->have_in & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) data->in[i][0] = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) data->REG_VIN[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) data->in[i][1] = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) data->REG_IN_MINMAX[0][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) data->in[i][2] = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) data->REG_IN_MINMAX[1][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) /* Measured fan speeds and limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (!(data->has_fan & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) reg = nct6775_read_value(data, data->REG_FAN[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) data->rpm[i] = data->fan_from_reg(reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) data->fan_div[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (data->has_fan_min & BIT(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) data->fan_min[i] = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) data->REG_FAN_MIN[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) if (data->REG_FAN_PULSES[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) data->fan_pulses[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) (nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) data->REG_FAN_PULSES[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) >> data->FAN_PULSE_SHIFT[i]) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) nct6775_select_fan_div(dev, data, i, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) nct6775_update_pwm(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) nct6775_update_pwm_limits(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) /* Measured temperatures and limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) for (i = 0; i < NUM_TEMP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (!(data->have_temp & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (data->reg_temp[j][i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) data->temp[j][i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) = nct6775_read_temp(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) data->reg_temp[j][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) if (i >= NUM_TEMP_FIXED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) !(data->have_temp_fixed & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) data->temp_offset[i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) data->alarms = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) for (i = 0; i < NUM_REG_ALARM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) u8 alarm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if (!data->REG_ALARM[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) alarm = nct6775_read_value(data, data->REG_ALARM[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) data->alarms |= ((u64)alarm) << (i << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) data->beeps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) for (i = 0; i < NUM_REG_BEEP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) u8 beep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (!data->REG_BEEP[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) beep = nct6775_read_value(data, data->REG_BEEP[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) data->beeps |= ((u64)beep) << (i << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) data->last_updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) data->valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) * Sysfs callback functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) data->in[nr][index] = in_to_reg(val, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) data->in[nr][index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) int nr = data->ALARM_BITS[sattr->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) return sprintf(buf, "%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) (unsigned int)((data->alarms >> nr) & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) static int find_temp_source(struct nct6775_data *data, int index, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) int source = data->temp_src[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) for (nr = 0; nr < count; nr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) int src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) src = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) data->REG_TEMP_SOURCE[nr]) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) if (src == source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) return nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) unsigned int alarm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) * For temperatures, there is no fixed mapping from registers to alarm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) * bits. Alarm bits are determined by the temperature source mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) if (nr >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) alarm = (data->alarms >> bit) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) return sprintf(buf, "%u\n", alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) show_beep(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) int nr = data->BEEP_BITS[sattr->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) return sprintf(buf, "%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) (unsigned int)((data->beeps >> nr) & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) int nr = data->BEEP_BITS[sattr->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) int regindex = nr >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) if (val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) data->beeps |= (1ULL << nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) data->beeps &= ~(1ULL << nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) nct6775_write_value(data, data->REG_BEEP[regindex],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) (data->beeps >> (regindex << 3)) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) unsigned int beep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) * For temperatures, there is no fixed mapping from registers to beep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) * enable bits. Beep enable bits are determined by the temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) * source mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (nr >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) beep = (data->beeps >> bit) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) return sprintf(buf, "%u\n", beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) store_temp_beep(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) int nr, bit, regindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) if (val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (nr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) return nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) regindex = bit >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) data->beeps |= (1ULL << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) data->beeps &= ~(1ULL << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) nct6775_write_value(data, data->REG_BEEP[regindex],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) (data->beeps >> (regindex << 3)) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) static umode_t nct6775_in_is_visible(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) struct attribute *attr, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) struct device *dev = kobj_to_dev(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) int in = index / 5; /* voltage index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) if (!(data->have_in & BIT(in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) return attr->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) SENSOR_TEMPLATE(in_beep, "in%d_beep", S_IWUSR | S_IRUGO, show_beep, store_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) store_in_reg, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) store_in_reg, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) * nct6775_in_is_visible uses the index into the following array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) * to determine if attributes should be created or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) * Any change in order or content must be matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) static struct sensor_device_template *nct6775_attributes_in_template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) &sensor_dev_template_in_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) &sensor_dev_template_in_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) &sensor_dev_template_in_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) &sensor_dev_template_in_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) &sensor_dev_template_in_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) static const struct sensor_template_group nct6775_in_template_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) .templates = nct6775_attributes_in_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) .is_visible = nct6775_in_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) show_fan(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) return sprintf(buf, "%d\n", data->rpm[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) return sprintf(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) data->fan_from_reg_min(data->fan_min[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) data->fan_div[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) store_fan_min(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) u8 new_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) if (!data->has_fan_div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) /* NCT6776F or NCT6779D; we know this is a 13 bit register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) val = 0xff1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) if (val > 1350000U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) val = 135000U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) val = 1350000U / val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) val = (val & 0x1f) | ((val << 3) & 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) data->fan_min[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) goto write_min; /* Leave fan divider alone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) /* No min limit, alarm disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) data->fan_min[nr] = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) new_div = data->fan_div[nr]; /* No change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) goto write_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) reg = 1350000U / val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) if (reg >= 128 * 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) * Speed below this value cannot possibly be represented,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * even with the highest divider (128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) data->fan_min[nr] = 254;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) new_div = 7; /* 128 == BIT(7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) dev_warn(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) "fan%u low limit %lu below minimum %u, set to minimum\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) nr + 1, val, data->fan_from_reg_min(254, 7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) } else if (!reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) * Speed above this value cannot possibly be represented,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) * even with the lowest divider (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) data->fan_min[nr] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) new_div = 0; /* 1 == BIT(0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) dev_warn(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) "fan%u low limit %lu above maximum %u, set to maximum\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) nr + 1, val, data->fan_from_reg_min(1, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) * Automatically pick the best divider, i.e. the one such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) * that the min limit will correspond to a register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) * in the 96..192 range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) new_div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) while (reg > 192 && new_div < 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) reg >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) new_div++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) data->fan_min[nr] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) write_div:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) * Write both the fan clock divider (if it changed) and the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) * fan min (unconditionally)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) if (new_div != data->fan_div[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) nr + 1, div_from_reg(data->fan_div[nr]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) div_from_reg(new_div));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) data->fan_div[nr] = new_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) nct6775_write_fan_div_common(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) /* Give the chip time to sample a new speed value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) data->last_updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) write_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) int p = data->fan_pulses[sattr->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) return sprintf(buf, "%d\n", p ? : 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) store_fan_pulses(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (val > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) data->fan_pulses[nr] = val & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) static umode_t nct6775_fan_is_visible(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) struct attribute *attr, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) struct device *dev = kobj_to_dev(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) int fan = index / 6; /* fan index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) int nr = index % 6; /* attribute index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) if (!(data->has_fan & BIT(fan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) if (nr == 3 && !data->REG_FAN_PULSES[fan])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) if (nr == 4 && !(data->has_fan_min & BIT(fan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) if (nr == 5 && data->kind != nct6775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) return attr->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) FAN_ALARM_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) SENSOR_TEMPLATE(fan_beep, "fan%d_beep", S_IWUSR | S_IRUGO, show_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) store_beep, FAN_ALARM_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) store_fan_pulses, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) store_fan_min, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) * nct6775_fan_is_visible uses the index into the following array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) * to determine if attributes should be created or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) * Any change in order or content must be matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) static struct sensor_device_template *nct6775_attributes_fan_template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) &sensor_dev_template_fan_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) &sensor_dev_template_fan_alarm, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) &sensor_dev_template_fan_beep, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) &sensor_dev_template_fan_pulses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) &sensor_dev_template_fan_min, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) &sensor_dev_template_fan_div, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) static const struct sensor_template_group nct6775_fan_template_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) .templates = nct6775_attributes_fan_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) .is_visible = nct6775_fan_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) .base = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) show_temp(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) data->temp[index][nr] = LM75_TEMP_TO_REG(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) nct6775_write_temp(data, data->reg_temp[index][nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) data->temp[index][nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) store_temp_offset(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) data->temp_offset[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) store_temp_type(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) u8 vbat, diode, vbit, dbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) if (val != 1 && val != 3 && val != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) data->temp_type[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) vbit = 0x02 << nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) dbit = data->DIODE_MASK << nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) case 1: /* CPU diode (diode, current mode) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) vbat |= vbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) diode |= dbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) case 3: /* diode, voltage mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) vbat |= dbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) case 4: /* thermistor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) nct6775_write_value(data, data->REG_VBAT, vbat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) nct6775_write_value(data, data->REG_DIODE, diode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) static umode_t nct6775_temp_is_visible(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) struct attribute *attr, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) struct device *dev = kobj_to_dev(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) int temp = index / 10; /* temp index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) int nr = index % 10; /* attribute index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (!(data->have_temp & BIT(temp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) if (nr == 1 && !data->temp_label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) return 0; /* alarm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) return 0; /* beep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) if (nr == 4 && !data->reg_temp[1][temp]) /* max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) if (nr == 5 && !data->reg_temp[2][temp]) /* max_hyst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) if (nr == 6 && !data->reg_temp[3][temp]) /* crit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) if (nr == 7 && !data->reg_temp[4][temp]) /* lcrit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) /* offset and type only apply to fixed sensors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) if (nr > 7 && !(data->have_temp_fixed & BIT(temp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) return attr->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) store_temp, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) show_temp, store_temp, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) store_temp, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) store_temp, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) show_temp_offset, store_temp_offset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) store_temp_type, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) SENSOR_TEMPLATE(temp_beep, "temp%d_beep", S_IRUGO | S_IWUSR, show_temp_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) store_temp_beep, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) * nct6775_temp_is_visible uses the index into the following array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) * to determine if attributes should be created or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) * Any change in order or content must be matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) static struct sensor_device_template *nct6775_attributes_temp_template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) &sensor_dev_template_temp_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) &sensor_dev_template_temp_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) &sensor_dev_template_temp_alarm, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) &sensor_dev_template_temp_beep, /* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) &sensor_dev_template_temp_max, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) &sensor_dev_template_temp_max_hyst, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) &sensor_dev_template_temp_crit, /* 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) &sensor_dev_template_temp_lcrit, /* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) &sensor_dev_template_temp_offset, /* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) &sensor_dev_template_temp_type, /* 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) static const struct sensor_template_group nct6775_temp_template_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) .templates = nct6775_attributes_temp_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) .is_visible = nct6775_temp_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) .base = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) return sprintf(buf, "%d\n", data->pwm_mode[sattr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) store_pwm_mode(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) if (val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) /* Setting DC mode (0) is not supported for all chips/channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) if (data->REG_PWM_MODE[nr] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) data->pwm_mode[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) reg &= ~data->PWM_MODE_MASK[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) reg |= data->PWM_MODE_MASK[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) int pwm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) * For automatic fan control modes, show current pwm readings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) * Otherwise, show the configured value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) if (index == 0 && data->pwm_enable[nr] > manual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) pwm = data->pwm[index][nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) return sprintf(buf, "%d\n", pwm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) int maxval[7]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) val = clamp_val(val, minval[index], maxval[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) data->pwm[index][nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) nct6775_write_value(data, data->REG_PWM[index][nr], val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) if (index == 2) { /* floor: disable if val == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) reg &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) reg |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) /* Returns 0 if OK, -EINVAL otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) static int check_trip_points(struct nct6775_data *data, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) for (i = 0; i < data->auto_pwm_num - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) for (i = 0; i < data->auto_pwm_num - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) /* validate critical temperature and pwm if enabled (pwm > 0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) if (data->auto_pwm[nr][data->auto_pwm_num]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) if (data->auto_temp[nr][data->auto_pwm_num - 1] >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) data->auto_temp[nr][data->auto_pwm_num] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) data->auto_pwm[nr][data->auto_pwm_num - 1] >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) data->auto_pwm[nr][data->auto_pwm_num])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) static void pwm_update_registers(struct nct6775_data *data, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) switch (data->pwm_enable[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) case off:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) case manual:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) case speed_cruise:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) reg = (reg & ~data->tolerance_mask) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) (data->target_speed_tolerance[nr] & data->tolerance_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) nct6775_write_value(data, data->REG_TARGET[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) data->target_speed[nr] & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) if (data->REG_TOLERANCE_H) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) reg = (data->target_speed[nr] >> 8) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) nct6775_write_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) data->REG_TOLERANCE_H[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) case thermal_cruise:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) nct6775_write_value(data, data->REG_TARGET[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) data->target_temp[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) reg = (reg & ~data->tolerance_mask) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) data->temp_tolerance[0][nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) store_pwm_enable(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) if (val > sf4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) if (val == sf3 && data->kind != nct6775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) if (val == sf4 && check_trip_points(data, nr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) dev_err(dev, "Adjust trip points and try again\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) data->pwm_enable[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) if (val == off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) * turn off pwm control: select manual mode, set pwm to maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) data->pwm[0][nr] = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) nct6775_write_value(data, data->REG_PWM[0][nr], 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) pwm_update_registers(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) reg &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) reg |= pwm_enable_to_reg(val) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) int i, sel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) for (i = 0; i < NUM_TEMP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) if (!(data->have_temp & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) if (src == data->temp_src[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) sel = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) return sprintf(buf, "%d\n", sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) int err, reg, src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if (val == 0 || val > NUM_TEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) if (!(data->have_temp & BIT(val - 1)) || !data->temp_src[val - 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) src = data->temp_src[val - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) data->pwm_temp_sel[nr] = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) reg &= 0xe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) reg |= src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) return show_pwm_temp_sel_common(data, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) data->pwm_weight_temp_sel[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) int err, reg, src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) if (val > NUM_TEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) val = array_index_nospec(val, NUM_TEMP + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) if (val && (!(data->have_temp & BIT(val - 1)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) !data->temp_src[val - 1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) if (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) src = data->temp_src[val - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) data->pwm_weight_temp_sel[nr] = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) reg &= 0xe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) reg |= (src | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) data->pwm_weight_temp_sel[nr] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) reg &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) store_target_temp(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) data->target_temp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) data->target_temp[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) pwm_update_registers(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) return sprintf(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) fan_from_reg16(data->target_speed[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) data->fan_div[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) store_target_speed(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) u16 speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) val = clamp_val(val, 0, 1350000U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) speed = fan_to_reg(val, data->fan_div[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) data->target_speed[nr] = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) pwm_update_registers(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) show_temp_tolerance(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) store_temp_tolerance(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) /* Limit tolerance as needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) data->temp_tolerance[index][nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) if (index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) pwm_update_registers(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) nct6775_write_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) data->REG_CRITICAL_TEMP_TOLERANCE[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) * Fan speed tolerance is a tricky beast, since the associated register is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) * a tick counter, but the value is reported and configured as rpm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) * Compute resulting low and high rpm values and report the difference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) * A fan speed tolerance only makes sense if a fan target speed has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) * configured, so only display values other than 0 if that is the case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) show_speed_tolerance(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) int target = data->target_speed[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) int tolerance = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) if (target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) int low = target - data->target_speed_tolerance[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) int high = target + data->target_speed_tolerance[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) if (low <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) low = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) if (high > 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) high = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) if (high < low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) high = low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) tolerance = (fan_from_reg16(low, data->fan_div[nr])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) - fan_from_reg16(high, data->fan_div[nr])) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) return sprintf(buf, "%d\n", tolerance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) store_speed_tolerance(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) int nr = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) int low, high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) high = fan_from_reg16(data->target_speed[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) data->fan_div[nr]) + val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) low = fan_from_reg16(data->target_speed[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) data->fan_div[nr]) - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) if (low <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) low = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) if (high < low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) high = low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) val = (fan_to_reg(low, data->fan_div[nr]) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) fan_to_reg(high, data->fan_div[nr])) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) /* Limit tolerance as needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) val = clamp_val(val, 0, data->speed_tolerance_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) data->target_speed_tolerance[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) pwm_update_registers(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) store_pwm_mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) store_pwm_enable, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) show_pwm_temp_sel, store_pwm_temp_sel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) show_target_temp, store_target_temp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) show_target_speed, store_target_speed, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) show_speed_tolerance, store_speed_tolerance, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) /* Smart Fan registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) store_weight_temp(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) data->weight_temp[index][nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) return sprintf(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) step_time_from_reg(data->fan_time[index][nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) data->pwm_mode[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) store_fan_time(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) int index = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) val = step_time_to_reg(val, data->pwm_mode[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) data->fan_time[index][nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) store_auto_pwm(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) int point = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) if (val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) if (point == data->auto_pwm_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) if (data->kind != nct6775 && !val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) if (data->kind != nct6779 && val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) val = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) data->auto_pwm[nr][point] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) if (point < data->auto_pwm_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) nct6775_write_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) NCT6775_AUTO_PWM(data, nr, point),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) data->auto_pwm[nr][point]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) case nct6775:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) /* disable if needed (pwm == 0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) reg = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) NCT6775_REG_CRITICAL_ENAB[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) reg |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) reg &= ~0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) case nct6776:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) break; /* always enabled, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) case nct6106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) case nct6116:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) case nct6779:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) reg = nct6775_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) data->REG_CRITICAL_PWM_ENABLE[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) if (val == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) reg |= data->CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) nct6775_write_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) data->REG_CRITICAL_PWM_ENABLE[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) int point = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) * We don't know for sure if the temperature is signed or unsigned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) * Assume it is unsigned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) store_auto_temp(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) int nr = sattr->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) int point = sattr->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) if (val > 255000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) if (point < data->auto_pwm_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) nct6775_write_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) NCT6775_AUTO_TEMP(data, nr, point),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) data->auto_temp[nr][point]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) data->auto_temp[nr][point]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) struct attribute *attr, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) struct device *dev = kobj_to_dev(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) int pwm = index / 36; /* pwm index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) int nr = index % 36; /* attribute index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) if (!(data->has_pwm & BIT(pwm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) if ((nr >= 14 && nr <= 18) || nr == 21) /* weight */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) if (!data->REG_WEIGHT_TEMP_SEL[pwm])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) if (nr >= 22 && nr <= 35) { /* auto point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) int api = (nr - 22) / 2; /* auto point index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) if (api > data->auto_pwm_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) return attr->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) show_fan_time, store_fan_time, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) show_fan_time, store_fan_time, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) show_fan_time, store_fan_time, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) store_pwm, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) store_pwm, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) show_temp_tolerance, store_temp_tolerance, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) store_pwm, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) * nct6775_pwm_is_visible uses the index into the following array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) * to determine if attributes should be created or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) * Any change in order or content must be matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) &sensor_dev_template_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) &sensor_dev_template_pwm_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) &sensor_dev_template_pwm_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) &sensor_dev_template_pwm_temp_sel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) &sensor_dev_template_pwm_temp_tolerance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) &sensor_dev_template_pwm_crit_temp_tolerance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) &sensor_dev_template_pwm_target_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) &sensor_dev_template_fan_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) &sensor_dev_template_fan_tolerance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) &sensor_dev_template_pwm_stop_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) &sensor_dev_template_pwm_step_up_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) &sensor_dev_template_pwm_step_down_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) &sensor_dev_template_pwm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) &sensor_dev_template_pwm_floor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) &sensor_dev_template_pwm_weight_temp_sel, /* 14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) &sensor_dev_template_pwm_weight_temp_step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) &sensor_dev_template_pwm_weight_temp_step_tol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) &sensor_dev_template_pwm_weight_temp_step_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) &sensor_dev_template_pwm_weight_duty_step, /* 18 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) &sensor_dev_template_pwm_max, /* 19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) &sensor_dev_template_pwm_step, /* 20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) &sensor_dev_template_pwm_weight_duty_base, /* 21 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) &sensor_dev_template_pwm_auto_point1_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) &sensor_dev_template_pwm_auto_point2_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) &sensor_dev_template_pwm_auto_point2_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) &sensor_dev_template_pwm_auto_point3_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) &sensor_dev_template_pwm_auto_point3_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) &sensor_dev_template_pwm_auto_point4_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) &sensor_dev_template_pwm_auto_point4_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) &sensor_dev_template_pwm_auto_point5_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) &sensor_dev_template_pwm_auto_point5_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) &sensor_dev_template_pwm_auto_point6_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) &sensor_dev_template_pwm_auto_point6_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) &sensor_dev_template_pwm_auto_point7_pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) static const struct sensor_template_group nct6775_pwm_template_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) .templates = nct6775_attributes_pwm_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) .is_visible = nct6775_pwm_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) .base = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) cpu0_vid_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) static DEVICE_ATTR_RO(cpu0_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) /* Case open detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) clear_caseopen(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) if (kstrtoul(buf, 10, &val) || val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) * Use CR registers to clear caseopen status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) * The CR registers are the same for all chips, and not all chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) * support clearing the caseopen status through "regular" registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) ret = superio_enter(data->sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) count = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) superio_select(data->sioreg, NCT6775_LD_ACPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) superio_exit(data->sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) data->valid = false; /* Force cache refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) clear_caseopen, INTRUSION_ALARM_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) clear_caseopen, INTRUSION_ALARM_BASE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) static SENSOR_DEVICE_ATTR(intrusion0_beep, S_IWUSR | S_IRUGO, show_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) store_beep, INTRUSION_ALARM_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) store_beep, INTRUSION_ALARM_BASE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) store_beep, BEEP_ENABLE_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) static umode_t nct6775_other_is_visible(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) struct attribute *attr, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) struct device *dev = kobj_to_dev(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) if (index == 0 && !data->have_vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) if (index == 1 || index == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) if (index == 3 || index == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) return attr->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) * nct6775_other_is_visible uses the index into the following array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) * to determine if attributes should be created or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) * Any change in order or content must be matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) static struct attribute *nct6775_attributes_other[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) &dev_attr_cpu0_vid.attr, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) static const struct attribute_group nct6775_group_other = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) .attrs = nct6775_attributes_other,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) .is_visible = nct6775_other_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) static inline void nct6775_init_device(struct nct6775_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) u8 tmp, diode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) /* Start monitoring if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) if (data->REG_CONFIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) tmp = nct6775_read_value(data, data->REG_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) if (!(tmp & 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) /* Enable temperature sensors if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) for (i = 0; i < NUM_TEMP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) if (!(data->have_temp & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) if (!data->reg_temp_config[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) tmp = nct6775_read_value(data, data->reg_temp_config[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) if (tmp & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) nct6775_write_value(data, data->reg_temp_config[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) tmp & 0xfe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) /* Enable VBAT monitoring if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) tmp = nct6775_read_value(data, data->REG_VBAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) if (!(tmp & 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) diode = nct6775_read_value(data, data->REG_DIODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) for (i = 0; i < data->temp_fixed_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) if (!(data->have_temp_fixed & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) if ((tmp & (data->DIODE_MASK << i))) /* diode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) data->temp_type[i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) = 3 - ((diode >> i) & data->DIODE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) else /* thermistor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) data->temp_type[i] = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) nct6775_check_fan_inputs(struct nct6775_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) bool fan3pin = false, fan4pin = false, fan4min = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) bool fan5pin = false, fan6pin = false, fan7pin = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) bool pwm3pin = false, pwm4pin = false, pwm5pin = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) bool pwm6pin = false, pwm7pin = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) int sioreg = data->sioreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) /* Store SIO_REG_ENABLE for use during resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) superio_select(sioreg, NCT6775_LD_HWM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) data->sio_reg_enable = superio_inb(sioreg, SIO_REG_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) /* fan4 and fan5 share some pins with the GPIO and serial flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) if (data->kind == nct6775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) int cr2c = superio_inb(sioreg, 0x2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) fan3pin = cr2c & BIT(6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) pwm3pin = cr2c & BIT(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) /* On NCT6775, fan4 shares pins with the fdc interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) } else if (data->kind == nct6776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) bool gpok = superio_inb(sioreg, 0x27) & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) const char *board_vendor, *board_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) board_name = dmi_get_system_info(DMI_BOARD_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) if (board_name && board_vendor &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) !strcmp(board_vendor, "ASRock")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) * Auxiliary fan monitoring is not enabled on ASRock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) * Z77 Pro4-M if booted in UEFI Ultra-FastBoot mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) * Observed with BIOS version 2.00.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) if (!strcmp(board_name, "Z77 Pro4-M")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) if ((data->sio_reg_enable & 0xe0) != 0xe0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) data->sio_reg_enable |= 0xe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) superio_outb(sioreg, SIO_REG_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) data->sio_reg_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) if (data->sio_reg_enable & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) fan3pin = gpok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) if (data->sio_reg_enable & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) fan4pin = gpok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) if (data->sio_reg_enable & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) fan5pin = gpok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) fan4min = fan4pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) pwm3pin = fan3pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) } else if (data->kind == nct6106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) int cr24 = superio_inb(sioreg, 0x24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) fan3pin = !(cr24 & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) pwm3pin = cr24 & 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) } else if (data->kind == nct6116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) int cr1a = superio_inb(sioreg, 0x1a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) int cr1b = superio_inb(sioreg, 0x1b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) int cr24 = superio_inb(sioreg, 0x24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) int cr2a = superio_inb(sioreg, 0x2a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) int cr2b = superio_inb(sioreg, 0x2b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) int cr2f = superio_inb(sioreg, 0x2f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) fan3pin = !(cr2b & 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) fan4pin = (cr2b & 0x80) || // pin 1(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) (!(cr2f & 0x10) && (cr1a & 0x04)); // pin 65(66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) fan5pin = (cr2b & 0x80) || // pin 126(127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) (!(cr1b & 0x03) && (cr2a & 0x02)); // pin 94(96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) pwm3pin = fan3pin && (cr24 & 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) pwm4pin = fan4pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) pwm5pin = fan5pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) * NCT6797D, NCT6798D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) int cr1a = superio_inb(sioreg, 0x1a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) int cr1b = superio_inb(sioreg, 0x1b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) int cr1c = superio_inb(sioreg, 0x1c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) int cr1d = superio_inb(sioreg, 0x1d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) int cr2a = superio_inb(sioreg, 0x2a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) int cr2b = superio_inb(sioreg, 0x2b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) int cr2d = superio_inb(sioreg, 0x2d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) int cr2f = superio_inb(sioreg, 0x2f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) bool dsw_en = cr2f & BIT(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) bool ddr4_en = cr2f & BIT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) int cre0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) int creb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) int cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) superio_select(sioreg, NCT6775_LD_12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) cre0 = superio_inb(sioreg, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) creb = superio_inb(sioreg, 0xeb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) cred = superio_inb(sioreg, 0xed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) fan3pin = !(cr1c & BIT(5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) fan4pin = !(cr1c & BIT(6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) fan5pin = !(cr1c & BIT(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) pwm3pin = !(cr1c & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) pwm4pin = !(cr1c & BIT(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) pwm5pin = !(cr1c & BIT(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) fan6pin = cr2d & BIT(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) pwm6pin = cr2d & BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) fan6pin = !dsw_en && (cr2d & BIT(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) pwm6pin = !dsw_en && (cr2d & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) fan5pin |= cr1b & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) fan5pin |= creb & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) fan6pin = !dsw_en && (cr2d & BIT(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) fan6pin |= creb & BIT(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) pwm5pin |= cr2d & BIT(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) pwm6pin = !dsw_en && (cr2d & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) pwm6pin |= creb & BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) fan5pin |= cr1b & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) fan5pin |= creb & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) fan6pin = (cr2a & BIT(4)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) (!dsw_en || (cred & BIT(4)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) fan6pin |= creb & BIT(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) pwm5pin |= cr2d & BIT(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) pwm6pin = (cr2a & BIT(3)) && (cred & BIT(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) pwm6pin |= creb & BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) fan5pin |= cr1b & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) fan5pin |= (cre0 & BIT(3)) && !(cr1b & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) fan5pin |= creb & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) fan6pin = (cr2a & BIT(4)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) (!dsw_en || (cred & BIT(4)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) fan6pin |= creb & BIT(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) fan7pin = !(cr2b & BIT(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) pwm5pin |= cr2d & BIT(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) pwm5pin |= (cre0 & BIT(4)) && !(cr1b & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) pwm6pin = (cr2a & BIT(3)) && (cred & BIT(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) pwm6pin |= creb & BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) pwm7pin = !(cr1d & (BIT(2) | BIT(3)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) fan5pin |= !ddr4_en && (cr1b & BIT(5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) fan5pin |= creb & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) fan6pin = cr2a & BIT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) fan6pin |= creb & BIT(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) fan7pin = cr1a & BIT(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) pwm5pin |= !ddr4_en && (cr2d & BIT(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) pwm6pin = creb & BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) pwm6pin |= cred & BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) pwm7pin = cr1d & BIT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) fan6pin |= cr2a & BIT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) fan6pin |= creb & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) fan7pin = cr1b & BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) fan7pin |= !(cr2b & BIT(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) fan7pin |= creb & BIT(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) pwm6pin |= !(cred & BIT(2)) && (cr2a & BIT(3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) pwm7pin = !(cr1d & (BIT(2) | BIT(3)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) pwm7pin |= cr2d & BIT(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) pwm7pin |= creb & BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) default: /* NCT6779D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) fan4min = fan4pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) /* fan 1 and 2 (0x03) are always present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) (fan5pin << 4) | (fan6pin << 5) | (fan7pin << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) (fan5pin << 4) | (fan6pin << 5) | (fan7pin << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) (pwm5pin << 4) | (pwm6pin << 5) | (pwm7pin << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) int *available, int *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) u8 src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) for (i = 0; i < data->pwm_num && *available; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) if (!regp[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) src = nct6775_read_value(data, regp[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) src &= 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) if (!src || (*mask & BIT(src)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) if (!(data->temp_mask & BIT(src)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) index = __ffs(*available);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) *available &= ~BIT(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) *mask |= BIT(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) static int nct6775_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) struct nct6775_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) int i, s, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) int src, mask, available;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) int num_reg_temp, num_reg_temp_mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) u8 cr2a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) struct attribute_group *group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) int num_attr_groups = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) res = platform_get_resource(pdev, IORESOURCE_IO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) DRVNAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) data->kind = sio_data->kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) data->sioreg = sio_data->sioreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) data->addr = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) mutex_init(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) data->name = nct6775_device_names[data->kind];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) data->bank = 0xff; /* Force initial bank selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) case nct6106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) data->in_num = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) data->pwm_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) data->auto_pwm_num = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) data->temp_fixed_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) data->num_temp_alarms = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) data->num_temp_beeps = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) data->fan_from_reg = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) data->fan_from_reg_min = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) data->temp_label = nct6776_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) data->temp_mask = NCT6776_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) data->REG_VBAT = NCT6106_REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) data->REG_DIODE = NCT6106_REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) data->DIODE_MASK = NCT6106_DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) data->REG_VIN = NCT6106_REG_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) data->REG_TARGET = NCT6106_REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) data->REG_FAN = NCT6106_REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) data->REG_TOLERANCE_H = NCT6106_REG_TOLERANCE_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) data->REG_PWM[0] = NCT6116_REG_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) data->REG_PWM_READ = NCT6106_REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) data->REG_CRITICAL_TEMP_TOLERANCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) data->CRITICAL_PWM_ENABLE_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) = NCT6106_CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) data->REG_ALARM = NCT6106_REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) data->ALARM_BITS = NCT6106_ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) data->REG_BEEP = NCT6106_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) data->BEEP_BITS = NCT6106_BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) reg_temp = NCT6106_REG_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) reg_temp_mon = NCT6106_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) reg_temp_over = NCT6106_REG_TEMP_OVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) reg_temp_hyst = NCT6106_REG_TEMP_HYST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) reg_temp_config = NCT6106_REG_TEMP_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) reg_temp_crit = NCT6106_REG_TEMP_CRIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) case nct6116:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) data->in_num = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) data->pwm_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) data->auto_pwm_num = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) data->temp_fixed_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) data->num_temp_alarms = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) data->num_temp_beeps = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) data->fan_from_reg = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) data->fan_from_reg_min = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) data->temp_label = nct6776_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) data->temp_mask = NCT6776_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) data->REG_VBAT = NCT6106_REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) data->REG_DIODE = NCT6106_REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) data->DIODE_MASK = NCT6106_DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) data->REG_VIN = NCT6106_REG_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) data->REG_TARGET = NCT6116_REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) data->REG_FAN = NCT6116_REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) data->REG_FAN_MODE = NCT6116_REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) data->REG_FAN_MIN = NCT6116_REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) data->REG_FAN_PULSES = NCT6116_REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) data->FAN_PULSE_SHIFT = NCT6116_FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) data->REG_FAN_TIME[0] = NCT6116_REG_FAN_STOP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) data->REG_FAN_TIME[1] = NCT6116_REG_FAN_STEP_UP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) data->REG_FAN_TIME[2] = NCT6116_REG_FAN_STEP_DOWN_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) data->REG_TOLERANCE_H = NCT6116_REG_TOLERANCE_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) data->REG_PWM[0] = NCT6116_REG_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) data->REG_PWM[1] = NCT6116_REG_FAN_START_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) data->REG_PWM[2] = NCT6116_REG_FAN_STOP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) data->REG_PWM_READ = NCT6106_REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) data->REG_AUTO_TEMP = NCT6116_REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) data->REG_AUTO_PWM = NCT6116_REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) data->REG_CRITICAL_TEMP = NCT6116_REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) data->REG_CRITICAL_TEMP_TOLERANCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) = NCT6116_REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) data->REG_CRITICAL_PWM_ENABLE = NCT6116_REG_CRITICAL_PWM_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) data->CRITICAL_PWM_ENABLE_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) = NCT6106_CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) data->REG_CRITICAL_PWM = NCT6116_REG_CRITICAL_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) data->REG_TEMP_SOURCE = NCT6116_REG_TEMP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) data->REG_ALARM = NCT6106_REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) data->ALARM_BITS = NCT6116_ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) data->REG_BEEP = NCT6106_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) data->BEEP_BITS = NCT6116_BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) reg_temp = NCT6106_REG_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) reg_temp_mon = NCT6106_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) reg_temp_over = NCT6106_REG_TEMP_OVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) reg_temp_hyst = NCT6106_REG_TEMP_HYST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) reg_temp_config = NCT6106_REG_TEMP_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) reg_temp_crit = NCT6106_REG_TEMP_CRIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) case nct6775:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) data->in_num = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) data->pwm_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) data->auto_pwm_num = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) data->has_fan_div = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) data->temp_fixed_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) data->num_temp_alarms = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) data->num_temp_beeps = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) data->ALARM_BITS = NCT6775_ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) data->BEEP_BITS = NCT6775_BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) data->fan_from_reg = fan_from_reg16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) data->fan_from_reg_min = fan_from_reg8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) data->target_temp_mask = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) data->tolerance_mask = 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) data->speed_tolerance_limit = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) data->temp_label = nct6775_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) data->temp_mask = NCT6775_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) data->virt_temp_mask = NCT6775_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) data->REG_CONFIG = NCT6775_REG_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) data->REG_VBAT = NCT6775_REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) data->REG_DIODE = NCT6775_REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) data->DIODE_MASK = NCT6775_DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) data->REG_VIN = NCT6775_REG_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) data->REG_TARGET = NCT6775_REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) data->REG_FAN = NCT6775_REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) data->REG_PWM[0] = NCT6775_REG_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) data->REG_PWM_READ = NCT6775_REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) data->REG_CRITICAL_TEMP_TOLERANCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) data->REG_ALARM = NCT6775_REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) data->REG_BEEP = NCT6775_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) reg_temp = NCT6775_REG_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) reg_temp_mon = NCT6775_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) reg_temp_over = NCT6775_REG_TEMP_OVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) reg_temp_hyst = NCT6775_REG_TEMP_HYST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) reg_temp_config = NCT6775_REG_TEMP_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) reg_temp_crit = NCT6775_REG_TEMP_CRIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) case nct6776:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) data->in_num = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) data->pwm_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) data->auto_pwm_num = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) data->has_fan_div = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) data->temp_fixed_num = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) data->num_temp_alarms = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) data->num_temp_beeps = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) data->ALARM_BITS = NCT6776_ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) data->BEEP_BITS = NCT6776_BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) data->fan_from_reg = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) data->fan_from_reg_min = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) data->target_temp_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) data->tolerance_mask = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) data->speed_tolerance_limit = 63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) data->temp_label = nct6776_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) data->temp_mask = NCT6776_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) data->REG_CONFIG = NCT6775_REG_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) data->REG_VBAT = NCT6775_REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) data->REG_DIODE = NCT6775_REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) data->DIODE_MASK = NCT6775_DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) data->REG_VIN = NCT6775_REG_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) data->REG_TARGET = NCT6775_REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) data->REG_FAN = NCT6775_REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) data->REG_PWM[0] = NCT6775_REG_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) data->REG_PWM_READ = NCT6775_REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) data->REG_CRITICAL_TEMP_TOLERANCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) data->REG_ALARM = NCT6775_REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) data->REG_BEEP = NCT6776_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) reg_temp = NCT6775_REG_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) reg_temp_mon = NCT6775_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) reg_temp_over = NCT6775_REG_TEMP_OVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) reg_temp_hyst = NCT6775_REG_TEMP_HYST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) reg_temp_config = NCT6776_REG_TEMP_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) reg_temp_crit = NCT6776_REG_TEMP_CRIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) case nct6779:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) data->in_num = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) data->pwm_num = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) data->auto_pwm_num = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) data->has_fan_div = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) data->temp_fixed_num = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) data->num_temp_alarms = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) data->num_temp_beeps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) data->ALARM_BITS = NCT6779_ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) data->BEEP_BITS = NCT6779_BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) data->fan_from_reg = fan_from_reg_rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) data->fan_from_reg_min = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) data->target_temp_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) data->tolerance_mask = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) data->speed_tolerance_limit = 63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) data->temp_label = nct6779_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) data->temp_mask = NCT6779_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) data->virt_temp_mask = NCT6779_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) data->REG_CONFIG = NCT6775_REG_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) data->REG_VBAT = NCT6775_REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) data->REG_DIODE = NCT6775_REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) data->DIODE_MASK = NCT6775_DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) data->REG_VIN = NCT6779_REG_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) data->REG_TARGET = NCT6775_REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) data->REG_FAN = NCT6779_REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) data->REG_PWM[0] = NCT6775_REG_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) data->REG_PWM_READ = NCT6775_REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) data->REG_CRITICAL_TEMP_TOLERANCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) data->CRITICAL_PWM_ENABLE_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) = NCT6779_CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) data->REG_ALARM = NCT6779_REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) data->REG_BEEP = NCT6776_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) reg_temp = NCT6779_REG_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) reg_temp_mon = NCT6779_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) reg_temp_over = NCT6779_REG_TEMP_OVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) reg_temp_hyst = NCT6779_REG_TEMP_HYST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) reg_temp_config = NCT6779_REG_TEMP_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) reg_temp_crit = NCT6779_REG_TEMP_CRIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) data->in_num = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) data->pwm_num = (data->kind == nct6796 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) data->kind == nct6797 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) data->kind == nct6798) ? 7 : 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) data->auto_pwm_num = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) data->has_fan_div = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) data->temp_fixed_num = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) data->num_temp_alarms = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) data->num_temp_beeps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) data->ALARM_BITS = NCT6791_ALARM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) data->BEEP_BITS = NCT6779_BEEP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) data->fan_from_reg = fan_from_reg_rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) data->fan_from_reg_min = fan_from_reg13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) data->target_temp_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) data->tolerance_mask = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) data->speed_tolerance_limit = 63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) data->temp_label = nct6779_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) data->temp_mask = NCT6791_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) data->virt_temp_mask = NCT6791_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) data->temp_label = nct6792_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) data->temp_mask = NCT6792_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) data->virt_temp_mask = NCT6792_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) data->temp_label = nct6793_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) data->temp_mask = NCT6793_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) data->virt_temp_mask = NCT6793_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) data->temp_label = nct6795_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) data->temp_mask = NCT6795_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) data->virt_temp_mask = NCT6795_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) data->temp_label = nct6796_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) data->temp_mask = NCT6796_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) data->virt_temp_mask = NCT6796_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) data->temp_label = nct6798_temp_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) data->temp_mask = NCT6798_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) data->REG_CONFIG = NCT6775_REG_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) data->REG_VBAT = NCT6775_REG_VBAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) data->REG_DIODE = NCT6775_REG_DIODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) data->DIODE_MASK = NCT6775_DIODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) data->REG_VIN = NCT6779_REG_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) data->REG_TARGET = NCT6775_REG_TARGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) data->REG_FAN = NCT6779_REG_FAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) data->REG_PWM[0] = NCT6775_REG_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) data->REG_PWM_READ = NCT6775_REG_PWM_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) data->REG_CRITICAL_TEMP_TOLERANCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) data->CRITICAL_PWM_ENABLE_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) = NCT6779_CRITICAL_PWM_ENABLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) data->REG_ALARM = NCT6791_REG_ALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) if (data->kind == nct6791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) data->REG_BEEP = NCT6776_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) data->REG_BEEP = NCT6792_REG_BEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) reg_temp = NCT6779_REG_TEMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) if (data->kind == nct6791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) reg_temp_mon = NCT6779_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) reg_temp_mon = NCT6792_REG_TEMP_MON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) num_reg_temp_mon = ARRAY_SIZE(NCT6792_REG_TEMP_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) reg_temp_over = NCT6779_REG_TEMP_OVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) reg_temp_hyst = NCT6779_REG_TEMP_HYST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) reg_temp_config = NCT6779_REG_TEMP_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) reg_temp_crit = NCT6779_REG_TEMP_CRIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) data->have_in = BIT(data->in_num) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) data->have_temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) * On some boards, not all available temperature sources are monitored,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) * even though some of the monitoring registers are unused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) * Get list of unused monitoring registers, then detect if any fan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) * controls are configured to use unmonitored temperature sources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) * If so, assign the unmonitored temperature sources to available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) * monitoring registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335) available = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) for (i = 0; i < num_reg_temp; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) if (reg_temp[i] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) if (!src || (mask & BIT(src)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) available |= BIT(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) mask |= BIT(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) * Now find unmonitored temperature registers and enable monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) * if additional monitoring registers are available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) for (i = 0; i < num_reg_temp; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) if (reg_temp[i] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360) src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) if (!src || (mask & BIT(src)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) if (!(data->temp_mask & BIT(src))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) dev_info(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367) src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371) mask |= BIT(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) if (src <= data->temp_fixed_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) data->have_temp |= BIT(src - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376) data->have_temp_fixed |= BIT(src - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) data->reg_temp[0][src - 1] = reg_temp[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) data->reg_temp[1][src - 1] = reg_temp_over[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379) data->reg_temp[2][src - 1] = reg_temp_hyst[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380) if (reg_temp_crit_h && reg_temp_crit_h[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) else if (reg_temp_crit[src - 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) data->reg_temp[3][src - 1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) = reg_temp_crit[src - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) if (reg_temp_crit_l && reg_temp_crit_l[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) data->reg_temp_config[src - 1] = reg_temp_config[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) data->temp_src[src - 1] = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) if (s >= NUM_TEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395) /* Use dynamic index for other sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396) data->have_temp |= BIT(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) data->reg_temp[0][s] = reg_temp[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) data->reg_temp[1][s] = reg_temp_over[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) data->reg_temp[2][s] = reg_temp_hyst[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) data->reg_temp_config[s] = reg_temp_config[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) if (reg_temp_crit_h && reg_temp_crit_h[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) data->reg_temp[3][s] = reg_temp_crit_h[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) else if (reg_temp_crit[src - 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) data->reg_temp[3][s] = reg_temp_crit[src - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) if (reg_temp_crit_l && reg_temp_crit_l[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406) data->reg_temp[4][s] = reg_temp_crit_l[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) data->temp_src[s] = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) * Repeat with temperatures used for fan control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) * This set of registers does not support limits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) for (i = 0; i < num_reg_temp_mon; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) if (reg_temp_mon[i] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) if (!src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) if (!(data->temp_mask & BIT(src))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) dev_info(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) src, i, data->REG_TEMP_SEL[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) reg_temp_mon[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) * For virtual temperature sources, the 'virtual' temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) * for each fan reflects a different temperature, and there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) * are no duplicates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) if (!(data->virt_temp_mask & BIT(src))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438) if (mask & BIT(src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440) mask |= BIT(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) if (src <= data->temp_fixed_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) if (data->have_temp & BIT(src - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447) data->have_temp |= BIT(src - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) data->have_temp_fixed |= BIT(src - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) data->reg_temp[0][src - 1] = reg_temp_mon[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450) data->temp_src[src - 1] = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) if (s >= NUM_TEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) /* Use dynamic index for other sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) data->have_temp |= BIT(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) data->reg_temp[0][s] = reg_temp_mon[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) data->temp_src[s] = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461) s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) #ifdef USE_ALTERNATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) * Go through the list of alternate temp registers and enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) * if possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) * The temperature is already monitored if the respective bit in <mask>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) * is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) for (i = 0; i < 31; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) if (!(data->temp_mask & BIT(i + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474) if (!reg_temp_alternate[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476) if (mask & BIT(i + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) if (i < data->temp_fixed_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) if (data->have_temp & BIT(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) data->have_temp |= BIT(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) data->have_temp_fixed |= BIT(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) data->reg_temp[0][i] = reg_temp_alternate[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) if (i < num_reg_temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) data->reg_temp[1][i] = reg_temp_over[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) data->reg_temp[2][i] = reg_temp_hyst[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) data->temp_src[i] = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) if (s >= NUM_TEMP) /* Abort if no more space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) data->have_temp |= BIT(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) data->reg_temp[0][s] = reg_temp_alternate[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) data->temp_src[s] = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) #endif /* USE_ALTERNATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) /* Initialize the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) nct6775_init_device(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) err = superio_enter(sio_data->sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) cr2a = superio_inb(sio_data->sioreg, 0x2a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) case nct6775:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) data->have_vid = (cr2a & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) case nct6776:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) data->have_vid = (cr2a & 0x60) == 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) case nct6106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) case nct6116:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) case nct6779:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) * Read VID value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) * We can get the VID input values directly at logical device D 0xe3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) if (data->have_vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) superio_select(sio_data->sioreg, NCT6775_LD_VID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) data->vid = superio_inb(sio_data->sioreg, 0xe3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) data->vrm = vid_which_vrm();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) if (fan_debounce) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) superio_select(sio_data->sioreg, NCT6775_LD_HWM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544) tmp = superio_inb(sio_data->sioreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) NCT6775_REG_CR_FAN_DEBOUNCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) switch (data->kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) case nct6106:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) case nct6116:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) tmp |= 0xe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) case nct6775:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) tmp |= 0x1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554) case nct6776:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) case nct6779:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) tmp |= 0x3e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) case nct6791:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559) case nct6792:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) case nct6793:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) case nct6795:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562) case nct6796:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563) case nct6797:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) case nct6798:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565) tmp |= 0x7e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568) superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570) dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571) data->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574) nct6775_check_fan_inputs(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) superio_exit(sio_data->sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) /* Read fan clock dividers immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579) nct6775_init_fan_common(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581) /* Register sysfs hooks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582) group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583) data->pwm_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584) if (IS_ERR(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585) return PTR_ERR(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587) data->groups[num_attr_groups++] = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589) group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) fls(data->have_in));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) if (IS_ERR(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592) return PTR_ERR(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) data->groups[num_attr_groups++] = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597) fls(data->has_fan));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) if (IS_ERR(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599) return PTR_ERR(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) data->groups[num_attr_groups++] = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604) fls(data->have_temp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605) if (IS_ERR(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606) return PTR_ERR(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) data->groups[num_attr_groups++] = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) data->groups[num_attr_groups++] = &nct6775_group_other;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611) hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) data, data->groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) return PTR_ERR_OR_ZERO(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616) static void nct6791_enable_io_mapping(int sioaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621) if (val & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) pr_info("Enabling hardware monitor logical device mappings.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623) superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624) val & ~0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628) static int __maybe_unused nct6775_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630) struct nct6775_data *data = nct6775_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633) data->vbat = nct6775_read_value(data, data->REG_VBAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) if (data->kind == nct6775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636) data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643) static int __maybe_unused nct6775_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) struct nct6775_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) int sioreg = data->sioreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647) int i, j, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651) data->bank = 0xff; /* Force initial bank selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) err = superio_enter(sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) goto abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) superio_select(sioreg, NCT6775_LD_HWM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) reg = superio_inb(sioreg, SIO_REG_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659) if (reg != data->sio_reg_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660) superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662) if (data->kind == nct6791 || data->kind == nct6792 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663) data->kind == nct6793 || data->kind == nct6795 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) data->kind == nct6796 || data->kind == nct6797 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665) data->kind == nct6798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) nct6791_enable_io_mapping(sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668) superio_exit(sioreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) /* Restore limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671) for (i = 0; i < data->in_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672) if (!(data->have_in & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675) nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676) data->in[i][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) data->in[i][2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681) for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) if (!(data->has_fan_min & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) nct6775_write_value(data, data->REG_FAN_MIN[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) data->fan_min[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) for (i = 0; i < NUM_TEMP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) if (!(data->have_temp & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693) for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) if (data->reg_temp[j][i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695) nct6775_write_temp(data, data->reg_temp[j][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) data->temp[j][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699) /* Restore other settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) nct6775_write_value(data, data->REG_VBAT, data->vbat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701) if (data->kind == nct6775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706) abort:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) /* Force re-reading all values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) data->valid = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714) static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716) static struct platform_driver nct6775_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718) .name = DRVNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719) .pm = &nct6775_dev_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721) .probe = nct6775_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724) /* nct6775_find() looks for a '627 in the Super-I/O config space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725) static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729) int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) err = superio_enter(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735) val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) superio_inb(sioaddr, SIO_REG_DEVID + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737) if (force_id && val != 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738) val = force_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740) switch (val & SIO_ID_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) case SIO_NCT6106_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742) sio_data->kind = nct6106;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) case SIO_NCT6116_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) sio_data->kind = nct6116;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747) case SIO_NCT6775_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) sio_data->kind = nct6775;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) case SIO_NCT6776_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) sio_data->kind = nct6776;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753) case SIO_NCT6779_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754) sio_data->kind = nct6779;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) case SIO_NCT6791_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757) sio_data->kind = nct6791;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759) case SIO_NCT6792_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) sio_data->kind = nct6792;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762) case SIO_NCT6793_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763) sio_data->kind = nct6793;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) case SIO_NCT6795_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766) sio_data->kind = nct6795;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768) case SIO_NCT6796_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) sio_data->kind = nct6796;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771) case SIO_NCT6797_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772) sio_data->kind = nct6797;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774) case SIO_NCT6798_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) sio_data->kind = nct6798;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) if (val != 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779) pr_debug("unsupported chip ID: 0x%04x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) superio_exit(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) /* We have a known chip, find the HWM I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785) superio_select(sioaddr, NCT6775_LD_HWM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) | superio_inb(sioaddr, SIO_REG_ADDR + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788) addr = val & IOREGION_ALIGNMENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789) if (addr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) superio_exit(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795) /* Activate logical device if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796) val = superio_inb(sioaddr, SIO_REG_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) if (!(val & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798) pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802) if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804) sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805) sio_data->kind == nct6798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806) nct6791_enable_io_mapping(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) superio_exit(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809) pr_info("Found %s or compatible chip at %#x:%#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810) nct6775_sio_names[sio_data->kind], sioaddr, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811) sio_data->sioreg = sioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817) * when Super-I/O functions move to a separate file, the Super-I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) * bus will manage the lifetime of the device and this module will only keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819) * track of the nct6775 driver. But since we use platform_device_alloc(), we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820) * must keep track of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) static struct platform_device *pdev[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824) static int __init sensors_nct6775_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) int address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) struct nct6775_sio_data sio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) int sioaddr[2] = { 0x2e, 0x4e };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833) err = platform_driver_register(&nct6775_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838) * initialize sio_data->kind and sio_data->sioreg.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) * when Super-I/O functions move to a separate file, the Super-I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841) * driver will probe 0x2e and 0x4e and auto-detect the presence of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842) * nct6775 hardware monitor, and call probe()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) for (i = 0; i < ARRAY_SIZE(pdev); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845) address = nct6775_find(sioaddr[i], &sio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846) if (address <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851) pdev[i] = platform_device_alloc(DRVNAME, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852) if (!pdev[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854) goto exit_device_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857) err = platform_device_add_data(pdev[i], &sio_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858) sizeof(struct nct6775_sio_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863) res.name = DRVNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864) res.start = address + IOREGION_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865) res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866) res.flags = IORESOURCE_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) err = acpi_check_resource_conflict(&res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870) platform_device_put(pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) pdev[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4872) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4875) err = platform_device_add_resources(pdev[i], &res, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4876) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4877) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4879) /* platform_device_add calls probe() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4880) err = platform_device_add(pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4881) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4882) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4884) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4885) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4886) goto exit_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4889) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4891) exit_device_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4892) platform_device_put(pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4893) exit_device_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4894) while (--i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4895) if (pdev[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4896) platform_device_unregister(pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4898) exit_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4899) platform_driver_unregister(&nct6775_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4900) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4903) static void __exit sensors_nct6775_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4905) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4907) for (i = 0; i < ARRAY_SIZE(pdev); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4908) if (pdev[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4909) platform_device_unregister(pdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4911) platform_driver_unregister(&nct6775_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4914) MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4915) MODULE_DESCRIPTION("Driver for NCT6775F and compatible chips");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4916) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4918) module_init(sensors_nct6775_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4919) module_exit(sensors_nct6775_exit);