1ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* 2ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * vt1211.c - driver for the VIA VT1211 Super-I/O chip integrated hardware 3ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * monitoring features 4ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Copyright (C) 2006 Juerg Haefliger <juergh@gmail.com> 5ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 6ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * This driver is based on the driver for kernel 2.4 by Mark D. Studebaker 7ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * and its port to kernel 2.6 by Lars Ekman. 8ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 9ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * This program is free software; you can redistribute it and/or modify 10ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * it under the terms of the GNU General Public License as published by 11ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * the Free Software Foundation; either version 2 of the License, or 12ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * (at your option) any later version. 13ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 14ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * This program is distributed in the hope that it will be useful, 15ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * but WITHOUT ANY WARRANTY; without even the implied warranty of 16ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * GNU General Public License for more details. 18ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 19ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * You should have received a copy of the GNU General Public License 20ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * along with this program; if not, write to the Free Software 21ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger */ 23ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 245ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 255ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches 26ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/module.h> 27ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/init.h> 28ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/slab.h> 29ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/jiffies.h> 30ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/platform_device.h> 31ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/hwmon.h> 32ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/hwmon-sysfs.h> 33ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/hwmon-vid.h> 34ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/err.h> 35ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#include <linux/mutex.h> 36ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare#include <linux/ioport.h> 37b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare#include <linux/acpi.h> 386055fae8aceee41471edfd1876e5617d16e028feH Hartley Sweeten#include <linux/io.h> 39ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 40ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic int uch_config = -1; 41ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligermodule_param(uch_config, int, 0); 42ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerMODULE_PARM_DESC(uch_config, "Initialize the universal channel configuration"); 43ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 44ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic int int_mode = -1; 45ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligermodule_param(int_mode, int, 0); 46ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerMODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode"); 47ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 4867b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvarestatic unsigned short force_id; 4967b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvaremodule_param(force_id, ushort, 0); 5067b671bceb4a8340a30929e9642620d99ed5ad76Jean DelvareMODULE_PARM_DESC(force_id, "Override the detected device ID"); 5167b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare 52ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic struct platform_device *pdev; 53ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 54ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define DRVNAME "vt1211" 55ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 56ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 57ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Registers 58ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 59ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * The sensors are defined as follows. 60ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 61ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Sensor Voltage Mode Temp Mode Notes (from the datasheet) 62ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * -------- ------------ --------- -------------------------- 63ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Reading 1 temp1 Intel thermal diode 64ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Reading 3 temp2 Internal thermal diode 65ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * UCH1/Reading2 in0 temp3 NTC type thermistor 66ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * UCH2 in1 temp4 +2.5V 67ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * UCH3 in2 temp5 VccP 68ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * UCH4 in3 temp6 +5V 69ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * UCH5 in4 temp7 +12V 70ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 3.3V in5 Internal VDD (+3.3V) 71ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 72ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 73ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 74ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* Voltages (in) numbered 0-5 (ix) */ 75ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_IN(ix) (0x21 + (ix)) 76ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_IN_MIN(ix) ((ix) == 0 ? 0x3e : 0x2a + 2 * (ix)) 77ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_IN_MAX(ix) ((ix) == 0 ? 0x3d : 0x29 + 2 * (ix)) 78ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 79ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* Temperatures (temp) numbered 0-6 (ix) */ 80ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic u8 regtemp[] = {0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25}; 81ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic u8 regtempmax[] = {0x39, 0x1d, 0x3d, 0x2b, 0x2d, 0x2f, 0x31}; 82ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic u8 regtemphyst[] = {0x3a, 0x1e, 0x3e, 0x2c, 0x2e, 0x30, 0x32}; 83ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 84ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* Fans numbered 0-1 (ix) */ 85ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_FAN(ix) (0x29 + (ix)) 86ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_FAN_MIN(ix) (0x3b + (ix)) 87ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_FAN_DIV 0x47 88ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 89ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* PWMs numbered 0-1 (ix) */ 90ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* Auto points numbered 0-3 (ap) */ 91ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_PWM(ix) (0x60 + (ix)) 92ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_PWM_CLK 0x50 93ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_PWM_CTL 0x51 94ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_PWM_AUTO_TEMP(ap) (0x55 - (ap)) 95ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_PWM_AUTO_PWM(ix, ap) (0x58 + 2 * (ix) - (ap)) 96ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 97ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* Miscellaneous registers */ 98ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_CONFIG 0x40 99ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_ALARM1 0x41 100ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_ALARM2 0x42 101ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_VID 0x45 102ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_UCH_CONFIG 0x4a 103ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_TEMP1_CONFIG 0x4b 104ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define VT1211_REG_TEMP2_CONFIG 0x4c 105ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 106ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* In, temp & fan alarm bits */ 107ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic const u8 bitalarmin[] = {11, 0, 1, 3, 8, 2, 9}; 108ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic const u8 bitalarmtemp[] = {4, 15, 11, 0, 1, 3, 8}; 109ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic const u8 bitalarmfan[] = {6, 7}; 110ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 111ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 112ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Data structures and manipulation thereof 113ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 114ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 115ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstruct vt1211_data { 116ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger unsigned short addr; 117ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *name; 1181beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones struct device *hwmon_dev; 119ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 120ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct mutex update_lock; 121ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char valid; /* !=0 if following fields are valid */ 122ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger unsigned long last_updated; /* In jiffies */ 123ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 124ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Register values */ 125ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 in[6]; 126ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 in_max[6]; 127ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 in_min[6]; 128ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 temp[7]; 129ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 temp_max[7]; 130ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 temp_hyst[7]; 131ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 fan[2]; 132ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 fan_min[2]; 133ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 fan_div[2]; 134ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 fan_ctl; 135ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 pwm[2]; 136ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 pwm_ctl[2]; 137ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 pwm_clk; 138ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 pwm_auto_temp[4]; 139ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 pwm_auto_pwm[2][4]; 140ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 vid; /* Read once at init time */ 141ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 vrm; 142ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u8 uch_config; /* Read once at init time */ 143ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger u16 alarms; 144ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 145ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 146ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* ix = [0-5] */ 147ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define ISVOLT(ix, uch_config) ((ix) > 4 ? 1 : \ 148ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger !(((uch_config) >> ((ix) + 2)) & 1)) 149ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 150ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* ix = [0-6] */ 151ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define ISTEMP(ix, uch_config) ((ix) < 2 ? 1 : \ 152ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((uch_config) >> (ix)) & 1) 153ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 154b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck/* 155b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * in5 (ix = 5) is special. It's the internal 3.3V so it's scaled in the 156b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * driver according to the VT1211 BIOS porting guide 157b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck */ 158ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define IN_FROM_REG(ix, reg) ((reg) < 3 ? 0 : (ix) == 5 ? \ 159ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (((reg) - 3) * 15882 + 479) / 958 : \ 160ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (((reg) - 3) * 10000 + 479) / 958) 161ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define IN_TO_REG(ix, val) (SENSORS_LIMIT((ix) == 5 ? \ 162ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((val) * 958 + 7941) / 15882 + 3 : \ 163ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((val) * 958 + 5000) / 10000 + 3, 0, 255)) 164ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 165b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck/* 166b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * temp1 (ix = 0) is an intel thermal diode which is scaled in user space. 167b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * temp2 (ix = 1) is the internal temp diode so it's scaled in the driver 168b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * according to some measurements that I took on an EPIA M10000. 169b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * temp3-7 are thermistor based so the driver returns the voltage measured at 170b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * the pin (range 0V - 2.2V). 171b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck */ 172ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define TEMP_FROM_REG(ix, reg) ((ix) == 0 ? (reg) * 1000 : \ 173ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (ix) == 1 ? (reg) < 51 ? 0 : \ 174ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((reg) - 51) * 1000 : \ 175ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((253 - (reg)) * 2200 + 105) / 210) 176ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define TEMP_TO_REG(ix, val) SENSORS_LIMIT( \ 177ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((ix) == 0 ? ((val) + 500) / 1000 : \ 178ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (ix) == 1 ? ((val) + 500) / 1000 + 51 : \ 179ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 253 - ((val) * 210 + 1100) / 2200), 0, 255) 180ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 181ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define DIV_FROM_REG(reg) (1 << (reg)) 182ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 183ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define RPM_FROM_REG(reg, div) (((reg) == 0) || ((reg) == 255) ? 0 : \ 184ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1310720 / (reg) / DIV_FROM_REG(div)) 185ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define RPM_TO_REG(val, div) ((val) == 0 ? 255 : \ 186ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSORS_LIMIT((1310720 / (val) / \ 187ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger DIV_FROM_REG(div)), 1, 254)) 188ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 189ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 190ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Super-I/O constants and functions 191ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 192ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 193b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck/* 194b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * Configuration index port registers 195b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * The vt1211 can live at 2 different addresses so we need to probe both 196b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck */ 1972219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger#define SIO_REG_CIP1 0x2e 1982219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger#define SIO_REG_CIP2 0x4e 199ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 200ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* Configuration registers */ 201ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_LDN 0x07 /* logical device number */ 202ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_DEVID 0x20 /* device ID */ 203ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_DEVREV 0x21 /* device revision */ 204ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_ACTIVE 0x30 /* HW monitor active */ 205ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_BADDR 0x60 /* base I/O address */ 206ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_ID 0x3c /* VT1211 device ID */ 207ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 208ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* VT1211 logical device numbers */ 209ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */ 210ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 2112219cd81a6cd186200606693b360c6429c003bb3Juerg Haefligerstatic inline void superio_outb(int sio_cip, int reg, int val) 212ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 2132219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(reg, sio_cip); 2142219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(val, sio_cip + 1); 215ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 216ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 2172219cd81a6cd186200606693b360c6429c003bb3Juerg Haefligerstatic inline int superio_inb(int sio_cip, int reg) 218ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 2192219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(reg, sio_cip); 2202219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger return inb(sio_cip + 1); 221ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 222ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 2232219cd81a6cd186200606693b360c6429c003bb3Juerg Haefligerstatic inline void superio_select(int sio_cip, int ldn) 224ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 2252219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(SIO_VT1211_LDN, sio_cip); 2262219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(ldn, sio_cip + 1); 227ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 228ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 2292219cd81a6cd186200606693b360c6429c003bb3Juerg Haefligerstatic inline void superio_enter(int sio_cip) 230ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 2312219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(0x87, sio_cip); 2322219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(0x87, sio_cip); 233ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 234ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 2352219cd81a6cd186200606693b360c6429c003bb3Juerg Haefligerstatic inline void superio_exit(int sio_cip) 236ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 2372219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger outb(0xaa, sio_cip); 238ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 239ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 240ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 241ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Device I/O access 242ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 243ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 244ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic inline u8 vt1211_read8(struct vt1211_data *data, u8 reg) 245ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 246ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return inb(data->addr + reg); 247ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 248ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 249ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic inline void vt1211_write8(struct vt1211_data *data, u8 reg, u8 val) 250ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 251ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger outb(val, data->addr + reg); 252ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 253ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 254ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic struct vt1211_data *vt1211_update_device(struct device *dev) 255ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 256ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 257ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix, val; 258ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 259ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 260ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 261ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* registers cache is refreshed after 1 second */ 262ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { 263ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* read VID */ 264ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->vid = vt1211_read8(data, VT1211_REG_VID) & 0x1f; 265ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 266ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* voltage (in) registers */ 267ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { 268ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (ISVOLT(ix, data->uch_config)) { 269ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->in[ix] = vt1211_read8(data, 270ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_IN(ix)); 271ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->in_min[ix] = vt1211_read8(data, 272ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_IN_MIN(ix)); 273ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->in_max[ix] = vt1211_read8(data, 274ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_IN_MAX(ix)); 275ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 276ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 277ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 278ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* temp registers */ 279ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { 280ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (ISTEMP(ix, data->uch_config)) { 281ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp[ix] = vt1211_read8(data, 282ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger regtemp[ix]); 283ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp_max[ix] = vt1211_read8(data, 284ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger regtempmax[ix]); 285ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp_hyst[ix] = vt1211_read8(data, 286ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger regtemphyst[ix]); 287ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 288ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 289ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 290ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* fan & pwm registers */ 291ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { 292ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan[ix] = vt1211_read8(data, 293ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_FAN(ix)); 294ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_min[ix] = vt1211_read8(data, 295ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_FAN_MIN(ix)); 296ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm[ix] = vt1211_read8(data, 297ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_PWM(ix)); 298ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 299ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger val = vt1211_read8(data, VT1211_REG_FAN_DIV); 300ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_div[0] = (val >> 4) & 3; 301ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_div[1] = (val >> 6) & 3; 302ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl = val & 0xf; 303ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 304ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger val = vt1211_read8(data, VT1211_REG_PWM_CTL); 305ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[0] = val & 0xf; 306ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[1] = (val >> 4) & 0xf; 307ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 308ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_clk = vt1211_read8(data, VT1211_REG_PWM_CLK); 309ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 310ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* pwm & temp auto point registers */ 311ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[0][1] = vt1211_read8(data, 312ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_PWM_AUTO_PWM(0, 1)); 313ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[0][2] = vt1211_read8(data, 314ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_PWM_AUTO_PWM(0, 2)); 315ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[1][1] = vt1211_read8(data, 316ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_PWM_AUTO_PWM(1, 1)); 317ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[1][2] = vt1211_read8(data, 318ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_PWM_AUTO_PWM(1, 2)); 319ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (ix = 0; ix < ARRAY_SIZE(data->pwm_auto_temp); ix++) { 320ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_temp[ix] = vt1211_read8(data, 321ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger VT1211_REG_PWM_AUTO_TEMP(ix)); 322ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 323ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 324ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* alarm registers */ 325ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->alarms = (vt1211_read8(data, VT1211_REG_ALARM2) << 8) | 326ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_read8(data, VT1211_REG_ALARM1); 327ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 328ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->last_updated = jiffies; 329ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->valid = 1; 330ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 331ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 332ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 333ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 334ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return data; 335ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 336ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 337ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 338ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Voltage sysfs interfaces 339ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix = [0-5] 340ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 341ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 342ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_IN_INPUT 0 343ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_IN_MIN 1 344ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_IN_MAX 2 345ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_IN_ALARM 3 346ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 347ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_in(struct device *dev, struct device_attribute *attr, 348ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 349ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 350ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 351ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 352ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 353ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 354ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 355ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int res; 356ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 357ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 358ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_IN_INPUT: 359ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = IN_FROM_REG(ix, data->in[ix]); 360ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 361ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_IN_MIN: 362ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = IN_FROM_REG(ix, data->in_min[ix]); 363ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 364ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_IN_MAX: 365ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = IN_FROM_REG(ix, data->in_max[ix]); 366ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 367ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_IN_ALARM: 368ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = (data->alarms >> bitalarmin[ix]) & 1; 369ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 370ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 371ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = 0; 372ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 373ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 374ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 375ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", res); 376ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 377ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 378ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_in(struct device *dev, struct device_attribute *attr, 379ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 380ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 381ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 382ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 383ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 384ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 385ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 386b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck long val; 387b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 388b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 389b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtol(buf, 10, &val); 390b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 391b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 392ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 393ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 394ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 395ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_IN_MIN: 396ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->in_min[ix] = IN_TO_REG(ix, val); 397ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_IN_MIN(ix), data->in_min[ix]); 398ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 399ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_IN_MAX: 400ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->in_max[ix] = IN_TO_REG(ix, val); 401ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_IN_MAX(ix), data->in_max[ix]); 402ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 403ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 404ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 405ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 406ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 407ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 408ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 409ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 410ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 411ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 412ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Temperature sysfs interfaces 413ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix = [0-6] 414ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 415ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 416ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_TEMP_INPUT 0 417ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_TEMP_MAX 1 418ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_TEMP_MAX_HYST 2 419ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_TEMP_ALARM 3 420ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 421ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_temp(struct device *dev, struct device_attribute *attr, 422ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 423ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 424ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 425ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 426ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 427ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 428ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 429ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int res; 430ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 431ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 432ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_TEMP_INPUT: 433ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = TEMP_FROM_REG(ix, data->temp[ix]); 434ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 435ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_TEMP_MAX: 436ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = TEMP_FROM_REG(ix, data->temp_max[ix]); 437ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 438ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_TEMP_MAX_HYST: 439ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = TEMP_FROM_REG(ix, data->temp_hyst[ix]); 440ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 441ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_TEMP_ALARM: 442ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = (data->alarms >> bitalarmtemp[ix]) & 1; 443ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 444ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 445ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = 0; 446ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 447ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 448ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 449ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", res); 450ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 451ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 452ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_temp(struct device *dev, struct device_attribute *attr, 453ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 454ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 455ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 456ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 457ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 458ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 459ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 460b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck long val; 461b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 462b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 463b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtol(buf, 10, &val); 464b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 465b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 466ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 467ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 468ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 469ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_TEMP_MAX: 470ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp_max[ix] = TEMP_TO_REG(ix, val); 471ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, regtempmax[ix], 472ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp_max[ix]); 473ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 474ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_TEMP_MAX_HYST: 475ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp_hyst[ix] = TEMP_TO_REG(ix, val); 476ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, regtemphyst[ix], 477ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->temp_hyst[ix]); 478ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 479ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 480ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 481ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 482ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 483ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 484ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 485ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 486ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 487ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 488ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Fan sysfs interfaces 489ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix = [0-1] 490ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 491ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 492ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_FAN_INPUT 0 493ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_FAN_MIN 1 494ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_FAN_DIV 2 495ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_FAN_ALARM 3 496ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 497ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_fan(struct device *dev, struct device_attribute *attr, 498ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 499ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 500ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 501ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 502ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 503ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 504ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 505ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int res; 506ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 507ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 508ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_FAN_INPUT: 509ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = RPM_FROM_REG(data->fan[ix], data->fan_div[ix]); 510ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 511ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_FAN_MIN: 512ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = RPM_FROM_REG(data->fan_min[ix], data->fan_div[ix]); 513ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 514ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_FAN_DIV: 515ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = DIV_FROM_REG(data->fan_div[ix]); 516ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 517ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_FAN_ALARM: 518ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = (data->alarms >> bitalarmfan[ix]) & 1; 519ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 520ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 521ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = 0; 522ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 523ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 524ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 525ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", res); 526ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 527ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 528ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_fan(struct device *dev, struct device_attribute *attr, 529ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 530ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 531ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 532ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 533ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 534ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 535ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 536ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int reg; 537b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck unsigned long val; 538b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 539b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 540b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtoul(buf, 10, &val); 541b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 542b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 543ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 544ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 545ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 546ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* sync the data cache */ 547ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger reg = vt1211_read8(data, VT1211_REG_FAN_DIV); 548ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_div[0] = (reg >> 4) & 3; 549ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_div[1] = (reg >> 6) & 3; 550ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl = reg & 0xf; 551ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 552ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 553ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_FAN_MIN: 554ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_min[ix] = RPM_TO_REG(val, data->fan_div[ix]); 555ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_FAN_MIN(ix), 556ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_min[ix]); 557ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 558ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_FAN_DIV: 559ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (val) { 560b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck case 1: 561b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck data->fan_div[ix] = 0; 562b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck break; 563b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck case 2: 564b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck data->fan_div[ix] = 1; 565b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck break; 566b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck case 4: 567b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck data->fan_div[ix] = 2; 568b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck break; 569b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck case 8: 570b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck data->fan_div[ix] = 3; 571b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck break; 572b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck default: 573b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck count = -EINVAL; 574b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck dev_warn(dev, "fan div value %ld not supported. " 575b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck "Choose one of 1, 2, 4, or 8.\n", val); 576b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck goto EXIT; 577ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 578ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_FAN_DIV, 579ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((data->fan_div[1] << 6) | 580ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (data->fan_div[0] << 4) | 581ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl)); 582ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 583ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 584ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 585ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 586ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 587ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT: 588ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 589ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 590ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 591ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 592ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 593ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * PWM sysfs interfaces 594ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix = [0-1] 595ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 596ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 597ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_PWM 0 598ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_PWM_ENABLE 1 599ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_PWM_FREQ 2 600ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SHOW_SET_PWM_AUTO_CHANNELS_TEMP 3 601ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 602ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_pwm(struct device *dev, struct device_attribute *attr, 603ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 604ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 605ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 606ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 607ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 608ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 609ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 610ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int res; 611ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 612ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 613ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_PWM: 614ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = data->pwm[ix]; 615ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 616ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_PWM_ENABLE: 617ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = ((data->pwm_ctl[ix] >> 3) & 1) ? 2 : 0; 618ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 619ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_PWM_FREQ: 620ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = 90000 >> (data->pwm_clk & 7); 621ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 622ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_PWM_AUTO_CHANNELS_TEMP: 623ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = (data->pwm_ctl[ix] & 7) + 1; 624ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 625ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 626ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = 0; 627ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 628ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 629ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 630ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", res); 631ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 632ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 633ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_pwm(struct device *dev, struct device_attribute *attr, 634ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 635ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 636ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 637ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 638ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 639ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 640ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int fn = sensor_attr_2->nr; 641ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int tmp, reg; 642b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck unsigned long val; 643b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 644b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 645b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtoul(buf, 10, &val); 646b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 647b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 648ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 649ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 650ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 651ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (fn) { 652ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_PWM_ENABLE: 653ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* sync the data cache */ 654ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger reg = vt1211_read8(data, VT1211_REG_FAN_DIV); 655ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_div[0] = (reg >> 4) & 3; 656ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_div[1] = (reg >> 6) & 3; 657ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl = reg & 0xf; 658ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger reg = vt1211_read8(data, VT1211_REG_PWM_CTL); 659ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[0] = reg & 0xf; 660ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[1] = (reg >> 4) & 0xf; 661ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger switch (val) { 662ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case 0: 663ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[ix] &= 7; 664b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck /* 665b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * disable SmartGuardian if both PWM outputs are 666b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * disabled 667b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck */ 668b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if ((data->pwm_ctl[ix ^ 1] & 1) == 0) 669ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl &= 0xe; 670ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 671ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case 2: 672ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[ix] |= 8; 673ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl |= 1; 674ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 675ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 676ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger count = -EINVAL; 677ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_warn(dev, "pwm mode %ld not supported. " 678ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger "Choose one of 0 or 2.\n", val); 679ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 680ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 681ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_PWM_CTL, 682ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((data->pwm_ctl[1] << 4) | 683ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[0])); 684ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_FAN_DIV, 685ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((data->fan_div[1] << 6) | 686ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (data->fan_div[0] << 4) | 687ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->fan_ctl)); 688ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 689ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_PWM_FREQ: 690ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000); 691ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* calculate tmp = log2(val) */ 692ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger tmp = 0; 693b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck for (val >>= 1; val > 0; val >>= 1) 694ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger tmp++; 695ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* sync the data cache */ 696ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger reg = vt1211_read8(data, VT1211_REG_PWM_CLK); 697ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_clk = (reg & 0xf8) | tmp; 698ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk); 699ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 700ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger case SHOW_SET_PWM_AUTO_CHANNELS_TEMP: 701b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (val < 1 || val > 7) { 702ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger count = -EINVAL; 703ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_warn(dev, "temp channel %ld not supported. " 704ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger "Choose a value between 1 and 7.\n", val); 705ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 706ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 707ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (!ISTEMP(val - 1, data->uch_config)) { 708ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger count = -EINVAL; 709ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_warn(dev, "temp channel %ld is not available.\n", 710ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger val); 711ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 712ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 713ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* sync the data cache */ 714ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger reg = vt1211_read8(data, VT1211_REG_PWM_CTL); 715ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[0] = reg & 0xf; 716ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[1] = (reg >> 4) & 0xf; 717ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[ix] = (data->pwm_ctl[ix] & 8) | (val - 1); 718ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_PWM_CTL, 719ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ((data->pwm_ctl[1] << 4) | data->pwm_ctl[0])); 720ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger break; 721ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger default: 722ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); 723ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 724ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 725ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT: 726ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 727ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 728ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 729ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 730ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 731ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * PWM auto point definitions 732ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix = [0-1] 733ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ap = [0-3] 734ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 735ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 736ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* 737ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * pwm[ix+1]_auto_point[ap+1]_temp mapping table: 738ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Note that there is only a single set of temp auto points that controls both 739ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * PWM controllers. We still create 2 sets of sysfs files to make it look 740ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * more consistent even though they map to the same registers. 741ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 742ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix ap : description 743ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ------------------- 744ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 0 : pwm1/2 off temperature (pwm_auto_temp[0]) 745ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 1 : pwm1/2 low speed temperature (pwm_auto_temp[1]) 746ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 2 : pwm1/2 high speed temperature (pwm_auto_temp[2]) 747ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 3 : pwm1/2 full speed temperature (pwm_auto_temp[3]) 748ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 0 : pwm1/2 off temperature (pwm_auto_temp[0]) 749ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 1 : pwm1/2 low speed temperature (pwm_auto_temp[1]) 750ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 2 : pwm1/2 high speed temperature (pwm_auto_temp[2]) 751ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 3 : pwm1/2 full speed temperature (pwm_auto_temp[3]) 752ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger */ 753ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 754ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_pwm_auto_point_temp(struct device *dev, 755ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device_attribute *attr, 756ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 757ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 758ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 759ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 760ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 761ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 762ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ap = sensor_attr_2->nr; 763ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 764ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", TEMP_FROM_REG(data->pwm_ctl[ix] & 7, 765ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_temp[ap])); 766ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 767ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 768ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_pwm_auto_point_temp(struct device *dev, 769ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device_attribute *attr, 770ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 771ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 772ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 773ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 774ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 775ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 776ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ap = sensor_attr_2->nr; 777ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int reg; 778b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck long val; 779b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 780b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 781b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtol(buf, 10, &val); 782b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 783b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 784b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 785ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 786ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 787ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 788ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* sync the data cache */ 789ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger reg = vt1211_read8(data, VT1211_REG_PWM_CTL); 790ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[0] = reg & 0xf; 791ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_ctl[1] = (reg >> 4) & 0xf; 792ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 793ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_temp[ap] = TEMP_TO_REG(data->pwm_ctl[ix] & 7, val); 794ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_PWM_AUTO_TEMP(ap), 795ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_temp[ap]); 796ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 797ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 798ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 799ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 800ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 801ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* 802ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * pwm[ix+1]_auto_point[ap+1]_pwm mapping table: 803ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Note that the PWM auto points 0 & 3 are hard-wired in the VT1211 and can't 804ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * be changed. 805ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 806ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ix ap : description 807ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * ------------------- 808ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 0 : pwm1 off (pwm_auto_pwm[0][0], hard-wired to 0) 809ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 1 : pwm1 low speed duty cycle (pwm_auto_pwm[0][1]) 810ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 2 : pwm1 high speed duty cycle (pwm_auto_pwm[0][2]) 811ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0 3 : pwm1 full speed (pwm_auto_pwm[0][3], hard-wired to 255) 812ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 0 : pwm2 off (pwm_auto_pwm[1][0], hard-wired to 0) 813ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 1 : pwm2 low speed duty cycle (pwm_auto_pwm[1][1]) 814ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 2 : pwm2 high speed duty cycle (pwm_auto_pwm[1][2]) 815ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1 3 : pwm2 full speed (pwm_auto_pwm[1][3], hard-wired to 255) 816b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck */ 817ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 818ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_pwm_auto_point_pwm(struct device *dev, 819ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device_attribute *attr, 820ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 821ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 822ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 823ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 824ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 825ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 826ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ap = sensor_attr_2->nr; 827ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 828ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", data->pwm_auto_pwm[ix][ap]); 829ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 830ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 831ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_pwm_auto_point_pwm(struct device *dev, 832ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device_attribute *attr, 833ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 834ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 835ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 836ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct sensor_device_attribute_2 *sensor_attr_2 = 837ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger to_sensor_dev_attr_2(attr); 838ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ix = sensor_attr_2->index; 839ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int ap = sensor_attr_2->nr; 840b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck unsigned long val; 841b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 842ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 843b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtoul(buf, 10, &val); 844b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 845b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 846ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 847ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_lock(&data->update_lock); 848b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck data->pwm_auto_pwm[ix][ap] = SENSORS_LIMIT(val, 0, 255); 849ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap), 850ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[ix][ap]); 851ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_unlock(&data->update_lock); 852ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 853ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 854ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 855ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 856ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 857ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Miscellaneous sysfs interfaces (VRM, VID, name, and (legacy) alarms) 858ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 859ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 860ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_vrm(struct device *dev, struct device_attribute *attr, 861ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 862ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 863ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 864ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 865ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", data->vrm); 866ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 867ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 868ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t set_vrm(struct device *dev, struct device_attribute *attr, 869ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger const char *buf, size_t count) 870ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 871ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 872b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck unsigned long val; 873b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck int err; 874b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck 875b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = kstrtoul(buf, 10, &val); 876b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 877b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck return err; 878ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 879ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->vrm = val; 880ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 881ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return count; 882ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 883ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 884ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_vid(struct device *dev, struct device_attribute *attr, 885ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger char *buf) 886ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 887ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 888ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 889ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); 890ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 891ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 892ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_name(struct device *dev, 893ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device_attribute *attr, char *buf) 894ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 895ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = dev_get_drvdata(dev); 896ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 897ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%s\n", data->name); 898ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 899ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 900ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic ssize_t show_alarms(struct device *dev, 901ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device_attribute *attr, char *buf) 902ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 903ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = vt1211_update_device(dev); 904ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 905ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return sprintf(buf, "%d\n", data->alarms); 906ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 907ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 908ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 909ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Device attribute structs 910ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 911ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 9122185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck#define SENSOR_ATTR_IN(ix) \ 9132185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck{ SENSOR_ATTR_2(in##ix##_input, S_IRUGO, \ 9142185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_in, NULL, SHOW_IN_INPUT, ix), \ 915ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \ 9162185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_in, set_in, SHOW_SET_IN_MIN, ix), \ 917ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \ 9182185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_in, set_in, SHOW_SET_IN_MAX, ix), \ 9192185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_2(in##ix##_alarm, S_IRUGO, \ 9202185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_in, NULL, SHOW_IN_ALARM, ix) \ 9212185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck} 9222185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck 9232185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeckstatic struct sensor_device_attribute_2 vt1211_sysfs_in[][4] = { 9242185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_IN(0), 9252185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_IN(1), 9262185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_IN(2), 9272185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_IN(3), 9282185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_IN(4), 9292185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_IN(5) 930ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 931ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 9322185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck#define IN_UNIT_ATTRS(X) \ 9332185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck{ &vt1211_sysfs_in[X][0].dev_attr.attr, \ 9342185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_sysfs_in[X][1].dev_attr.attr, \ 9352185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_sysfs_in[X][2].dev_attr.attr, \ 9362185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_sysfs_in[X][3].dev_attr.attr, \ 9372185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck NULL \ 9382185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck} 9392185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck 9402185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeckstatic struct attribute *vt1211_in_attr[][5] = { 9412185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck IN_UNIT_ATTRS(0), 9422185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck IN_UNIT_ATTRS(1), 9432185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck IN_UNIT_ATTRS(2), 9442185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck IN_UNIT_ATTRS(3), 9452185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck IN_UNIT_ATTRS(4), 9462185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck IN_UNIT_ATTRS(5) 947ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 948ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 9492185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeckstatic const struct attribute_group vt1211_in_attr_group[] = { 9502185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_in_attr[0] }, 9512185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_in_attr[1] }, 9522185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_in_attr[2] }, 9532185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_in_attr[3] }, 9542185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_in_attr[4] }, 9552185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_in_attr[5] } 956ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 957ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 9582185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck#define SENSOR_ATTR_TEMP(ix) \ 9592185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck{ SENSOR_ATTR_2(temp##ix##_input, S_IRUGO, \ 9602185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_temp, NULL, SHOW_TEMP_INPUT, ix-1), \ 961ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \ 9622185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_temp, set_temp, SHOW_SET_TEMP_MAX, ix-1), \ 9632185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_2(temp##ix##_max_hyst, S_IRUGO | S_IWUSR, \ 9642185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_temp, set_temp, SHOW_SET_TEMP_MAX_HYST, ix-1), \ 9652185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_2(temp##ix##_alarm, S_IRUGO, \ 9662185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck show_temp, NULL, SHOW_TEMP_ALARM, ix-1) \ 9672185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck} 9682185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck 9692185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeckstatic struct sensor_device_attribute_2 vt1211_sysfs_temp[][4] = { 9702185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(1), 9712185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(2), 9722185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(3), 9732185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(4), 9742185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(5), 9752185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(6), 9762185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck SENSOR_ATTR_TEMP(7), 977ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 978ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 9792185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck#define TEMP_UNIT_ATTRS(X) \ 9802185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck{ &vt1211_sysfs_temp[X][0].dev_attr.attr, \ 9812185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_sysfs_temp[X][1].dev_attr.attr, \ 9822185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_sysfs_temp[X][2].dev_attr.attr, \ 9832185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_sysfs_temp[X][3].dev_attr.attr, \ 9842185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck NULL \ 9852185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck} 9862185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck 9872185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeckstatic struct attribute *vt1211_temp_attr[][5] = { 9882185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(0), 9892185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(1), 9902185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(2), 9912185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(3), 9922185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(4), 9932185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(5), 9942185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck TEMP_UNIT_ATTRS(6) 995ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 996ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 9972185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeckstatic const struct attribute_group vt1211_temp_attr_group[] = { 9982185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[0] }, 9992185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[1] }, 10002185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[2] }, 10012185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[3] }, 10022185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[4] }, 10032185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[5] }, 10042185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck { .attrs = vt1211_temp_attr[6] } 1005ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 1006ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1007ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_FAN(ix) \ 1008ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(fan##ix##_input, S_IRUGO, \ 1009ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_fan, NULL, SHOW_FAN_INPUT, ix-1), \ 1010ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ 1011ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_fan, set_fan, SHOW_SET_FAN_MIN, ix-1), \ 1012ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(fan##ix##_div, S_IRUGO | S_IWUSR, \ 1013ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_fan, set_fan, SHOW_SET_FAN_DIV, ix-1), \ 1014ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(fan##ix##_alarm, S_IRUGO, \ 1015ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_fan, NULL, SHOW_FAN_ALARM, ix-1) 1016ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1017ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM(ix) \ 1018ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix, S_IRUGO, \ 1019ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm, NULL, SHOW_PWM, ix-1), \ 1020ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_enable, S_IRUGO | S_IWUSR, \ 1021ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm, set_pwm, SHOW_SET_PWM_ENABLE, ix-1), \ 1022ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_auto_channels_temp, S_IRUGO | S_IWUSR, \ 1023ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm, set_pwm, SHOW_SET_PWM_AUTO_CHANNELS_TEMP, ix-1) 1024ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1025ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM_FREQ(ix) \ 1026ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \ 1027ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm, set_pwm, SHOW_SET_PWM_FREQ, ix-1) 1028ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1029ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM_FREQ_RO(ix) \ 1030ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO, \ 1031ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm, NULL, SHOW_SET_PWM_FREQ, ix-1) 1032ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1033ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP(ix, ap) \ 1034ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO | S_IWUSR, \ 1035ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm_auto_point_temp, set_pwm_auto_point_temp, \ 1036ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ap-1, ix-1) 1037ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1038ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(ix, ap) \ 1039ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO, \ 1040ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm_auto_point_temp, NULL, \ 1041ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ap-1, ix-1) 1042ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1043ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM_AUTO_POINT_PWM(ix, ap) \ 1044ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO | S_IWUSR, \ 1045ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm_auto_point_pwm, set_pwm_auto_point_pwm, \ 1046ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ap-1, ix-1) 1047ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1048ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger#define SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(ix, ap) \ 1049ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO, \ 1050ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger show_pwm_auto_point_pwm, NULL, \ 1051ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger ap-1, ix-1) 1052ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1053ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic struct sensor_device_attribute_2 vt1211_sysfs_fan_pwm[] = { 1054ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_FAN(1), 1055ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_FAN(2), 1056ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM(1), 1057ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM(2), 1058ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_FREQ(1), 1059ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_FREQ_RO(2), 1060ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 1), 1061ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 2), 1062ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 3), 1063ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 4), 1064ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 1), 1065ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 2), 1066ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 3), 1067ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 4), 1068ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 1), 1069ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 2), 1070ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 3), 1071ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 4), 1072ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 1), 1073ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 2), 1074ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 3), 1075ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 4), 1076ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 1077ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1078ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic struct device_attribute vt1211_sysfs_misc[] = { 1079ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger __ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm), 1080ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger __ATTR(cpu0_vid, S_IRUGO, show_vid, NULL), 1081ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger __ATTR(name, S_IRUGO, show_name, NULL), 1082ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger __ATTR(alarms, S_IRUGO, show_alarms, NULL), 1083ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 1084ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1085ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger/* --------------------------------------------------------------------- 1086ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * Device registration and initialization 1087ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * --------------------------------------------------------------------- */ 1088ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1089ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic void __devinit vt1211_init_device(struct vt1211_data *data) 1090ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1091ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* set VRM */ 1092ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->vrm = vid_which_vrm(); 1093ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1094ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Read (and initialize) UCH config */ 1095ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->uch_config = vt1211_read8(data, VT1211_REG_UCH_CONFIG); 1096ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (uch_config > -1) { 1097ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->uch_config = (data->uch_config & 0x83) | 1098ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger (uch_config << 2); 1099ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_UCH_CONFIG, data->uch_config); 1100ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1101ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1102b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck /* 1103b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * Initialize the interrupt mode (if request at module load time). 1104ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * The VT1211 implements 3 different modes for clearing interrupts: 1105ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 0: Clear INT when status register is read. Regenerate INT as long 1106ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * as temp stays above hysteresis limit. 1107ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1: Clear INT when status register is read. DON'T regenerate INT 1108ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * until temp falls below hysteresis limit and exceeds hot limit 1109ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * again. 1110ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 2: Clear INT when temp falls below max limit. 1111ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * 1112ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger * The driver only allows to force mode 0 since that's the only one 1113b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck * that makes sense for 'sensors' 1114b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck */ 1115ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (int_mode == 0) { 1116ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_TEMP1_CONFIG, 0); 1117ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_write8(data, VT1211_REG_TEMP2_CONFIG, 0); 1118ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1119ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1120ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Fill in some hard wired values into our data struct */ 1121ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[0][3] = 255; 1122ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->pwm_auto_pwm[1][3] = 255; 1123ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1124ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1125ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic void vt1211_remove_sysfs(struct platform_device *pdev) 1126ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1127ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device *dev = &pdev->dev; 1128ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int i; 1129ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 11302185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck for (i = 0; i < ARRAY_SIZE(vt1211_in_attr_group); i++) 11312185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck sysfs_remove_group(&dev->kobj, &vt1211_in_attr_group[i]); 11322185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck 11332185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck for (i = 0; i < ARRAY_SIZE(vt1211_temp_attr_group); i++) 11342185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck sysfs_remove_group(&dev->kobj, &vt1211_temp_attr_group[i]); 11352185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck 1136ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) { 1137ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger device_remove_file(dev, 1138ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger &vt1211_sysfs_fan_pwm[i].dev_attr); 1139ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1140b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) 1141ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger device_remove_file(dev, &vt1211_sysfs_misc[i]); 1142ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1143ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1144ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic int __devinit vt1211_probe(struct platform_device *pdev) 1145ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1146ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct device *dev = &pdev->dev; 1147ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data; 1148ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct resource *res; 1149ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int i, err; 1150ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1151b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL); 1152b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (!data) { 1153ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = -ENOMEM; 1154ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_err(dev, "Out of memory\n"); 1155ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 1156ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1157ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1158ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res = platform_get_resource(pdev, IORESOURCE_IO, 0); 115986855b0c1fd75338c67cabbf85d64d033612c47bJulia Lawall if (!request_region(res->start, resource_size(res), DRVNAME)) { 1160ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare err = -EBUSY; 1161ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", 1162ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare (unsigned long)res->start, (unsigned long)res->end); 1163ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare goto EXIT_KFREE; 1164ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare } 1165ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->addr = res->start; 1166ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger data->name = DRVNAME; 1167ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger mutex_init(&data->update_lock); 1168ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1169ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_set_drvdata(pdev, data); 1170ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1171ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Initialize the VT1211 chip */ 1172ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_init_device(data); 1173ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1174ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Create sysfs interface files */ 11752185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck for (i = 0; i < ARRAY_SIZE(vt1211_in_attr_group); i++) { 1176ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (ISVOLT(i, data->uch_config)) { 11772185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck err = sysfs_create_group(&dev->kobj, 11782185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_in_attr_group[i]); 11792185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck if (err) 1180ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_REMOVE; 1181ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1182ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 11832185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck for (i = 0; i < ARRAY_SIZE(vt1211_temp_attr_group); i++) { 1184ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (ISTEMP(i, data->uch_config)) { 11852185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck err = sysfs_create_group(&dev->kobj, 11862185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck &vt1211_temp_attr_group[i]); 11872185696d7d8a852146f6a901b35e9b94be43329aGuenter Roeck if (err) 1188ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_REMOVE; 1189ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1190ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1191ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) { 1192ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = device_create_file(dev, 1193ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger &vt1211_sysfs_fan_pwm[i].dev_attr); 1194b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 1195ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_REMOVE; 1196ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1197ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) { 1198ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = device_create_file(dev, 1199ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger &vt1211_sysfs_misc[i]); 1200b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 1201ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_REMOVE; 1202ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1203ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1204ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Register device */ 12051beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones data->hwmon_dev = hwmon_device_register(dev); 12061beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones if (IS_ERR(data->hwmon_dev)) { 12071beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones err = PTR_ERR(data->hwmon_dev); 1208ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_err(dev, "Class registration failed (%d)\n", err); 1209ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_REMOVE_SILENT; 1210ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1211ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1212ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return 0; 1213ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1214ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT_DEV_REMOVE: 1215ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger dev_err(dev, "Sysfs interface creation failed (%d)\n", err); 1216ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT_DEV_REMOVE_SILENT: 1217ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_remove_sysfs(pdev); 121886855b0c1fd75338c67cabbf85d64d033612c47bJulia Lawall release_region(res->start, resource_size(res)); 1219ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean DelvareEXIT_KFREE: 1220ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_set_drvdata(pdev, NULL); 1221ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger kfree(data); 1222ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT: 1223ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return err; 1224ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1225ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1226ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic int __devexit vt1211_remove(struct platform_device *pdev) 1227ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1228ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct vt1211_data *data = platform_get_drvdata(pdev); 1229ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare struct resource *res; 1230ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 12311beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones hwmon_device_unregister(data->hwmon_dev); 1232ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger vt1211_remove_sysfs(pdev); 1233ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_set_drvdata(pdev, NULL); 1234ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger kfree(data); 1235ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1236ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare res = platform_get_resource(pdev, IORESOURCE_IO, 0); 123786855b0c1fd75338c67cabbf85d64d033612c47bJulia Lawall release_region(res->start, resource_size(res)); 1238ce7ee4e80a72d3b1009ca232be8981de93c015f6Jean Delvare 1239ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return 0; 1240ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1241ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1242ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic struct platform_driver vt1211_driver = { 1243ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .driver = { 1244ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .owner = THIS_MODULE, 1245ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .name = DRVNAME, 1246ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger }, 1247ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .probe = vt1211_probe, 1248ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .remove = __devexit_p(vt1211_remove), 1249ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger}; 1250ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1251ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic int __init vt1211_device_add(unsigned short address) 1252ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1253ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger struct resource res = { 1254ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .start = address, 1255ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .end = address + 0x7f, 1256ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger .flags = IORESOURCE_IO, 1257ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger }; 1258ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int err; 1259ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1260ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger pdev = platform_device_alloc(DRVNAME, address); 1261ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (!pdev) { 1262ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = -ENOMEM; 12635ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_err("Device allocation failed (%d)\n", err); 1264ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 1265ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1266ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1267ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger res.name = pdev->name; 1268b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare err = acpi_check_resource_conflict(&res); 1269b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare if (err) 127018632f84fac770125c0982dfadec6b551e82144eHans de Goede goto EXIT_DEV_PUT; 1271b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare 1272ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = platform_device_add_resources(pdev, &res, 1); 1273ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (err) { 12745ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_err("Device resource addition failed (%d)\n", err); 1275ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_PUT; 1276ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1277ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1278ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = platform_device_add(pdev); 1279ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (err) { 12805ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_err("Device addition failed (%d)\n", err); 1281ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DEV_PUT; 1282ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1283ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1284ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return 0; 1285ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1286ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT_DEV_PUT: 1287ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_device_put(pdev); 1288ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT: 1289ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return err; 1290ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1291ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 12922219cd81a6cd186200606693b360c6429c003bb3Juerg Haefligerstatic int __init vt1211_find(int sio_cip, unsigned short *address) 1293ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1294ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int err = -ENODEV; 129567b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare int devid; 1296ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 12972219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger superio_enter(sio_cip); 1298ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 129967b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID); 1300b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (devid != SIO_VT1211_ID) 1301ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 1302ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 13032219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger superio_select(sio_cip, SIO_VT1211_LDN_HWMON); 1304ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 13052219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) { 13065ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_warn("HW monitor is disabled, skipping\n"); 1307ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 1308ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1309ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 13102219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) | 13112219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00; 1312ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if (*address == 0) { 13135ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_warn("Base address is not set, skipping\n"); 1314ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 1315ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1316ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1317ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = 0; 13185ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_info("Found VT1211 chip at 0x%04x, revision %u\n", 13195ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches *address, superio_inb(sio_cip, SIO_VT1211_DEVREV)); 1320ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1321ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT: 13222219cd81a6cd186200606693b360c6429c003bb3Juerg Haefliger superio_exit(sio_cip); 1323ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return err; 1324ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1325ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1326ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic int __init vt1211_init(void) 1327ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1328ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger int err; 1329ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger unsigned short address = 0; 1330ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1331b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = vt1211_find(SIO_REG_CIP1, &address); 1332b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) { 1333b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck err = vt1211_find(SIO_REG_CIP2, &address); 1334b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 1335b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck goto EXIT; 1336ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1337ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1338ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if ((uch_config < -1) || (uch_config > 31)) { 1339ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = -EINVAL; 13405ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_warn("Invalid UCH configuration %d. " 13415ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches "Choose a value between 0 and 31.\n", uch_config); 1342b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck goto EXIT; 1343ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1344ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1345ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger if ((int_mode < -1) || (int_mode > 0)) { 1346ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = -EINVAL; 13475ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches pr_warn("Invalid interrupt mode %d. " 13485ed9ba6b87545d21b48e50a028bfb79f9812f89fJoe Perches "Only mode 0 is supported.\n", int_mode); 1349b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck goto EXIT; 1350ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger } 1351ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1352ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = platform_driver_register(&vt1211_driver); 1353b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 1354ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT; 1355ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1356ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger /* Sets global pdev as a side effect */ 1357ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger err = vt1211_device_add(address); 1358b162c033480a7ba0433d329f56c142a0ab59049dGuenter Roeck if (err) 1359ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger goto EXIT_DRV_UNREGISTER; 1360ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1361ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return 0; 1362ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1363ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT_DRV_UNREGISTER: 1364ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_driver_unregister(&vt1211_driver); 1365ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerEXIT: 1366ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger return err; 1367ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1368ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1369ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligerstatic void __exit vt1211_exit(void) 1370ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger{ 1371ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_device_unregister(pdev); 1372ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger platform_driver_unregister(&vt1211_driver); 1373ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger} 1374ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1375ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerMODULE_AUTHOR("Juerg Haefliger <juergh@gmail.com>"); 1376ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerMODULE_DESCRIPTION("VT1211 sensors"); 1377ab41319eab3b5e600873dc77dff7756970424ca6Juerg HaefligerMODULE_LICENSE("GPL"); 1378ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefliger 1379ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligermodule_init(vt1211_init); 1380ab41319eab3b5e600873dc77dff7756970424ca6Juerg Haefligermodule_exit(vt1211_exit); 1381