^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * pc87427.c - hardware monitoring driver for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * National Semiconductor PC87427 Super-I/O chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006, 2008, 2010 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) * Supports the following chips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Chip #vin #fan #pwm #temp devid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * PC87427 - 8 4 6 0xF2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This driver assumes that no more than one chip is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Only fans are fully supported so far. Temperatures are in read-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * mode, and voltages aren't supported at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static unsigned short force_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) module_param(force_id, ushort, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_PARM_DESC(force_id, "Override the detected device ID");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DRVNAME "pc87427"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * The lock mutex protects both the I/O accesses (needed because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * device is using banked registers) and the register cache (needed to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * the data in the registers and the cache in sync at any time).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct pc87427_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int address[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned long last_updated; /* in jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u8 fan_enabled; /* bit vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u16 fan[8]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u16 fan_min[8]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u8 fan_status[8]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 pwm_enabled; /* bit vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 pwm_auto_ok; /* bit vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 pwm_enable[4]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u8 pwm[4]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 temp_enabled; /* bit vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) s16 temp[6]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) s8 temp_min[6]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) s8 temp_max[6]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) s8 temp_crit[6]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u8 temp_status[6]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u8 temp_type[6]; /* register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct pc87427_sio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned short address[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u8 has_fanin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 has_fanout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Super-I/O registers and operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SIOREG_LDSEL 0x07 /* Logical device select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SIOREG_DEVID 0x20 /* Device ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SIOREG_CF2 0x22 /* Configuration 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define SIOREG_CF3 0x23 /* Configuration 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define SIOREG_CF4 0x24 /* Configuration 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SIOREG_CF5 0x25 /* Configuration 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SIOREG_CFB 0x2B /* Configuration B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SIOREG_CFC 0x2C /* Configuration C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SIOREG_CFD 0x2D /* Configuration D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define SIOREG_ACT 0x30 /* Device activation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define SIOREG_MAP 0x50 /* I/O or memory mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define SIOREG_IOBASE 0x60 /* I/O base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static const u8 logdev[2] = { 0x09, 0x14 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define LD_FAN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define LD_IN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define LD_TEMP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static inline int superio_enter(int sioaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!request_muxed_region(sioaddr, 2, DRVNAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static inline void superio_outb(int sioaddr, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) outb(reg, sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) outb(val, sioaddr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static inline int superio_inb(int sioaddr, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) outb(reg, sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return inb(sioaddr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline void superio_exit(int sioaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) outb(0x02, sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) outb(0x02, sioaddr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) release_region(sioaddr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Logical devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define REGION_LENGTH 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define PC87427_REG_BANK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define BANK_FM(nr) (nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define BANK_FT(nr) (0x08 + (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define BANK_FC(nr) (0x10 + (nr) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define BANK_TM(nr) (nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define BANK_VM(nr) (0x08 + (nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * I/O access functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* ldi is the logical device index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return inb(data->address[ldi] + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Must be called with data->lock held, except during init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u8 bank, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) outb(bank, data->address[ldi] + PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return inb(data->address[ldi] + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Must be called with data->lock held, except during init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u8 bank, u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) outb(bank, data->address[ldi] + PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) outb(value, data->address[ldi] + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Fan registers and conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* fan data registers are 16-bit wide */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define PC87427_REG_FAN 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define PC87427_REG_FAN_MIN 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define PC87427_REG_FAN_STATUS 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define FAN_STATUS_STALL (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define FAN_STATUS_LOSPD (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define FAN_STATUS_MONEN (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Dedicated function to read all registers related to a given fan input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * This saves us quite a few locks and bank selections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Must be called with data->lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * nr is from 0 to 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int iobase = data->address[LD_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) data->fan[nr] = inw(iobase + PC87427_REG_FAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* Clear fan alarm bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * The 2 LSB of fan speed registers are used for something different.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * The actual 2 LSB of the measurements are not available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static inline unsigned long fan_from_reg(u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) reg &= 0xfffc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (reg == 0x0000 || reg == 0xfffc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 5400000UL / reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* The 2 LSB of the fan speed limit registers are not significant. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static inline u16 fan_to_reg(unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (val < 83UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (val >= 1350000UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return 0x0004;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return ((1350000UL + val / 2) / val) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * PWM registers and conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define PC87427_REG_PWM_ENABLE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define PC87427_REG_PWM_DUTY 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define PWM_ENABLE_MODE_MASK (7 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define PWM_ENABLE_CTLEN (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define PWM_MODE_MANUAL (0 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define PWM_MODE_AUTO (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #define PWM_MODE_OFF (2 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #define PWM_MODE_ON (7 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * Dedicated function to read all registers related to a given PWM output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * This saves us quite a few locks and bank selections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Must be called with data->lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * nr is from 0 to 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int iobase = data->address[LD_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) outb(BANK_FC(nr), iobase + PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) data->pwm_enable[nr] = inb(iobase + PC87427_REG_PWM_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) data->pwm[nr] = inb(iobase + PC87427_REG_PWM_DUTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static inline int pwm_enable_from_reg(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) switch (reg & PWM_ENABLE_MODE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case PWM_MODE_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case PWM_MODE_MANUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case PWM_MODE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case PWM_MODE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return PWM_MODE_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return pwmval ? PWM_MODE_MANUAL : PWM_MODE_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return PWM_MODE_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * Temperature registers and conversions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #define PC87427_REG_TEMP_STATUS 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #define PC87427_REG_TEMP 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #define PC87427_REG_TEMP_MAX 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define PC87427_REG_TEMP_MIN 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #define PC87427_REG_TEMP_CRIT 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #define PC87427_REG_TEMP_TYPE 0x1d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define TEMP_STATUS_CHANEN (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #define TEMP_STATUS_LOWFLG (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define TEMP_STATUS_HIGHFLG (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #define TEMP_STATUS_CRITFLG (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #define TEMP_STATUS_SENSERR (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #define TEMP_TYPE_MASK (3 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define TEMP_TYPE_THERMISTOR (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define TEMP_TYPE_REMOTE_DIODE (2 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #define TEMP_TYPE_LOCAL_DIODE (3 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Dedicated function to read all registers related to a given temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * input. This saves us quite a few locks and bank selections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Must be called with data->lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * nr is from 0 to 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void pc87427_readall_temp(struct pc87427_data *data, u8 nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int iobase = data->address[LD_TEMP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) outb(BANK_TM(nr), iobase + PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) data->temp[nr] = le16_to_cpu(inw(iobase + PC87427_REG_TEMP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) data->temp_max[nr] = inb(iobase + PC87427_REG_TEMP_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) data->temp_min[nr] = inb(iobase + PC87427_REG_TEMP_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) data->temp_crit[nr] = inb(iobase + PC87427_REG_TEMP_CRIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) data->temp_type[nr] = inb(iobase + PC87427_REG_TEMP_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) data->temp_status[nr] = inb(iobase + PC87427_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Clear fan alarm bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) outb(data->temp_status[nr], iobase + PC87427_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static inline unsigned int temp_type_from_reg(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) switch (reg & TEMP_TYPE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case TEMP_TYPE_THERMISTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case TEMP_TYPE_REMOTE_DIODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case TEMP_TYPE_LOCAL_DIODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * We assume 8-bit thermal sensors; 9-bit thermal sensors are possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * too, but I have no idea how to figure out when they are used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static inline long temp_from_reg(s16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return reg * 1000 / 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static inline long temp_from_reg8(s8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return reg * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * Data interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static struct pc87427_data *pc87427_update_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!time_after(jiffies, data->last_updated + HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) && data->last_updated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* Fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (!(data->fan_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pc87427_readall_fan(data, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* PWM outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!(data->pwm_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) pc87427_readall_pwm(data, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* Temperature channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!(data->temp_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pc87427_readall_temp(data, i);
^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) data->last_updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static ssize_t fan_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static ssize_t fan_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static ssize_t fan_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return sprintf(buf, "%d\n", !!(data->fan_status[nr]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) & FAN_STATUS_LOSPD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static ssize_t fan_fault_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return sprintf(buf, "%d\n", !!(data->fan_status[nr]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) & FAN_STATUS_STALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static ssize_t fan_min_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int iobase = data->address[LD_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (kstrtoul(buf, 10, &val) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * The low speed limit registers are read-only while monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * is enabled, so we have to disable monitoring, then change the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * limit, and finally enable monitoring again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) outb(0, iobase + PC87427_REG_FAN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) data->fan_min[nr] = fan_to_reg(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static SENSOR_DEVICE_ATTR_RO(fan4_input, fan_input, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static SENSOR_DEVICE_ATTR_RO(fan5_input, fan_input, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static SENSOR_DEVICE_ATTR_RO(fan6_input, fan_input, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static SENSOR_DEVICE_ATTR_RO(fan7_input, fan_input, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static SENSOR_DEVICE_ATTR_RO(fan8_input, fan_input, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static SENSOR_DEVICE_ATTR_RW(fan5_min, fan_min, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static SENSOR_DEVICE_ATTR_RW(fan6_min, fan_min, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static SENSOR_DEVICE_ATTR_RW(fan7_min, fan_min, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static SENSOR_DEVICE_ATTR_RW(fan8_min, fan_min, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static SENSOR_DEVICE_ATTR_RO(fan1_alarm, fan_alarm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static SENSOR_DEVICE_ATTR_RO(fan2_alarm, fan_alarm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static SENSOR_DEVICE_ATTR_RO(fan3_alarm, fan_alarm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static SENSOR_DEVICE_ATTR_RO(fan4_alarm, fan_alarm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static SENSOR_DEVICE_ATTR_RO(fan5_alarm, fan_alarm, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static SENSOR_DEVICE_ATTR_RO(fan6_alarm, fan_alarm, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static SENSOR_DEVICE_ATTR_RO(fan7_alarm, fan_alarm, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static SENSOR_DEVICE_ATTR_RO(fan8_alarm, fan_alarm, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static SENSOR_DEVICE_ATTR_RO(fan1_fault, fan_fault, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static SENSOR_DEVICE_ATTR_RO(fan2_fault, fan_fault, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static SENSOR_DEVICE_ATTR_RO(fan3_fault, fan_fault, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static SENSOR_DEVICE_ATTR_RO(fan4_fault, fan_fault, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static SENSOR_DEVICE_ATTR_RO(fan5_fault, fan_fault, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static SENSOR_DEVICE_ATTR_RO(fan6_fault, fan_fault, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static SENSOR_DEVICE_ATTR_RO(fan7_fault, fan_fault, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static SENSOR_DEVICE_ATTR_RO(fan8_fault, fan_fault, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static struct attribute *pc87427_attributes_fan[8][5] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) &sensor_dev_attr_fan1_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) &sensor_dev_attr_fan1_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) &sensor_dev_attr_fan1_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) &sensor_dev_attr_fan1_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) &sensor_dev_attr_fan2_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) &sensor_dev_attr_fan2_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) &sensor_dev_attr_fan2_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) &sensor_dev_attr_fan2_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) &sensor_dev_attr_fan3_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) &sensor_dev_attr_fan3_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) &sensor_dev_attr_fan3_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) &sensor_dev_attr_fan3_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) &sensor_dev_attr_fan4_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) &sensor_dev_attr_fan4_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) &sensor_dev_attr_fan4_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) &sensor_dev_attr_fan4_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) &sensor_dev_attr_fan5_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) &sensor_dev_attr_fan5_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) &sensor_dev_attr_fan5_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) &sensor_dev_attr_fan5_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) &sensor_dev_attr_fan6_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) &sensor_dev_attr_fan6_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) &sensor_dev_attr_fan6_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) &sensor_dev_attr_fan6_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) &sensor_dev_attr_fan7_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) &sensor_dev_attr_fan7_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) &sensor_dev_attr_fan7_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) &sensor_dev_attr_fan7_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) &sensor_dev_attr_fan8_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) &sensor_dev_attr_fan8_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) &sensor_dev_attr_fan8_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) &sensor_dev_attr_fan8_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static const struct attribute_group pc87427_group_fan[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) { .attrs = pc87427_attributes_fan[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) { .attrs = pc87427_attributes_fan[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) { .attrs = pc87427_attributes_fan[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) { .attrs = pc87427_attributes_fan[3] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) { .attrs = pc87427_attributes_fan[4] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) { .attrs = pc87427_attributes_fan[5] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) { .attrs = pc87427_attributes_fan[6] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) { .attrs = pc87427_attributes_fan[7] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * Must be called with data->lock held and pc87427_readall_pwm() freshly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int iobase = data->address[LD_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) data->pwm_enable[nr] &= ~PWM_ENABLE_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) data->pwm_enable[nr] |= mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static ssize_t pwm_enable_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int pwm_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) pwm_enable = pwm_enable_from_reg(data->pwm_enable[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (pwm_enable < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return pwm_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return sprintf(buf, "%d\n", pwm_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) static ssize_t pwm_enable_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (kstrtoul(buf, 10, &val) < 0 || val > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* Can't go to automatic mode if it isn't configured */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (val == 2 && !(data->pwm_auto_ok & (1 << nr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) pc87427_readall_pwm(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) update_pwm_enable(data, nr, pwm_enable_to_reg(val, data->pwm[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static ssize_t pwm_show(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return sprintf(buf, "%d\n", (int)data->pwm[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static ssize_t pwm_store(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int iobase = data->address[LD_FAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (kstrtoul(buf, 10, &val) < 0 || val > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) pc87427_readall_pwm(data, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) dev_notice(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) "Can't set PWM%d duty cycle while not in manual mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) nr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* We may have to change the mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (mode == PWM_MODE_MANUAL && val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* Transition from Manual to Off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) update_pwm_enable(data, nr, PWM_MODE_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) mode = PWM_MODE_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) "manual", "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) } else if (mode == PWM_MODE_OFF && val != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* Transition from Off to Manual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) update_pwm_enable(data, nr, PWM_MODE_MANUAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) mode = PWM_MODE_MANUAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) "off", "manual");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) data->pwm[nr] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (mode == PWM_MODE_MANUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) outb(val, iobase + PC87427_REG_PWM_DUTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_enable, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static SENSOR_DEVICE_ATTR_RW(pwm4_enable, pwm_enable, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static SENSOR_DEVICE_ATTR_RW(pwm4, pwm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static struct attribute *pc87427_attributes_pwm[4][3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) &sensor_dev_attr_pwm1_enable.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) &sensor_dev_attr_pwm1.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) &sensor_dev_attr_pwm2_enable.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) &sensor_dev_attr_pwm2.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) &sensor_dev_attr_pwm3_enable.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) &sensor_dev_attr_pwm3.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) &sensor_dev_attr_pwm4_enable.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) &sensor_dev_attr_pwm4.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) NULL
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static const struct attribute_group pc87427_group_pwm[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) { .attrs = pc87427_attributes_pwm[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) { .attrs = pc87427_attributes_pwm[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) { .attrs = pc87427_attributes_pwm[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) { .attrs = pc87427_attributes_pwm[3] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static ssize_t temp_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static ssize_t temp_min_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static ssize_t temp_max_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static ssize_t temp_crit_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static ssize_t temp_type_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static ssize_t temp_min_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return sprintf(buf, "%d\n", !!(data->temp_status[nr]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) & TEMP_STATUS_LOWFLG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static ssize_t temp_max_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return sprintf(buf, "%d\n", !!(data->temp_status[nr]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) & TEMP_STATUS_HIGHFLG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static ssize_t temp_crit_alarm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return sprintf(buf, "%d\n", !!(data->temp_status[nr]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) & TEMP_STATUS_CRITFLG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static ssize_t temp_fault_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) struct device_attribute *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct pc87427_data *data = pc87427_update_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) int nr = to_sensor_dev_attr(devattr)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return sprintf(buf, "%d\n", !!(data->temp_status[nr]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) & TEMP_STATUS_SENSERR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static SENSOR_DEVICE_ATTR_RO(temp3_input, temp_input, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static SENSOR_DEVICE_ATTR_RO(temp4_input, temp_input, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static SENSOR_DEVICE_ATTR_RO(temp5_input, temp_input, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static SENSOR_DEVICE_ATTR_RO(temp6_input, temp_input, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static SENSOR_DEVICE_ATTR_RO(temp1_min, temp_min, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static SENSOR_DEVICE_ATTR_RO(temp2_min, temp_min, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static SENSOR_DEVICE_ATTR_RO(temp3_min, temp_min, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static SENSOR_DEVICE_ATTR_RO(temp4_min, temp_min, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static SENSOR_DEVICE_ATTR_RO(temp5_min, temp_min, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) static SENSOR_DEVICE_ATTR_RO(temp6_min, temp_min, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static SENSOR_DEVICE_ATTR_RO(temp1_max, temp_max, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static SENSOR_DEVICE_ATTR_RO(temp2_max, temp_max, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static SENSOR_DEVICE_ATTR_RO(temp3_max, temp_max, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static SENSOR_DEVICE_ATTR_RO(temp4_max, temp_max, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static SENSOR_DEVICE_ATTR_RO(temp5_max, temp_max, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static SENSOR_DEVICE_ATTR_RO(temp6_max, temp_max, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static SENSOR_DEVICE_ATTR_RO(temp1_crit, temp_crit, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static SENSOR_DEVICE_ATTR_RO(temp2_crit, temp_crit, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static SENSOR_DEVICE_ATTR_RO(temp3_crit, temp_crit, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static SENSOR_DEVICE_ATTR_RO(temp4_crit, temp_crit, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static SENSOR_DEVICE_ATTR_RO(temp5_crit, temp_crit, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static SENSOR_DEVICE_ATTR_RO(temp6_crit, temp_crit, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static SENSOR_DEVICE_ATTR_RO(temp1_type, temp_type, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static SENSOR_DEVICE_ATTR_RO(temp2_type, temp_type, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static SENSOR_DEVICE_ATTR_RO(temp3_type, temp_type, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static SENSOR_DEVICE_ATTR_RO(temp4_type, temp_type, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static SENSOR_DEVICE_ATTR_RO(temp5_type, temp_type, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static SENSOR_DEVICE_ATTR_RO(temp6_type, temp_type, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, temp_min_alarm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, temp_min_alarm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, temp_min_alarm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static SENSOR_DEVICE_ATTR_RO(temp4_min_alarm, temp_min_alarm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static SENSOR_DEVICE_ATTR_RO(temp5_min_alarm, temp_min_alarm, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static SENSOR_DEVICE_ATTR_RO(temp6_min_alarm, temp_min_alarm, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, temp_max_alarm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, temp_max_alarm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, temp_max_alarm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static SENSOR_DEVICE_ATTR_RO(temp4_max_alarm, temp_max_alarm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static SENSOR_DEVICE_ATTR_RO(temp5_max_alarm, temp_max_alarm, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static SENSOR_DEVICE_ATTR_RO(temp6_max_alarm, temp_max_alarm, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, temp_crit_alarm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, temp_crit_alarm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, temp_crit_alarm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, temp_crit_alarm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, temp_crit_alarm, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, temp_crit_alarm, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static SENSOR_DEVICE_ATTR_RO(temp3_fault, temp_fault, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static SENSOR_DEVICE_ATTR_RO(temp4_fault, temp_fault, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static SENSOR_DEVICE_ATTR_RO(temp5_fault, temp_fault, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) static SENSOR_DEVICE_ATTR_RO(temp6_fault, temp_fault, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static struct attribute *pc87427_attributes_temp[6][10] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) &sensor_dev_attr_temp1_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) &sensor_dev_attr_temp1_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) &sensor_dev_attr_temp1_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) &sensor_dev_attr_temp1_crit.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) &sensor_dev_attr_temp1_type.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) &sensor_dev_attr_temp1_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) &sensor_dev_attr_temp2_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) &sensor_dev_attr_temp2_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) &sensor_dev_attr_temp2_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) &sensor_dev_attr_temp2_crit.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) &sensor_dev_attr_temp2_type.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) &sensor_dev_attr_temp2_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) &sensor_dev_attr_temp3_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) &sensor_dev_attr_temp3_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) &sensor_dev_attr_temp3_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) &sensor_dev_attr_temp3_crit.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) &sensor_dev_attr_temp3_type.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) &sensor_dev_attr_temp3_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) &sensor_dev_attr_temp4_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) &sensor_dev_attr_temp4_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) &sensor_dev_attr_temp4_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) &sensor_dev_attr_temp4_crit.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) &sensor_dev_attr_temp4_type.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) &sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) &sensor_dev_attr_temp4_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) &sensor_dev_attr_temp5_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) &sensor_dev_attr_temp5_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) &sensor_dev_attr_temp5_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) &sensor_dev_attr_temp5_crit.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) &sensor_dev_attr_temp5_type.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) &sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) &sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) &sensor_dev_attr_temp5_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) &sensor_dev_attr_temp6_input.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) &sensor_dev_attr_temp6_min.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) &sensor_dev_attr_temp6_max.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) &sensor_dev_attr_temp6_crit.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) &sensor_dev_attr_temp6_type.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) &sensor_dev_attr_temp6_min_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) &sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) &sensor_dev_attr_temp6_fault.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static const struct attribute_group pc87427_group_temp[6] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) { .attrs = pc87427_attributes_temp[0] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) { .attrs = pc87427_attributes_temp[1] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) { .attrs = pc87427_attributes_temp[2] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) { .attrs = pc87427_attributes_temp[3] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) { .attrs = pc87427_attributes_temp[4] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) { .attrs = pc87427_attributes_temp[5] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static ssize_t name_show(struct device *dev, struct device_attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) *devattr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return sprintf(buf, "%s\n", data->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static DEVICE_ATTR_RO(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * Device detection, attach and detach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static int pc87427_request_regions(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) res = platform_get_resource(pdev, IORESOURCE_IO, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) dev_err(&pdev->dev, "Missing resource #%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (!devm_request_region(&pdev->dev, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) resource_size(res), DRVNAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) "Failed to request region 0x%lx-0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) (unsigned long)res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) (unsigned long)res->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static void pc87427_init_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct pc87427_sio_data *sio_data = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* The FMC module should be ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (!(reg & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dev_warn(dev, "%s module not ready!\n", "FMC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /* Check which fans are enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (!(sio_data->has_fanin & (1 << i))) /* Not wired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) PC87427_REG_FAN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (reg & FAN_STATUS_MONEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) data->fan_enabled |= (1 << i);
^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) if (!data->fan_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) dev_dbg(dev, "Enabling monitoring of all fans\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!(sio_data->has_fanin & (1 << i))) /* Not wired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) PC87427_REG_FAN_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) FAN_STATUS_MONEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) data->fan_enabled = sio_data->has_fanin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* Check which PWM outputs are enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!(sio_data->has_fanout & (1 << i))) /* Not wired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) reg = pc87427_read8_bank(data, LD_FAN, BANK_FC(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) PC87427_REG_PWM_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (reg & PWM_ENABLE_CTLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) data->pwm_enabled |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * We don't expose an interface to reconfigure the automatic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * fan control mode, so only allow to return to this mode if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * it was originally set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) dev_dbg(dev, "PWM%d is in automatic control mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) data->pwm_auto_ok |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* The HMC module should be ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) reg = pc87427_read8(data, LD_TEMP, PC87427_REG_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (!(reg & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) dev_warn(dev, "%s module not ready!\n", "HMC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* Check which temperature channels are enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) reg = pc87427_read8_bank(data, LD_TEMP, BANK_TM(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) PC87427_REG_TEMP_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (reg & TEMP_STATUS_CHANEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) data->temp_enabled |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) static void pc87427_remove_files(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct pc87427_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) device_remove_file(dev, &dev_attr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (!(data->fan_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) sysfs_remove_group(&dev->kobj, &pc87427_group_fan[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (!(data->pwm_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) sysfs_remove_group(&dev->kobj, &pc87427_group_pwm[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!(data->temp_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) sysfs_remove_group(&dev->kobj, &pc87427_group_temp[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) static int pc87427_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) struct pc87427_sio_data *sio_data = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) struct pc87427_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) int i, err, res_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) data = devm_kzalloc(&pdev->dev, sizeof(struct pc87427_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) data->address[0] = sio_data->address[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) data->address[1] = sio_data->address[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) res_count = (data->address[0] != 0) + (data->address[1] != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) err = pc87427_request_regions(pdev, res_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) data->name = "pc87427";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) pc87427_init_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /* Register sysfs hooks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) err = device_create_file(&pdev->dev, &dev_attr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!(data->fan_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) err = sysfs_create_group(&pdev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) &pc87427_group_fan[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) goto exit_remove_files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (!(data->pwm_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) err = sysfs_create_group(&pdev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) &pc87427_group_pwm[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) goto exit_remove_files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (!(data->temp_enabled & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) err = sysfs_create_group(&pdev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) &pc87427_group_temp[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) goto exit_remove_files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) data->hwmon_dev = hwmon_device_register(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (IS_ERR(data->hwmon_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) err = PTR_ERR(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) goto exit_remove_files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) exit_remove_files:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) pc87427_remove_files(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int pc87427_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct pc87427_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) hwmon_device_unregister(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) pc87427_remove_files(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static struct platform_driver pc87427_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) .name = DRVNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) .probe = pc87427_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) .remove = pc87427_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct resource res[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) { .flags = IORESOURCE_IO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) { .flags = IORESOURCE_IO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) int err, i, res_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) res_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (!sio_data->address[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) res[res_count].start = sio_data->address[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) res[res_count].end = sio_data->address[i] + REGION_LENGTH - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) res[res_count].name = logdev_str[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) err = acpi_check_resource_conflict(&res[res_count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) res_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) pdev = platform_device_alloc(DRVNAME, res[0].start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (!pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) pr_err("Device allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) err = platform_device_add_resources(pdev, res, res_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) pr_err("Device resource addition failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) goto exit_device_put;
^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) err = platform_device_add_data(pdev, sio_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) sizeof(struct pc87427_sio_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) pr_err("Platform data allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) err = platform_device_add(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) pr_err("Device addition failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) goto exit_device_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) exit_device_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) platform_device_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) u8 cfg, cfg_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) err = superio_enter(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) /* Identify device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (val != 0xf2) { /* PC87427 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) sio_data->address[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /* Select logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) val = superio_inb(sioaddr, SIOREG_ACT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (!(val & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) pr_info("Logical device 0x%02x not activated\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) val = superio_inb(sioaddr, SIOREG_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (val & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) pr_warn("Logical device 0x%02x is memory-mapped, can't use\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) | superio_inb(sioaddr, SIOREG_IOBASE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) pr_info("I/O base address not set for logical device 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) logdev[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) sio_data->address[i] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /* No point in loading the driver if everything is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (!sio_data->address[0] && !sio_data->address[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* Check which fan inputs are wired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) sio_data->has_fanin = (1 << 2) | (1 << 3); /* FANIN2, FANIN3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) cfg = superio_inb(sioaddr, SIOREG_CF2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (!(cfg & (1 << 3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) sio_data->has_fanin |= (1 << 0); /* FANIN0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (!(cfg & (1 << 2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) sio_data->has_fanin |= (1 << 4); /* FANIN4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) cfg = superio_inb(sioaddr, SIOREG_CFD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (!(cfg & (1 << 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) sio_data->has_fanin |= (1 << 1); /* FANIN1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) cfg = superio_inb(sioaddr, SIOREG_CF4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (!(cfg & (1 << 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) sio_data->has_fanin |= (1 << 7); /* FANIN7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) cfg_b = superio_inb(sioaddr, SIOREG_CFB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) sio_data->has_fanin |= (1 << 5); /* FANIN5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) cfg = superio_inb(sioaddr, SIOREG_CF3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) sio_data->has_fanin |= (1 << 6); /* FANIN6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) /* Check which fan outputs are wired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) sio_data->has_fanout = (1 << 0); /* FANOUT0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (cfg_b & (1 << 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) sio_data->has_fanout |= (1 << 3); /* FANOUT3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) cfg = superio_inb(sioaddr, SIOREG_CFC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (!(cfg & (1 << 4))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (cfg_b & (1 << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) sio_data->has_fanout |= (1 << 1); /* FANOUT1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (cfg_b & (1 << 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) sio_data->has_fanout |= (1 << 2); /* FANOUT2 */
^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) /* FANOUT1 and FANOUT2 can each be routed to 2 different pins */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) cfg = superio_inb(sioaddr, SIOREG_CF5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (cfg & (1 << 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) sio_data->has_fanout |= (1 << 1); /* FANOUT1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (cfg & (1 << 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) sio_data->has_fanout |= (1 << 2); /* FANOUT2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) superio_exit(sioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static int __init pc87427_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) struct pc87427_sio_data sio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (pc87427_find(0x2e, &sio_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) && pc87427_find(0x4e, &sio_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) err = platform_driver_register(&pc87427_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) /* Sets global pdev as a side effect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) err = pc87427_device_add(&sio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) goto exit_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) exit_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) platform_driver_unregister(&pc87427_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static void __exit pc87427_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) platform_driver_unregister(&pc87427_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) module_init(pc87427_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) module_exit(pc87427_exit);