^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) * pc87360.c - Part of lm_sensors, Linux kernel modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for hardware monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004, 2007 Jean Delvare <jdelvare@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copied from smsc47m1.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Supports the following chips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Chip #vin #fan #pwm #temp devid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * PC87360 - 2 2 - 0xE1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * PC87363 - 2 2 - 0xE8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * PC87364 - 3 3 - 0xE4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * PC87365 11 3 3 2 0xE5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * PC87366 11 3 3 3-4 0xE9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * This driver assumes that no more than one chip is present, and one of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/hwmon-vid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static u8 devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static unsigned short extra_isa[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static u8 confreg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int init = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) module_param(init, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_PARM_DESC(init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) "Chip initialization level:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) " 0: None\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "*1: Forcibly enable internal voltage and temperature channels, except in9\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) " 2: Forcibly enable all voltage and temperature channels, except in9\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) " 3: Forcibly enable all voltage and temperature channels, including in9");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static unsigned short force_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) module_param(force_id, ushort, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MODULE_PARM_DESC(force_id, "Override the detected device ID");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Super-I/O registers and operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define DEV 0x07 /* Register: Logical device select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define DEVID 0x20 /* Register: Device ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define ACT 0x30 /* Register: Device activation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define BASE 0x60 /* Register: Base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define FSCM 0x09 /* Logical device: fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define VLM 0x0d /* Logical device: voltages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define TMS 0x0e /* Logical device: temperatures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define LDNI_MAX 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const u8 logdev[LDNI_MAX] = { FSCM, VLM, TMS };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define LD_FAN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define LD_IN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define LD_TEMP 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static inline void superio_outb(int sioaddr, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) outb(reg, sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) outb(val, sioaddr + 1);
^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 inline int superio_inb(int sioaddr, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) outb(reg, sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return inb(sioaddr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static inline void superio_exit(int sioaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) outb(0x02, sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) outb(0x02, sioaddr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Logical devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define PC87360_EXTENT 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define PC87365_REG_BANK 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define NO_BANK 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * Fan registers and conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* nr has to be 0 or 1 (PC87360/87363) or 2 (PC87364/87365/87366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define PC87360_REG_PRESCALE(nr) (0x00 + 2 * (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PC87360_REG_PWM(nr) (0x01 + 2 * (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define PC87360_REG_FAN_MIN(nr) (0x06 + 3 * (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define PC87360_REG_FAN(nr) (0x07 + 3 * (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 480000 / ((val) * (div)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define FAN_TO_REG(val, div) ((val) <= 100 ? 0 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 480000 / ((val) * (div)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define FAN_DIV_FROM_REG(val) (1 << (((val) >> 5) & 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define FAN_STATUS_FROM_REG(val) ((val) & 0x07)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define FAN_CONFIG_MONITOR(val, nr) (((val) >> (2 + (nr) * 3)) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define FAN_CONFIG_CONTROL(val, nr) (((val) >> (3 + (nr) * 3)) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define FAN_CONFIG_INVERT(val, nr) (((val) >> (4 + (nr) * 3)) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define PWM_FROM_REG(val, inv) ((inv) ? 255 - (val) : (val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline u8 PWM_TO_REG(int val, int inv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (inv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) val = 255 - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Voltage registers and conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define PC87365_REG_IN_CONVRATE 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define PC87365_REG_IN_CONFIG 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define PC87365_REG_IN 0x0B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define PC87365_REG_IN_MIN 0x0D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define PC87365_REG_IN_MAX 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define PC87365_REG_IN_STATUS 0x0A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define PC87365_REG_IN_ALARMS1 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define PC87365_REG_IN_ALARMS2 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define PC87365_REG_VID 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define IN_FROM_REG(val, ref) (((val) * (ref) + 128) / 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define IN_TO_REG(val, ref) ((val) < 0 ? 0 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) (val) * 256 >= (ref) * 255 ? 255 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ((val) * 256 + (ref) / 2) / (ref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Temperature registers and conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define PC87365_REG_TEMP_CONFIG 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define PC87365_REG_TEMP 0x0B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define PC87365_REG_TEMP_MIN 0x0D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define PC87365_REG_TEMP_MAX 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define PC87365_REG_TEMP_CRIT 0x0E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define PC87365_REG_TEMP_STATUS 0x0A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define PC87365_REG_TEMP_ALARMS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define TEMP_FROM_REG(val) ((val) * 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define TEMP_TO_REG(val) ((val) < -55000 ? -55 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) (val) > 127000 ? 127 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (val) < 0 ? ((val) - 500) / 1000 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ((val) + 500) / 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Device data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct pc87360_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct mutex update_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) char valid; /* !=0 if following fields are valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned long last_updated; /* In jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int address[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u8 fannr, innr, tempnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u8 fan[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u8 fan_min[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u8 fan_status[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u8 pwm[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u16 fan_conf; /* Configuration register values, combined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u16 in_vref; /* 1 mV/bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u8 in[14]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u8 in_min[14]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u8 in_max[14]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 in_crit[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u8 in_status[14]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u16 in_alarms; /* Register values, combined, masked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u8 vid_conf; /* Configuration register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u8 vrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u8 vid; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) s8 temp[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) s8 temp_min[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) s8 temp_max[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) s8 temp_crit[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u8 temp_status[3]; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 temp_alarms; /* Register value, masked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Functions declaration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int pc87360_probe(struct platform_device *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int pc87360_remove(struct platform_device *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u8 reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u8 reg, u8 value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static void pc87360_init_device(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int use_thermistors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static struct pc87360_data *pc87360_update_device(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Driver data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct platform_driver pc87360_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .name = "pc87360",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .probe = pc87360_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .remove = pc87360_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * Sysfs stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static ssize_t fan_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) FAN_DIV_FROM_REG(data->fan_status[attr->index])));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static ssize_t fan_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) FAN_DIV_FROM_REG(data->fan_status[attr->index])));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static ssize_t fan_div_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return sprintf(buf, "%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) FAN_DIV_FROM_REG(data->fan_status[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static ssize_t fan_status_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return sprintf(buf, "%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static ssize_t fan_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) long fan_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) err = kstrtol(buf, 10, &fan_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) fan_min = FAN_TO_REG(fan_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) FAN_DIV_FROM_REG(data->fan_status[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* If it wouldn't fit, change clock divisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) while (fan_min > 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) && (data->fan_status[attr->index] & 0x60) != 0x60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) fan_min >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) data->fan[attr->index] >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) data->fan_status[attr->index] += 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) pc87360_write_value(data, LD_FAN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) PC87360_REG_FAN_MIN(attr->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) data->fan_min[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Write new divider, preserve alarm bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) pc87360_write_value(data, LD_FAN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) PC87360_REG_FAN_STATUS(attr->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) data->fan_status[attr->index] & 0xF9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static struct sensor_device_attribute fan_input[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) SENSOR_ATTR_RO(fan1_input, fan_input, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) SENSOR_ATTR_RO(fan2_input, fan_input, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) SENSOR_ATTR_RO(fan3_input, fan_input, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static struct sensor_device_attribute fan_status[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) SENSOR_ATTR_RO(fan1_status, fan_status, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) SENSOR_ATTR_RO(fan2_status, fan_status, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) SENSOR_ATTR_RO(fan3_status, fan_status, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static struct sensor_device_attribute fan_div[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) SENSOR_ATTR_RO(fan1_div, fan_div, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) SENSOR_ATTR_RO(fan2_div, fan_div, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) SENSOR_ATTR_RO(fan3_div, fan_div, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static struct sensor_device_attribute fan_min[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) SENSOR_ATTR_RW(fan1_min, fan_min, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) SENSOR_ATTR_RW(fan2_min, fan_min, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) SENSOR_ATTR_RW(fan3_min, fan_min, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) #define FAN_UNIT_ATTRS(X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { &fan_input[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) &fan_status[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) &fan_div[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) &fan_min[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) NULL \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static ssize_t pwm_show(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return sprintf(buf, "%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) PWM_FROM_REG(data->pwm[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) FAN_CONFIG_INVERT(data->fan_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) attr->index)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static ssize_t pwm_store(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) data->pwm[attr->index] = PWM_TO_REG(val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) FAN_CONFIG_INVERT(data->fan_conf, attr->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) data->pwm[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return count;
^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) static struct sensor_device_attribute pwm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) SENSOR_ATTR_RW(pwm1, pwm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) SENSOR_ATTR_RW(pwm2, pwm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) SENSOR_ATTR_RW(pwm3, pwm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static struct attribute *pc8736x_fan_attr[][5] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) FAN_UNIT_ATTRS(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) FAN_UNIT_ATTRS(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) FAN_UNIT_ATTRS(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static const struct attribute_group pc8736x_fan_attr_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { .attrs = pc8736x_fan_attr[0], },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) { .attrs = pc8736x_fan_attr[1], },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) { .attrs = pc8736x_fan_attr[2], },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static ssize_t in_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static ssize_t in_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static ssize_t in_max_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static ssize_t in_status_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return sprintf(buf, "%u\n", data->in_status[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static ssize_t in_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct device_attribute *devattr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) data->in_min[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static ssize_t in_max_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct device_attribute *devattr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) data->in_max[attr->index] = IN_TO_REG(val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) data->in_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) data->in_max[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static struct sensor_device_attribute in_input[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) SENSOR_ATTR_RO(in0_input, in_input, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) SENSOR_ATTR_RO(in1_input, in_input, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) SENSOR_ATTR_RO(in2_input, in_input, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) SENSOR_ATTR_RO(in3_input, in_input, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) SENSOR_ATTR_RO(in4_input, in_input, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) SENSOR_ATTR_RO(in5_input, in_input, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) SENSOR_ATTR_RO(in6_input, in_input, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) SENSOR_ATTR_RO(in7_input, in_input, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) SENSOR_ATTR_RO(in8_input, in_input, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) SENSOR_ATTR_RO(in9_input, in_input, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) SENSOR_ATTR_RO(in10_input, in_input, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static struct sensor_device_attribute in_status[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) SENSOR_ATTR_RO(in0_status, in_status, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) SENSOR_ATTR_RO(in1_status, in_status, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) SENSOR_ATTR_RO(in2_status, in_status, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) SENSOR_ATTR_RO(in3_status, in_status, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) SENSOR_ATTR_RO(in4_status, in_status, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) SENSOR_ATTR_RO(in5_status, in_status, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) SENSOR_ATTR_RO(in6_status, in_status, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) SENSOR_ATTR_RO(in7_status, in_status, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) SENSOR_ATTR_RO(in8_status, in_status, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) SENSOR_ATTR_RO(in9_status, in_status, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) SENSOR_ATTR_RO(in10_status, in_status, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static struct sensor_device_attribute in_min[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) SENSOR_ATTR_RW(in0_min, in_min, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) SENSOR_ATTR_RW(in1_min, in_min, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) SENSOR_ATTR_RW(in2_min, in_min, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) SENSOR_ATTR_RW(in3_min, in_min, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) SENSOR_ATTR_RW(in4_min, in_min, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) SENSOR_ATTR_RW(in5_min, in_min, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) SENSOR_ATTR_RW(in6_min, in_min, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) SENSOR_ATTR_RW(in7_min, in_min, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) SENSOR_ATTR_RW(in8_min, in_min, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) SENSOR_ATTR_RW(in9_min, in_min, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) SENSOR_ATTR_RW(in10_min, in_min, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static struct sensor_device_attribute in_max[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) SENSOR_ATTR_RW(in0_max, in_max, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) SENSOR_ATTR_RW(in1_max, in_max, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) SENSOR_ATTR_RW(in2_max, in_max, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) SENSOR_ATTR_RW(in3_max, in_max, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) SENSOR_ATTR_RW(in4_max, in_max, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) SENSOR_ATTR_RW(in5_max, in_max, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) SENSOR_ATTR_RW(in6_max, in_max, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) SENSOR_ATTR_RW(in7_max, in_max, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) SENSOR_ATTR_RW(in8_max, in_max, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) SENSOR_ATTR_RW(in9_max, in_max, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) SENSOR_ATTR_RW(in10_max, in_max, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* (temp & vin) channel status register alarm bits (pdf sec.11.5.12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) #define CHAN_ALM_MIN 0x02 /* min limit crossed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) #define CHAN_ALM_MAX 0x04 /* max limit exceeded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #define TEMP_ALM_CRIT 0x08 /* temp crit exceeded (temp only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * show_in_min/max_alarm() reads data from the per-channel status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * register (sec 11.5.12), not the vin event status registers (sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static ssize_t in_min_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static ssize_t in_max_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static struct sensor_device_attribute in_min_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) SENSOR_ATTR_RO(in0_min_alarm, in_min_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) SENSOR_ATTR_RO(in1_min_alarm, in_min_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) SENSOR_ATTR_RO(in2_min_alarm, in_min_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) SENSOR_ATTR_RO(in3_min_alarm, in_min_alarm, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) SENSOR_ATTR_RO(in4_min_alarm, in_min_alarm, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) SENSOR_ATTR_RO(in5_min_alarm, in_min_alarm, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) SENSOR_ATTR_RO(in6_min_alarm, in_min_alarm, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) SENSOR_ATTR_RO(in7_min_alarm, in_min_alarm, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) SENSOR_ATTR_RO(in8_min_alarm, in_min_alarm, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) SENSOR_ATTR_RO(in9_min_alarm, in_min_alarm, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) SENSOR_ATTR_RO(in10_min_alarm, in_min_alarm, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static struct sensor_device_attribute in_max_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) SENSOR_ATTR_RO(in0_max_alarm, in_max_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) SENSOR_ATTR_RO(in1_max_alarm, in_max_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) SENSOR_ATTR_RO(in2_max_alarm, in_max_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) SENSOR_ATTR_RO(in3_max_alarm, in_max_alarm, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) SENSOR_ATTR_RO(in4_max_alarm, in_max_alarm, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) SENSOR_ATTR_RO(in5_max_alarm, in_max_alarm, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) SENSOR_ATTR_RO(in6_max_alarm, in_max_alarm, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) SENSOR_ATTR_RO(in7_max_alarm, in_max_alarm, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) SENSOR_ATTR_RO(in8_max_alarm, in_max_alarm, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) SENSOR_ATTR_RO(in9_max_alarm, in_max_alarm, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) SENSOR_ATTR_RO(in10_max_alarm, in_max_alarm, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) #define VIN_UNIT_ATTRS(X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) &in_input[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) &in_status[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) &in_min[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) &in_max[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) &in_min_alarm[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) &in_max_alarm[X].dev_attr.attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static ssize_t cpu0_vid_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static DEVICE_ATTR_RO(cpu0_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return sprintf(buf, "%u\n", data->vrm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) err = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) data->vrm = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static DEVICE_ATTR_RW(vrm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static ssize_t alarms_in_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return sprintf(buf, "%u\n", data->in_alarms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static DEVICE_ATTR_RO(alarms_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static struct attribute *pc8736x_vin_attr_array[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) VIN_UNIT_ATTRS(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) VIN_UNIT_ATTRS(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) VIN_UNIT_ATTRS(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) VIN_UNIT_ATTRS(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) VIN_UNIT_ATTRS(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) VIN_UNIT_ATTRS(5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) VIN_UNIT_ATTRS(6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) VIN_UNIT_ATTRS(7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) VIN_UNIT_ATTRS(8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) VIN_UNIT_ATTRS(9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) VIN_UNIT_ATTRS(10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) &dev_attr_cpu0_vid.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) &dev_attr_vrm.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) &dev_attr_alarms_in.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static const struct attribute_group pc8736x_vin_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .attrs = pc8736x_vin_attr_array,
^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) static ssize_t therm_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static ssize_t therm_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static ssize_t therm_max_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static ssize_t therm_crit_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) data->in_vref));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) static ssize_t therm_status_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return sprintf(buf, "%u\n", data->in_status[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static ssize_t therm_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) data->in_min[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static ssize_t therm_max_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) data->in_max[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static ssize_t therm_crit_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) data->in_crit[attr->index-11]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * the +11 term below reflects the fact that VLM units 11,12,13 are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * used in the chip to measure voltage across the thermistors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static struct sensor_device_attribute therm_input[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) SENSOR_ATTR_RO(temp4_input, therm_input, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) SENSOR_ATTR_RO(temp5_input, therm_input, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) SENSOR_ATTR_RO(temp6_input, therm_input, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static struct sensor_device_attribute therm_status[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) SENSOR_ATTR_RO(temp4_status, therm_status, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) SENSOR_ATTR_RO(temp5_status, therm_status, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) SENSOR_ATTR_RO(temp6_status, therm_status, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static struct sensor_device_attribute therm_min[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) SENSOR_ATTR_RW(temp4_min, therm_min, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) SENSOR_ATTR_RW(temp5_min, therm_min, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) SENSOR_ATTR_RW(temp6_min, therm_min, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static struct sensor_device_attribute therm_max[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) SENSOR_ATTR_RW(temp4_max, therm_max, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) SENSOR_ATTR_RW(temp5_max, therm_max, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) SENSOR_ATTR_RW(temp6_max, therm_max, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static struct sensor_device_attribute therm_crit[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) SENSOR_ATTR_RW(temp4_crit, therm_crit, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) SENSOR_ATTR_RW(temp5_crit, therm_crit, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) SENSOR_ATTR_RW(temp6_crit, therm_crit, 2 + 11),
^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) * show_therm_min/max_alarm() reads data from the per-channel voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * status register (sec 11.5.12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static ssize_t therm_min_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static ssize_t therm_max_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static ssize_t therm_crit_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return sprintf(buf, "%u\n", !!(data->in_status[nr] & TEMP_ALM_CRIT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static struct sensor_device_attribute therm_min_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) SENSOR_ATTR_RO(temp4_min_alarm, therm_min_alarm, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) SENSOR_ATTR_RO(temp5_min_alarm, therm_min_alarm, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) SENSOR_ATTR_RO(temp6_min_alarm, therm_min_alarm, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static struct sensor_device_attribute therm_max_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) SENSOR_ATTR_RO(temp4_max_alarm, therm_max_alarm, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) SENSOR_ATTR_RO(temp5_max_alarm, therm_max_alarm, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) SENSOR_ATTR_RO(temp6_max_alarm, therm_max_alarm, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static struct sensor_device_attribute therm_crit_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) SENSOR_ATTR_RO(temp4_crit_alarm, therm_crit_alarm, 0 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) SENSOR_ATTR_RO(temp5_crit_alarm, therm_crit_alarm, 1 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) SENSOR_ATTR_RO(temp6_crit_alarm, therm_crit_alarm, 2 + 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) #define THERM_UNIT_ATTRS(X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) &therm_input[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) &therm_status[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) &therm_min[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) &therm_max[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) &therm_crit[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) &therm_min_alarm[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) &therm_max_alarm[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) &therm_crit_alarm[X].dev_attr.attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static struct attribute *pc8736x_therm_attr_array[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) THERM_UNIT_ATTRS(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) THERM_UNIT_ATTRS(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) THERM_UNIT_ATTRS(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) static const struct attribute_group pc8736x_therm_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .attrs = pc8736x_therm_attr_array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static ssize_t temp_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static ssize_t temp_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static ssize_t temp_max_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static ssize_t temp_crit_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return sprintf(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) TEMP_FROM_REG(data->temp_crit[attr->index]));
^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 ssize_t temp_status_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return sprintf(buf, "%d\n", data->temp_status[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static ssize_t temp_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) data->temp_min[attr->index] = TEMP_TO_REG(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) data->temp_min[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static ssize_t temp_max_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) data->temp_max[attr->index] = TEMP_TO_REG(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) data->temp_max[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static ssize_t temp_crit_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) err = kstrtol(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) data->temp_crit[attr->index] = TEMP_TO_REG(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) data->temp_crit[attr->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static struct sensor_device_attribute temp_input[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) SENSOR_ATTR_RO(temp1_input, temp_input, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) SENSOR_ATTR_RO(temp2_input, temp_input, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) SENSOR_ATTR_RO(temp3_input, temp_input, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static struct sensor_device_attribute temp_status[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) SENSOR_ATTR_RO(temp1_status, temp_status, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) SENSOR_ATTR_RO(temp2_status, temp_status, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) SENSOR_ATTR_RO(temp3_status, temp_status, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static struct sensor_device_attribute temp_min[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) SENSOR_ATTR_RW(temp1_min, temp_min, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) SENSOR_ATTR_RW(temp2_min, temp_min, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) SENSOR_ATTR_RW(temp3_min, temp_min, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static struct sensor_device_attribute temp_max[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) SENSOR_ATTR_RW(temp1_max, temp_max, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) SENSOR_ATTR_RW(temp2_max, temp_max, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) SENSOR_ATTR_RW(temp3_max, temp_max, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static struct sensor_device_attribute temp_crit[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) SENSOR_ATTR_RW(temp1_crit, temp_crit, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) SENSOR_ATTR_RW(temp2_crit, temp_crit, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) SENSOR_ATTR_RW(temp3_crit, temp_crit, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static ssize_t alarms_temp_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return sprintf(buf, "%u\n", data->temp_alarms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) static DEVICE_ATTR_RO(alarms_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * show_temp_min/max_alarm() reads data from the per-channel status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * register (sec 12.3.7), not the temp event status registers (sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * 12.3.2) that show_temp_alarm() reads (via data->temp_alarms)
^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 ssize_t temp_min_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static ssize_t temp_max_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static ssize_t temp_crit_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_ALM_CRIT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static struct sensor_device_attribute temp_min_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) SENSOR_ATTR_RO(temp1_min_alarm, temp_min_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) SENSOR_ATTR_RO(temp2_min_alarm, temp_min_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) SENSOR_ATTR_RO(temp3_min_alarm, temp_min_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static struct sensor_device_attribute temp_max_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) SENSOR_ATTR_RO(temp1_max_alarm, temp_max_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) SENSOR_ATTR_RO(temp2_max_alarm, temp_max_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) SENSOR_ATTR_RO(temp3_max_alarm, temp_max_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) static struct sensor_device_attribute temp_crit_alarm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) SENSOR_ATTR_RO(temp1_crit_alarm, temp_crit_alarm, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) SENSOR_ATTR_RO(temp2_crit_alarm, temp_crit_alarm, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) SENSOR_ATTR_RO(temp3_crit_alarm, temp_crit_alarm, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) #define TEMP_FAULT 0x40 /* open diode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static ssize_t temp_fault_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct pc87360_data *data = pc87360_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) unsigned nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_FAULT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static struct sensor_device_attribute temp_fault[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) SENSOR_ATTR_RO(temp1_fault, temp_fault, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) SENSOR_ATTR_RO(temp2_fault, temp_fault, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) SENSOR_ATTR_RO(temp3_fault, temp_fault, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) #define TEMP_UNIT_ATTRS(X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) { &temp_input[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) &temp_status[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) &temp_min[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) &temp_max[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) &temp_crit[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) &temp_min_alarm[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) &temp_max_alarm[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) &temp_crit_alarm[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) &temp_fault[X].dev_attr.attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) NULL \
^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) static struct attribute *pc8736x_temp_attr[][10] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) TEMP_UNIT_ATTRS(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) TEMP_UNIT_ATTRS(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) TEMP_UNIT_ATTRS(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static const struct attribute_group pc8736x_temp_attr_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) { .attrs = pc8736x_temp_attr[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) { .attrs = pc8736x_temp_attr[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) { .attrs = pc8736x_temp_attr[2] }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static ssize_t name_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return sprintf(buf, "%s\n", data->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static DEVICE_ATTR_RO(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) * Device detection, registration and update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static int __init pc87360_find(int sioaddr, u8 *devid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) unsigned short *addresses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) int nrdev; /* logical device count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* No superio_enter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) /* Identify device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) val = force_id ? force_id : superio_inb(sioaddr, DEVID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) case 0xE1: /* PC87360 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) case 0xE8: /* PC87363 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) case 0xE4: /* PC87364 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) nrdev = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) case 0xE5: /* PC87365 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) case 0xE9: /* PC87366 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) nrdev = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) superio_exit(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* Remember the device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) *devid = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) for (i = 0; i < nrdev; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* select logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) superio_outb(sioaddr, DEV, logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) val = superio_inb(sioaddr, ACT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (!(val & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) pr_info("Device 0x%02x not activated\n", logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) val = (superio_inb(sioaddr, BASE) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) | superio_inb(sioaddr, BASE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) pr_info("Base address not set for device 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) addresses[i] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (i == 0) { /* Fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) confreg[0] = superio_inb(sioaddr, 0xF0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) confreg[1] = superio_inb(sioaddr, 0xF1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) (confreg[0] >> 2) & 1, (confreg[0] >> 3) & 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) (confreg[0] >> 4) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) (confreg[0] >> 5) & 1, (confreg[0] >> 6) & 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) (confreg[0] >> 7) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) confreg[1] & 1, (confreg[1] >> 1) & 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) (confreg[1] >> 2) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) } else if (i == 1) { /* Voltages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* Are we using thermistors? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (*devid == 0xE9) { /* PC87366 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * These registers are not logical-device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * specific, just that we won't need them if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * we don't use the VLM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) confreg[2] = superio_inb(sioaddr, 0x2B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) confreg[3] = superio_inb(sioaddr, 0x25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (confreg[2] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) pr_info("Using thermistors for temperature monitoring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (confreg[3] & 0xE0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) pr_info("VID inputs routed (mode %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) confreg[3] >> 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) superio_exit(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static void pc87360_remove_files(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) device_remove_file(dev, &dev_attr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) device_remove_file(dev, &dev_attr_alarms_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) for (i = 0; i < ARRAY_SIZE(pc8736x_temp_attr_group); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) sysfs_remove_group(&dev->kobj, &pc8736x_temp_attr_group[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) for (i = 0; i < ARRAY_SIZE(pc8736x_fan_attr_group); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_attr_group[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) device_remove_file(dev, &pwm[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) sysfs_remove_group(&dev->kobj, &pc8736x_therm_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) static int pc87360_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct pc87360_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) int use_thermistors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) data = devm_kzalloc(dev, sizeof(struct pc87360_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) switch (devid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) name = "pc87360";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) data->fannr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case 0xe8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) name = "pc87363";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) data->fannr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) case 0xe4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) name = "pc87364";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) data->fannr = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) case 0xe5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) name = "pc87365";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) data->fannr = extra_isa[0] ? 3 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) data->innr = extra_isa[1] ? 11 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) data->tempnr = extra_isa[2] ? 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) case 0xe9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) name = "pc87366";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) data->fannr = extra_isa[0] ? 3 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) data->innr = extra_isa[1] ? 14 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) data->tempnr = extra_isa[2] ? 3 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) data->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) mutex_init(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) for (i = 0; i < LDNI_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) data->address[i] = extra_isa[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (data->address[i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) && !devm_request_region(dev, extra_isa[i], PC87360_EXTENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) pc87360_driver.driver.name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) "Region 0x%x-0x%x already in use!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) extra_isa[i], extra_isa[i]+PC87360_EXTENT-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) /* Retrieve the fans configuration from Super-I/O space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (data->fannr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) data->fan_conf = confreg[0] | (confreg[1] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * Use the correct reference voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * Unless both the VLM and the TMS logical devices agree to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * use an external Vref, the internal one is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (data->innr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) i = pc87360_read_value(data, LD_IN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) PC87365_REG_IN_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (data->tempnr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) i &= pc87360_read_value(data, LD_TEMP, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) PC87365_REG_TEMP_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) data->in_vref = (i&0x02) ? 3025 : 2966;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) dev_dbg(dev, "Using %s reference voltage\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) (i&0x02) ? "external" : "internal");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) data->vid_conf = confreg[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) data->vrm = vid_which_vrm();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* Fan clock dividers may be needed before any data is read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) for (i = 0; i < data->fannr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (FAN_CONFIG_MONITOR(data->fan_conf, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) data->fan_status[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) LD_FAN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) PC87360_REG_FAN_STATUS(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (init > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (devid == 0xe9 && data->address[1]) /* PC87366 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) use_thermistors = confreg[2] & 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) pc87360_init_device(pdev, use_thermistors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) /* Register all-or-nothing sysfs groups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (data->innr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) err = sysfs_create_group(&dev->kobj, &pc8736x_vin_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (data->innr == 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) err = sysfs_create_group(&dev->kobj, &pc8736x_therm_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) /* create device attr-files for varying sysfs groups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (data->tempnr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) for (i = 0; i < data->tempnr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) err = sysfs_create_group(&dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) &pc8736x_temp_attr_group[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) err = device_create_file(dev, &dev_attr_alarms_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) for (i = 0; i < data->fannr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) err = sysfs_create_group(&dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) &pc8736x_fan_attr_group[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (FAN_CONFIG_CONTROL(data->fan_conf, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) err = device_create_file(dev, &pwm[i].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) err = device_create_file(dev, &dev_attr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) data->hwmon_dev = hwmon_device_register(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (IS_ERR(data->hwmon_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) err = PTR_ERR(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) pc87360_remove_files(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) static int pc87360_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) struct pc87360_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) hwmon_device_unregister(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) pc87360_remove_files(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * ldi is the logical device index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * bank is for voltages and temperatures only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) mutex_lock(&(data->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (bank != NO_BANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) res = inb_p(data->address[ldi] + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) mutex_unlock(&(data->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) mutex_lock(&(data->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (bank != NO_BANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) outb_p(value, data->address[ldi] + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) mutex_unlock(&(data->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) /* (temp & vin) channel conversion status register flags (pdf sec.11.5.12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) #define CHAN_CNVRTD 0x80 /* new data ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) #define CHAN_ENA 0x01 /* enabled channel (temp or vin) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) #define CHAN_ALM_ENA 0x10 /* propagate to alarms-reg ?? (chk val!) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) #define CHAN_READY (CHAN_ENA|CHAN_CNVRTD) /* sample ready mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) #define TEMP_OTS_OE 0x20 /* OTS Output Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) #define VIN_RW1C_MASK (CHAN_READY|CHAN_ALM_MAX|CHAN_ALM_MIN) /* 0x87 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) #define TEMP_RW1C_MASK (VIN_RW1C_MASK|TEMP_ALM_CRIT|TEMP_FAULT) /* 0xCF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) static void pc87360_init_device(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) int use_thermistors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) struct pc87360_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) int i, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) const u8 init_temp[3] = { 2, 2, 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) if (init >= 2 && data->innr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) reg = pc87360_read_value(data, LD_IN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) PC87365_REG_IN_CONVRATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) dev_info(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) "VLM conversion set to 1s period, 160us delay\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) pc87360_write_value(data, LD_IN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) PC87365_REG_IN_CONVRATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) (reg & 0xC0) | 0x11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) nr = data->innr < 11 ? data->innr : 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) for (i = 0; i < nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) reg = pc87360_read_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) PC87365_REG_IN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) dev_dbg(&pdev->dev, "bios in%d status:0x%02x\n", i, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) if (init >= init_in[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) /* Forcibly enable voltage channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if (!(reg & CHAN_ENA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) dev_dbg(&pdev->dev, "Forcibly enabling in%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) pc87360_write_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) PC87365_REG_IN_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) (reg & 0x68) | 0x87);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * We can't blindly trust the Super-I/O space configuration bit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) * most BIOS won't set it properly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) dev_dbg(&pdev->dev, "bios thermistors:%d\n", use_thermistors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) for (i = 11; i < data->innr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) reg = pc87360_read_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) PC87365_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) use_thermistors = use_thermistors || (reg & CHAN_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) /* thermistors are temp[4-6], measured on vin[11-14] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i-7, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) dev_dbg(&pdev->dev, "using thermistors:%d\n", use_thermistors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) i = use_thermistors ? 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) for (; i < data->tempnr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) reg = pc87360_read_value(data, LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) PC87365_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i + 1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (init >= init_temp[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) /* Forcibly enable temperature channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) if (!(reg & CHAN_ENA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) "Forcibly enabling temp%d\n", i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) pc87360_write_value(data, LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) PC87365_REG_TEMP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 0xCF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (use_thermistors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) for (i = 11; i < data->innr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (init >= init_in[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) * The pin may already be used by thermal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) * diodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) reg = pc87360_read_value(data, LD_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) (i - 11) / 2, PC87365_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (reg & CHAN_ENA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) "Skipping temp%d, pin already in use by temp%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) i - 7, (i - 11) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) /* Forcibly enable thermistor channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) reg = pc87360_read_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) PC87365_REG_IN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (!(reg & CHAN_ENA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) "Forcibly enabling temp%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) i - 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) pc87360_write_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) PC87365_REG_TEMP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) (reg & 0x60) | 0x8F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (data->innr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) reg = pc87360_read_value(data, LD_IN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) PC87365_REG_IN_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (reg & CHAN_ENA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) "Forcibly enabling monitoring (VLM)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) pc87360_write_value(data, LD_IN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) PC87365_REG_IN_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) reg & 0xFE);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) if (data->tempnr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) PC87365_REG_TEMP_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (reg & CHAN_ENA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) "Forcibly enabling monitoring (TMS)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) pc87360_write_value(data, LD_TEMP, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) PC87365_REG_TEMP_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) reg & 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (init >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) /* Chip config as documented by National Semi. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) * We voluntarily omit the bank here, in case the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) * sequence itself matters. It shouldn't be a problem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * since nobody else is supposed to access the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * device at that point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) pc87360_write_value(data, LD_TEMP, NO_BANK, 0xE, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) static void pc87360_autodiv(struct device *dev, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) u8 old_min = data->fan_min[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) /* Increase clock divider if needed and possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if ((data->fan_status[nr] & 0x04) /* overflow flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) || (data->fan[nr] >= 224)) { /* next to overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if ((data->fan_status[nr] & 0x60) != 0x60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) data->fan_status[nr] += 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) data->fan_min[nr] >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) data->fan[nr] >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) dev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) "Increasing clock divider to %d for fan %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) FAN_DIV_FROM_REG(data->fan_status[nr]), nr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) /* Decrease clock divider if possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) while (!(data->fan_min[nr] & 0x80) /* min "nails" divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) && data->fan[nr] < 85 /* bad accuracy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) && (data->fan_status[nr] & 0x60) != 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) data->fan_status[nr] -= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) data->fan_min[nr] <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) data->fan[nr] <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) dev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) "Decreasing clock divider to %d for fan %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) FAN_DIV_FROM_REG(data->fan_status[nr]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) nr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) /* Write new fan min if it changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (old_min != data->fan_min[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) pc87360_write_value(data, LD_FAN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) PC87360_REG_FAN_MIN(nr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) data->fan_min[nr]);
^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) static struct pc87360_data *pc87360_update_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) struct pc87360_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) mutex_lock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) dev_dbg(dev, "Data update\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) /* Fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) for (i = 0; i < data->fannr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) data->fan_status[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) pc87360_read_value(data, LD_FAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) NO_BANK, PC87360_REG_FAN_STATUS(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) data->fan[i] = pc87360_read_value(data, LD_FAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) NO_BANK, PC87360_REG_FAN(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) data->fan_min[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) LD_FAN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) PC87360_REG_FAN_MIN(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) /* Change clock divider if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) pc87360_autodiv(dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) /* Clear bits and write new divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) pc87360_write_value(data, LD_FAN, NO_BANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) PC87360_REG_FAN_STATUS(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) data->fan_status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (FAN_CONFIG_CONTROL(data->fan_conf, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) data->pwm[i] = pc87360_read_value(data, LD_FAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) NO_BANK, PC87360_REG_PWM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) /* Voltages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) for (i = 0; i < data->innr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) data->in_status[i] = pc87360_read_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) PC87365_REG_IN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) /* Clear bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) pc87360_write_value(data, LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) PC87365_REG_IN_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) data->in_status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if ((data->in_status[i] & CHAN_READY) == CHAN_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) data->in[i] = pc87360_read_value(data, LD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) i, PC87365_REG_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (data->in_status[i] & CHAN_ENA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) data->in_min[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) PC87365_REG_IN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) data->in_max[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) LD_IN, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) PC87365_REG_IN_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (i >= 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) data->in_crit[i-11] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) pc87360_read_value(data, LD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) i, PC87365_REG_TEMP_CRIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) if (data->innr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) data->in_alarms = pc87360_read_value(data, LD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) NO_BANK, PC87365_REG_IN_ALARMS1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) | ((pc87360_read_value(data, LD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) NO_BANK, PC87365_REG_IN_ALARMS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) & 0x07) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) data->vid = (data->vid_conf & 0xE0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) pc87360_read_value(data, LD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) NO_BANK, PC87365_REG_VID) : 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) /* Temperatures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) for (i = 0; i < data->tempnr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) data->temp_status[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) PC87365_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) /* Clear bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) pc87360_write_value(data, LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) PC87365_REG_TEMP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) data->temp_status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) if ((data->temp_status[i] & CHAN_READY) == CHAN_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) data->temp[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) PC87365_REG_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) if (data->temp_status[i] & CHAN_ENA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) data->temp_min[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) PC87365_REG_TEMP_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) data->temp_max[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) PC87365_REG_TEMP_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) data->temp_crit[i] = pc87360_read_value(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) LD_TEMP, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) PC87365_REG_TEMP_CRIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) if (data->tempnr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) data->temp_alarms = pc87360_read_value(data, LD_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) NO_BANK, PC87365_REG_TEMP_ALARMS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) & 0x3F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) data->last_updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) data->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) mutex_unlock(&data->update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) static int __init pc87360_device_add(unsigned short address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct resource res[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) int err, i, res_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) pdev = platform_device_alloc("pc87360", address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) if (!pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) pr_err("Device allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) memset(res, 0, 3 * sizeof(struct resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) res_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (!extra_isa[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) res[res_count].start = extra_isa[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) res[res_count].name = "pc87360",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) res[res_count].flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) err = acpi_check_resource_conflict(&res[res_count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) res_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) err = platform_device_add_resources(pdev, res, res_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) pr_err("Device resources addition failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) err = platform_device_add(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) pr_err("Device addition failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) exit_device_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) platform_device_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) static int __init pc87360_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) unsigned short address = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (pc87360_find(0x2e, &devid, extra_isa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) && pc87360_find(0x4e, &devid, extra_isa)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) pr_warn("PC8736x not detected, module not inserted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) /* Arbitrarily pick one of the addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) if (extra_isa[i] != 0x0000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) address = extra_isa[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (address == 0x0000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) pr_warn("No active logical device, module not inserted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) err = platform_driver_register(&pc87360_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) /* Sets global pdev as a side effect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) err = pc87360_device_add(address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) goto exit_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) exit_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) platform_driver_unregister(&pc87360_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) static void __exit pc87360_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) platform_driver_unregister(&pc87360_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) MODULE_DESCRIPTION("PC8736x hardware monitor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) module_init(pc87360_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) module_exit(pc87360_exit);