1*08426edaSThilo Cestonaro /* 2*08426edaSThilo Cestonaro * Support for the FTS Systemmonitoring Chip "Teutates" 3*08426edaSThilo Cestonaro * 4*08426edaSThilo Cestonaro * Copyright (C) 2016 Fujitsu Technology Solutions GmbH, 5*08426edaSThilo Cestonaro * Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com> 6*08426edaSThilo Cestonaro * 7*08426edaSThilo Cestonaro * This program is free software; you can redistribute it and/or modify 8*08426edaSThilo Cestonaro * it under the terms of the GNU General Public License as published by 9*08426edaSThilo Cestonaro * the Free Software Foundation; either version 2 of the License, or 10*08426edaSThilo Cestonaro * (at your option) any later version. 11*08426edaSThilo Cestonaro * 12*08426edaSThilo Cestonaro * This program is distributed in the hope that it will be useful, 13*08426edaSThilo Cestonaro * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*08426edaSThilo Cestonaro * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*08426edaSThilo Cestonaro * GNU General Public License for more details. 16*08426edaSThilo Cestonaro * 17*08426edaSThilo Cestonaro */ 18*08426edaSThilo Cestonaro #include <linux/err.h> 19*08426edaSThilo Cestonaro #include <linux/fs.h> 20*08426edaSThilo Cestonaro #include <linux/hwmon.h> 21*08426edaSThilo Cestonaro #include <linux/hwmon-sysfs.h> 22*08426edaSThilo Cestonaro #include <linux/i2c.h> 23*08426edaSThilo Cestonaro #include <linux/init.h> 24*08426edaSThilo Cestonaro #include <linux/jiffies.h> 25*08426edaSThilo Cestonaro #include <linux/module.h> 26*08426edaSThilo Cestonaro #include <linux/mutex.h> 27*08426edaSThilo Cestonaro #include <linux/slab.h> 28*08426edaSThilo Cestonaro #include <linux/sysfs.h> 29*08426edaSThilo Cestonaro #include <linux/uaccess.h> 30*08426edaSThilo Cestonaro #include <linux/version.h> 31*08426edaSThilo Cestonaro #include <linux/watchdog.h> 32*08426edaSThilo Cestonaro 33*08426edaSThilo Cestonaro #define FTS_DEVICE_ID_REG 0x0000 34*08426edaSThilo Cestonaro #define FTS_DEVICE_REVISION_REG 0x0001 35*08426edaSThilo Cestonaro #define FTS_DEVICE_STATUS_REG 0x0004 36*08426edaSThilo Cestonaro #define FTS_SATELLITE_STATUS_REG 0x0005 37*08426edaSThilo Cestonaro #define FTS_EVENT_STATUS_REG 0x0006 38*08426edaSThilo Cestonaro #define FTS_GLOBAL_CONTROL_REG 0x0007 39*08426edaSThilo Cestonaro 40*08426edaSThilo Cestonaro #define FTS_SENSOR_EVENT_REG 0x0010 41*08426edaSThilo Cestonaro 42*08426edaSThilo Cestonaro #define FTS_FAN_EVENT_REG 0x0014 43*08426edaSThilo Cestonaro #define FTS_FAN_PRESENT_REG 0x0015 44*08426edaSThilo Cestonaro 45*08426edaSThilo Cestonaro #define FTS_POWER_ON_TIME_COUNTER_A 0x007A 46*08426edaSThilo Cestonaro #define FTS_POWER_ON_TIME_COUNTER_B 0x007B 47*08426edaSThilo Cestonaro #define FTS_POWER_ON_TIME_COUNTER_C 0x007C 48*08426edaSThilo Cestonaro 49*08426edaSThilo Cestonaro #define FTS_PAGE_SELECT_REG 0x007F 50*08426edaSThilo Cestonaro 51*08426edaSThilo Cestonaro #define FTS_WATCHDOG_TIME_PRESET 0x000B 52*08426edaSThilo Cestonaro #define FTS_WATCHDOG_CONTROL 0x5081 53*08426edaSThilo Cestonaro 54*08426edaSThilo Cestonaro #define FTS_NO_FAN_SENSORS 0x08 55*08426edaSThilo Cestonaro #define FTS_NO_TEMP_SENSORS 0x10 56*08426edaSThilo Cestonaro #define FTS_NO_VOLT_SENSORS 0x04 57*08426edaSThilo Cestonaro 58*08426edaSThilo Cestonaro static struct i2c_device_id fts_id[] = { 59*08426edaSThilo Cestonaro { "ftsteutates", 0 }, 60*08426edaSThilo Cestonaro { } 61*08426edaSThilo Cestonaro }; 62*08426edaSThilo Cestonaro MODULE_DEVICE_TABLE(i2c, fts_id); 63*08426edaSThilo Cestonaro 64*08426edaSThilo Cestonaro enum WATCHDOG_RESOLUTION { 65*08426edaSThilo Cestonaro seconds = 1, 66*08426edaSThilo Cestonaro minutes = 60 67*08426edaSThilo Cestonaro }; 68*08426edaSThilo Cestonaro 69*08426edaSThilo Cestonaro struct fts_data { 70*08426edaSThilo Cestonaro struct i2c_client *client; 71*08426edaSThilo Cestonaro /* update sensor data lock */ 72*08426edaSThilo Cestonaro struct mutex update_lock; 73*08426edaSThilo Cestonaro /* read/write register lock */ 74*08426edaSThilo Cestonaro struct mutex access_lock; 75*08426edaSThilo Cestonaro unsigned long last_updated; /* in jiffies */ 76*08426edaSThilo Cestonaro struct watchdog_device wdd; 77*08426edaSThilo Cestonaro enum WATCHDOG_RESOLUTION resolution; 78*08426edaSThilo Cestonaro bool valid; /* false until following fields are valid */ 79*08426edaSThilo Cestonaro 80*08426edaSThilo Cestonaro u8 volt[FTS_NO_VOLT_SENSORS]; 81*08426edaSThilo Cestonaro 82*08426edaSThilo Cestonaro u8 temp_input[FTS_NO_TEMP_SENSORS]; 83*08426edaSThilo Cestonaro u8 temp_alarm; 84*08426edaSThilo Cestonaro 85*08426edaSThilo Cestonaro u8 fan_present; 86*08426edaSThilo Cestonaro u8 fan_input[FTS_NO_FAN_SENSORS]; /* in rps */ 87*08426edaSThilo Cestonaro u8 fan_source[FTS_NO_FAN_SENSORS]; 88*08426edaSThilo Cestonaro u8 fan_alarm; 89*08426edaSThilo Cestonaro }; 90*08426edaSThilo Cestonaro 91*08426edaSThilo Cestonaro #define FTS_REG_FAN_INPUT(idx) ((idx) + 0x20) 92*08426edaSThilo Cestonaro #define FTS_REG_FAN_SOURCE(idx) ((idx) + 0x30) 93*08426edaSThilo Cestonaro #define FTS_REG_FAN_CONTROL(idx) (((idx) << 16) + 0x4881) 94*08426edaSThilo Cestonaro 95*08426edaSThilo Cestonaro #define FTS_REG_TEMP_INPUT(idx) ((idx) + 0x40) 96*08426edaSThilo Cestonaro #define FTS_REG_TEMP_CONTROL(idx) (((idx) << 16) + 0x0681) 97*08426edaSThilo Cestonaro 98*08426edaSThilo Cestonaro #define FTS_REG_VOLT(idx) ((idx) + 0x18) 99*08426edaSThilo Cestonaro 100*08426edaSThilo Cestonaro /*****************************************************************************/ 101*08426edaSThilo Cestonaro /* I2C Helper functions */ 102*08426edaSThilo Cestonaro /*****************************************************************************/ 103*08426edaSThilo Cestonaro static int fts_read_byte(struct i2c_client *client, unsigned short reg) 104*08426edaSThilo Cestonaro { 105*08426edaSThilo Cestonaro int ret; 106*08426edaSThilo Cestonaro unsigned char page = reg >> 8; 107*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(&client->dev); 108*08426edaSThilo Cestonaro 109*08426edaSThilo Cestonaro mutex_lock(&data->access_lock); 110*08426edaSThilo Cestonaro 111*08426edaSThilo Cestonaro dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page); 112*08426edaSThilo Cestonaro ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page); 113*08426edaSThilo Cestonaro if (ret < 0) 114*08426edaSThilo Cestonaro goto error; 115*08426edaSThilo Cestonaro 116*08426edaSThilo Cestonaro reg &= 0xFF; 117*08426edaSThilo Cestonaro ret = i2c_smbus_read_byte_data(client, reg); 118*08426edaSThilo Cestonaro dev_dbg(&client->dev, "read - reg: 0x%.02x: val: 0x%.02x\n", reg, ret); 119*08426edaSThilo Cestonaro 120*08426edaSThilo Cestonaro error: 121*08426edaSThilo Cestonaro mutex_unlock(&data->access_lock); 122*08426edaSThilo Cestonaro return ret; 123*08426edaSThilo Cestonaro } 124*08426edaSThilo Cestonaro 125*08426edaSThilo Cestonaro static int fts_write_byte(struct i2c_client *client, unsigned short reg, 126*08426edaSThilo Cestonaro unsigned char value) 127*08426edaSThilo Cestonaro { 128*08426edaSThilo Cestonaro int ret; 129*08426edaSThilo Cestonaro unsigned char page = reg >> 8; 130*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(&client->dev); 131*08426edaSThilo Cestonaro 132*08426edaSThilo Cestonaro mutex_lock(&data->access_lock); 133*08426edaSThilo Cestonaro 134*08426edaSThilo Cestonaro dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page); 135*08426edaSThilo Cestonaro ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page); 136*08426edaSThilo Cestonaro if (ret < 0) 137*08426edaSThilo Cestonaro goto error; 138*08426edaSThilo Cestonaro 139*08426edaSThilo Cestonaro reg &= 0xFF; 140*08426edaSThilo Cestonaro dev_dbg(&client->dev, 141*08426edaSThilo Cestonaro "write - reg: 0x%.02x: val: 0x%.02x\n", reg, value); 142*08426edaSThilo Cestonaro ret = i2c_smbus_write_byte_data(client, reg, value); 143*08426edaSThilo Cestonaro 144*08426edaSThilo Cestonaro error: 145*08426edaSThilo Cestonaro mutex_unlock(&data->access_lock); 146*08426edaSThilo Cestonaro return ret; 147*08426edaSThilo Cestonaro } 148*08426edaSThilo Cestonaro 149*08426edaSThilo Cestonaro /*****************************************************************************/ 150*08426edaSThilo Cestonaro /* Data Updater Helper function */ 151*08426edaSThilo Cestonaro /*****************************************************************************/ 152*08426edaSThilo Cestonaro static int fts_update_device(struct fts_data *data) 153*08426edaSThilo Cestonaro { 154*08426edaSThilo Cestonaro int i; 155*08426edaSThilo Cestonaro int err = 0; 156*08426edaSThilo Cestonaro 157*08426edaSThilo Cestonaro mutex_lock(&data->update_lock); 158*08426edaSThilo Cestonaro if (!time_after(jiffies, data->last_updated + 2 * HZ) && data->valid) 159*08426edaSThilo Cestonaro goto exit; 160*08426edaSThilo Cestonaro 161*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_DEVICE_STATUS_REG); 162*08426edaSThilo Cestonaro if (err < 0) 163*08426edaSThilo Cestonaro goto exit; 164*08426edaSThilo Cestonaro 165*08426edaSThilo Cestonaro data->valid = !!(err & 0x02); /* Data not ready yet */ 166*08426edaSThilo Cestonaro if (unlikely(!data->valid)) { 167*08426edaSThilo Cestonaro err = -EAGAIN; 168*08426edaSThilo Cestonaro goto exit; 169*08426edaSThilo Cestonaro } 170*08426edaSThilo Cestonaro 171*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_FAN_PRESENT_REG); 172*08426edaSThilo Cestonaro if (err < 0) 173*08426edaSThilo Cestonaro goto exit; 174*08426edaSThilo Cestonaro data->fan_present = err; 175*08426edaSThilo Cestonaro 176*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_FAN_EVENT_REG); 177*08426edaSThilo Cestonaro if (err < 0) 178*08426edaSThilo Cestonaro goto exit; 179*08426edaSThilo Cestonaro data->fan_alarm = err; 180*08426edaSThilo Cestonaro 181*08426edaSThilo Cestonaro for (i = 0; i < FTS_NO_FAN_SENSORS; i++) { 182*08426edaSThilo Cestonaro if (data->fan_present & BIT(i)) { 183*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_REG_FAN_INPUT(i)); 184*08426edaSThilo Cestonaro if (err < 0) 185*08426edaSThilo Cestonaro goto exit; 186*08426edaSThilo Cestonaro data->fan_input[i] = err; 187*08426edaSThilo Cestonaro 188*08426edaSThilo Cestonaro err = fts_read_byte(data->client, 189*08426edaSThilo Cestonaro FTS_REG_FAN_SOURCE(i)); 190*08426edaSThilo Cestonaro if (err < 0) 191*08426edaSThilo Cestonaro goto exit; 192*08426edaSThilo Cestonaro data->fan_source[i] = err; 193*08426edaSThilo Cestonaro } else { 194*08426edaSThilo Cestonaro data->fan_input[i] = 0; 195*08426edaSThilo Cestonaro data->fan_source[i] = 0; 196*08426edaSThilo Cestonaro } 197*08426edaSThilo Cestonaro } 198*08426edaSThilo Cestonaro 199*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_SENSOR_EVENT_REG); 200*08426edaSThilo Cestonaro if (err < 0) 201*08426edaSThilo Cestonaro goto exit; 202*08426edaSThilo Cestonaro data->temp_alarm = err; 203*08426edaSThilo Cestonaro 204*08426edaSThilo Cestonaro for (i = 0; i < FTS_NO_TEMP_SENSORS; i++) { 205*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_REG_TEMP_INPUT(i)); 206*08426edaSThilo Cestonaro if (err < 0) 207*08426edaSThilo Cestonaro goto exit; 208*08426edaSThilo Cestonaro data->temp_input[i] = err; 209*08426edaSThilo Cestonaro } 210*08426edaSThilo Cestonaro 211*08426edaSThilo Cestonaro for (i = 0; i < FTS_NO_VOLT_SENSORS; i++) { 212*08426edaSThilo Cestonaro err = fts_read_byte(data->client, FTS_REG_VOLT(i)); 213*08426edaSThilo Cestonaro if (err < 0) 214*08426edaSThilo Cestonaro goto exit; 215*08426edaSThilo Cestonaro data->volt[i] = err; 216*08426edaSThilo Cestonaro } 217*08426edaSThilo Cestonaro data->last_updated = jiffies; 218*08426edaSThilo Cestonaro err = 0; 219*08426edaSThilo Cestonaro exit: 220*08426edaSThilo Cestonaro mutex_unlock(&data->update_lock); 221*08426edaSThilo Cestonaro return err; 222*08426edaSThilo Cestonaro } 223*08426edaSThilo Cestonaro 224*08426edaSThilo Cestonaro /*****************************************************************************/ 225*08426edaSThilo Cestonaro /* Watchdog functions */ 226*08426edaSThilo Cestonaro /*****************************************************************************/ 227*08426edaSThilo Cestonaro static int fts_wd_set_resolution(struct fts_data *data, 228*08426edaSThilo Cestonaro enum WATCHDOG_RESOLUTION resolution) 229*08426edaSThilo Cestonaro { 230*08426edaSThilo Cestonaro int ret; 231*08426edaSThilo Cestonaro 232*08426edaSThilo Cestonaro if (data->resolution == resolution) 233*08426edaSThilo Cestonaro return 0; 234*08426edaSThilo Cestonaro 235*08426edaSThilo Cestonaro ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL); 236*08426edaSThilo Cestonaro if (ret < 0) 237*08426edaSThilo Cestonaro return ret; 238*08426edaSThilo Cestonaro 239*08426edaSThilo Cestonaro if ((resolution == seconds && ret & BIT(1)) || 240*08426edaSThilo Cestonaro (resolution == minutes && (ret & BIT(1)) == 0)) { 241*08426edaSThilo Cestonaro data->resolution = resolution; 242*08426edaSThilo Cestonaro return 0; 243*08426edaSThilo Cestonaro } 244*08426edaSThilo Cestonaro 245*08426edaSThilo Cestonaro if (resolution == seconds) 246*08426edaSThilo Cestonaro set_bit(1, (unsigned long *)&ret); 247*08426edaSThilo Cestonaro else 248*08426edaSThilo Cestonaro ret &= ~BIT(1); 249*08426edaSThilo Cestonaro 250*08426edaSThilo Cestonaro ret = fts_write_byte(data->client, FTS_WATCHDOG_CONTROL, ret); 251*08426edaSThilo Cestonaro if (ret < 0) 252*08426edaSThilo Cestonaro return ret; 253*08426edaSThilo Cestonaro 254*08426edaSThilo Cestonaro data->resolution = resolution; 255*08426edaSThilo Cestonaro return ret; 256*08426edaSThilo Cestonaro } 257*08426edaSThilo Cestonaro 258*08426edaSThilo Cestonaro static int fts_wd_set_timeout(struct watchdog_device *wdd, unsigned int timeout) 259*08426edaSThilo Cestonaro { 260*08426edaSThilo Cestonaro struct fts_data *data; 261*08426edaSThilo Cestonaro enum WATCHDOG_RESOLUTION resolution = seconds; 262*08426edaSThilo Cestonaro int ret; 263*08426edaSThilo Cestonaro 264*08426edaSThilo Cestonaro data = watchdog_get_drvdata(wdd); 265*08426edaSThilo Cestonaro /* switch watchdog resolution to minutes if timeout does not fit 266*08426edaSThilo Cestonaro * into a byte 267*08426edaSThilo Cestonaro */ 268*08426edaSThilo Cestonaro if (timeout > 0xFF) { 269*08426edaSThilo Cestonaro timeout = DIV_ROUND_UP(timeout, 60) * 60; 270*08426edaSThilo Cestonaro resolution = minutes; 271*08426edaSThilo Cestonaro } 272*08426edaSThilo Cestonaro 273*08426edaSThilo Cestonaro ret = fts_wd_set_resolution(data, resolution); 274*08426edaSThilo Cestonaro if (ret < 0) 275*08426edaSThilo Cestonaro return ret; 276*08426edaSThilo Cestonaro 277*08426edaSThilo Cestonaro wdd->timeout = timeout; 278*08426edaSThilo Cestonaro return 0; 279*08426edaSThilo Cestonaro } 280*08426edaSThilo Cestonaro 281*08426edaSThilo Cestonaro static int fts_wd_start(struct watchdog_device *wdd) 282*08426edaSThilo Cestonaro { 283*08426edaSThilo Cestonaro struct fts_data *data = watchdog_get_drvdata(wdd); 284*08426edaSThilo Cestonaro 285*08426edaSThilo Cestonaro return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET, 286*08426edaSThilo Cestonaro wdd->timeout / (u8)data->resolution); 287*08426edaSThilo Cestonaro } 288*08426edaSThilo Cestonaro 289*08426edaSThilo Cestonaro static int fts_wd_stop(struct watchdog_device *wdd) 290*08426edaSThilo Cestonaro { 291*08426edaSThilo Cestonaro struct fts_data *data; 292*08426edaSThilo Cestonaro 293*08426edaSThilo Cestonaro data = watchdog_get_drvdata(wdd); 294*08426edaSThilo Cestonaro return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET, 0); 295*08426edaSThilo Cestonaro } 296*08426edaSThilo Cestonaro 297*08426edaSThilo Cestonaro static const struct watchdog_info fts_wd_info = { 298*08426edaSThilo Cestonaro .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 299*08426edaSThilo Cestonaro .identity = "FTS Teutates Hardware Watchdog", 300*08426edaSThilo Cestonaro }; 301*08426edaSThilo Cestonaro 302*08426edaSThilo Cestonaro static const struct watchdog_ops fts_wd_ops = { 303*08426edaSThilo Cestonaro .owner = THIS_MODULE, 304*08426edaSThilo Cestonaro .start = fts_wd_start, 305*08426edaSThilo Cestonaro .stop = fts_wd_stop, 306*08426edaSThilo Cestonaro .set_timeout = fts_wd_set_timeout, 307*08426edaSThilo Cestonaro }; 308*08426edaSThilo Cestonaro 309*08426edaSThilo Cestonaro static int fts_watchdog_init(struct fts_data *data) 310*08426edaSThilo Cestonaro { 311*08426edaSThilo Cestonaro int timeout, ret; 312*08426edaSThilo Cestonaro 313*08426edaSThilo Cestonaro watchdog_set_drvdata(&data->wdd, data); 314*08426edaSThilo Cestonaro 315*08426edaSThilo Cestonaro timeout = fts_read_byte(data->client, FTS_WATCHDOG_TIME_PRESET); 316*08426edaSThilo Cestonaro if (timeout < 0) 317*08426edaSThilo Cestonaro return timeout; 318*08426edaSThilo Cestonaro 319*08426edaSThilo Cestonaro /* watchdog not running, set timeout to a default of 60 sec. */ 320*08426edaSThilo Cestonaro if (timeout == 0) { 321*08426edaSThilo Cestonaro ret = fts_wd_set_resolution(data, seconds); 322*08426edaSThilo Cestonaro if (ret < 0) 323*08426edaSThilo Cestonaro return ret; 324*08426edaSThilo Cestonaro data->wdd.timeout = 60; 325*08426edaSThilo Cestonaro } else { 326*08426edaSThilo Cestonaro ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL); 327*08426edaSThilo Cestonaro if (ret < 0) 328*08426edaSThilo Cestonaro return ret; 329*08426edaSThilo Cestonaro 330*08426edaSThilo Cestonaro data->resolution = ret & BIT(1) ? seconds : minutes; 331*08426edaSThilo Cestonaro data->wdd.timeout = timeout * (u8)data->resolution; 332*08426edaSThilo Cestonaro set_bit(WDOG_HW_RUNNING, &data->wdd.status); 333*08426edaSThilo Cestonaro } 334*08426edaSThilo Cestonaro 335*08426edaSThilo Cestonaro /* Register our watchdog part */ 336*08426edaSThilo Cestonaro data->wdd.info = &fts_wd_info; 337*08426edaSThilo Cestonaro data->wdd.ops = &fts_wd_ops; 338*08426edaSThilo Cestonaro data->wdd.parent = &data->client->dev; 339*08426edaSThilo Cestonaro data->wdd.min_timeout = 1; 340*08426edaSThilo Cestonaro 341*08426edaSThilo Cestonaro /* max timeout 255 minutes. */ 342*08426edaSThilo Cestonaro data->wdd.max_hw_heartbeat_ms = 0xFF * 60 * MSEC_PER_SEC; 343*08426edaSThilo Cestonaro 344*08426edaSThilo Cestonaro return watchdog_register_device(&data->wdd); 345*08426edaSThilo Cestonaro } 346*08426edaSThilo Cestonaro 347*08426edaSThilo Cestonaro /*****************************************************************************/ 348*08426edaSThilo Cestonaro /* SysFS handler functions */ 349*08426edaSThilo Cestonaro /*****************************************************************************/ 350*08426edaSThilo Cestonaro static ssize_t show_in_value(struct device *dev, 351*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 352*08426edaSThilo Cestonaro { 353*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 354*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 355*08426edaSThilo Cestonaro int err; 356*08426edaSThilo Cestonaro 357*08426edaSThilo Cestonaro err = fts_update_device(data); 358*08426edaSThilo Cestonaro if (err < 0) 359*08426edaSThilo Cestonaro return err; 360*08426edaSThilo Cestonaro 361*08426edaSThilo Cestonaro return sprintf(buf, "%u\n", data->volt[index]); 362*08426edaSThilo Cestonaro } 363*08426edaSThilo Cestonaro 364*08426edaSThilo Cestonaro static ssize_t show_temp_value(struct device *dev, 365*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 366*08426edaSThilo Cestonaro { 367*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 368*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 369*08426edaSThilo Cestonaro int err; 370*08426edaSThilo Cestonaro 371*08426edaSThilo Cestonaro err = fts_update_device(data); 372*08426edaSThilo Cestonaro if (err < 0) 373*08426edaSThilo Cestonaro return err; 374*08426edaSThilo Cestonaro 375*08426edaSThilo Cestonaro return sprintf(buf, "%u\n", data->temp_input[index]); 376*08426edaSThilo Cestonaro } 377*08426edaSThilo Cestonaro 378*08426edaSThilo Cestonaro static ssize_t show_temp_fault(struct device *dev, 379*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 380*08426edaSThilo Cestonaro { 381*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 382*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 383*08426edaSThilo Cestonaro int err; 384*08426edaSThilo Cestonaro 385*08426edaSThilo Cestonaro err = fts_update_device(data); 386*08426edaSThilo Cestonaro if (err < 0) 387*08426edaSThilo Cestonaro return err; 388*08426edaSThilo Cestonaro 389*08426edaSThilo Cestonaro /* 00h Temperature = Sensor Error */ 390*08426edaSThilo Cestonaro return sprintf(buf, "%d\n", data->temp_input[index] == 0); 391*08426edaSThilo Cestonaro } 392*08426edaSThilo Cestonaro 393*08426edaSThilo Cestonaro static ssize_t show_temp_alarm(struct device *dev, 394*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 395*08426edaSThilo Cestonaro { 396*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 397*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 398*08426edaSThilo Cestonaro int err; 399*08426edaSThilo Cestonaro 400*08426edaSThilo Cestonaro err = fts_update_device(data); 401*08426edaSThilo Cestonaro if (err < 0) 402*08426edaSThilo Cestonaro return err; 403*08426edaSThilo Cestonaro 404*08426edaSThilo Cestonaro return sprintf(buf, "%u\n", !!(data->temp_alarm & BIT(index))); 405*08426edaSThilo Cestonaro } 406*08426edaSThilo Cestonaro 407*08426edaSThilo Cestonaro static ssize_t 408*08426edaSThilo Cestonaro clear_temp_alarm(struct device *dev, struct device_attribute *devattr, 409*08426edaSThilo Cestonaro const char *buf, size_t count) 410*08426edaSThilo Cestonaro { 411*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 412*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 413*08426edaSThilo Cestonaro long ret; 414*08426edaSThilo Cestonaro 415*08426edaSThilo Cestonaro ret = fts_update_device(data); 416*08426edaSThilo Cestonaro if (ret < 0) 417*08426edaSThilo Cestonaro return ret; 418*08426edaSThilo Cestonaro 419*08426edaSThilo Cestonaro if (kstrtoul(buf, 10, &ret) || ret != 0) 420*08426edaSThilo Cestonaro return -EINVAL; 421*08426edaSThilo Cestonaro 422*08426edaSThilo Cestonaro mutex_lock(&data->update_lock); 423*08426edaSThilo Cestonaro ret = fts_read_byte(data->client, FTS_REG_TEMP_CONTROL(index)); 424*08426edaSThilo Cestonaro if (ret < 0) 425*08426edaSThilo Cestonaro goto error; 426*08426edaSThilo Cestonaro 427*08426edaSThilo Cestonaro ret = fts_write_byte(data->client, FTS_REG_TEMP_CONTROL(index), 428*08426edaSThilo Cestonaro ret | 0x1); 429*08426edaSThilo Cestonaro if (ret < 0) 430*08426edaSThilo Cestonaro goto error; 431*08426edaSThilo Cestonaro 432*08426edaSThilo Cestonaro data->valid = false; 433*08426edaSThilo Cestonaro error: 434*08426edaSThilo Cestonaro mutex_unlock(&data->update_lock); 435*08426edaSThilo Cestonaro return ret; 436*08426edaSThilo Cestonaro } 437*08426edaSThilo Cestonaro 438*08426edaSThilo Cestonaro static ssize_t show_fan_value(struct device *dev, 439*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 440*08426edaSThilo Cestonaro { 441*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 442*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 443*08426edaSThilo Cestonaro int err; 444*08426edaSThilo Cestonaro 445*08426edaSThilo Cestonaro err = fts_update_device(data); 446*08426edaSThilo Cestonaro if (err < 0) 447*08426edaSThilo Cestonaro return err; 448*08426edaSThilo Cestonaro 449*08426edaSThilo Cestonaro return sprintf(buf, "%u\n", data->fan_input[index]); 450*08426edaSThilo Cestonaro } 451*08426edaSThilo Cestonaro 452*08426edaSThilo Cestonaro static ssize_t show_fan_source(struct device *dev, 453*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 454*08426edaSThilo Cestonaro { 455*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 456*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 457*08426edaSThilo Cestonaro int err; 458*08426edaSThilo Cestonaro 459*08426edaSThilo Cestonaro err = fts_update_device(data); 460*08426edaSThilo Cestonaro if (err < 0) 461*08426edaSThilo Cestonaro return err; 462*08426edaSThilo Cestonaro 463*08426edaSThilo Cestonaro return sprintf(buf, "%u\n", data->fan_source[index]); 464*08426edaSThilo Cestonaro } 465*08426edaSThilo Cestonaro 466*08426edaSThilo Cestonaro static ssize_t show_fan_alarm(struct device *dev, 467*08426edaSThilo Cestonaro struct device_attribute *devattr, char *buf) 468*08426edaSThilo Cestonaro { 469*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 470*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 471*08426edaSThilo Cestonaro int err; 472*08426edaSThilo Cestonaro 473*08426edaSThilo Cestonaro err = fts_update_device(data); 474*08426edaSThilo Cestonaro if (err < 0) 475*08426edaSThilo Cestonaro return err; 476*08426edaSThilo Cestonaro 477*08426edaSThilo Cestonaro return sprintf(buf, "%d\n", !!(data->fan_alarm & BIT(index))); 478*08426edaSThilo Cestonaro } 479*08426edaSThilo Cestonaro 480*08426edaSThilo Cestonaro static ssize_t 481*08426edaSThilo Cestonaro clear_fan_alarm(struct device *dev, struct device_attribute *devattr, 482*08426edaSThilo Cestonaro const char *buf, size_t count) 483*08426edaSThilo Cestonaro { 484*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(dev); 485*08426edaSThilo Cestonaro int index = to_sensor_dev_attr(devattr)->index; 486*08426edaSThilo Cestonaro long ret; 487*08426edaSThilo Cestonaro 488*08426edaSThilo Cestonaro ret = fts_update_device(data); 489*08426edaSThilo Cestonaro if (ret < 0) 490*08426edaSThilo Cestonaro return ret; 491*08426edaSThilo Cestonaro 492*08426edaSThilo Cestonaro if (kstrtoul(buf, 10, &ret) || ret != 0) 493*08426edaSThilo Cestonaro return -EINVAL; 494*08426edaSThilo Cestonaro 495*08426edaSThilo Cestonaro mutex_lock(&data->update_lock); 496*08426edaSThilo Cestonaro ret = fts_read_byte(data->client, FTS_REG_FAN_CONTROL(index)); 497*08426edaSThilo Cestonaro if (ret < 0) 498*08426edaSThilo Cestonaro goto error; 499*08426edaSThilo Cestonaro 500*08426edaSThilo Cestonaro ret = fts_write_byte(data->client, FTS_REG_FAN_CONTROL(index), 501*08426edaSThilo Cestonaro ret | 0x1); 502*08426edaSThilo Cestonaro if (ret < 0) 503*08426edaSThilo Cestonaro goto error; 504*08426edaSThilo Cestonaro 505*08426edaSThilo Cestonaro data->valid = false; 506*08426edaSThilo Cestonaro error: 507*08426edaSThilo Cestonaro mutex_unlock(&data->update_lock); 508*08426edaSThilo Cestonaro return ret; 509*08426edaSThilo Cestonaro } 510*08426edaSThilo Cestonaro 511*08426edaSThilo Cestonaro /*****************************************************************************/ 512*08426edaSThilo Cestonaro /* SysFS structs */ 513*08426edaSThilo Cestonaro /*****************************************************************************/ 514*08426edaSThilo Cestonaro 515*08426edaSThilo Cestonaro /* Temprature sensors */ 516*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0); 517*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1); 518*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2); 519*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3); 520*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_value, NULL, 4); 521*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_value, NULL, 5); 522*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_value, NULL, 6); 523*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_value, NULL, 7); 524*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp_value, NULL, 8); 525*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp_value, NULL, 9); 526*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_temp_value, NULL, 10); 527*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_temp_value, NULL, 11); 528*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, show_temp_value, NULL, 12); 529*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, show_temp_value, NULL, 13); 530*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, show_temp_value, NULL, 14); 531*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, show_temp_value, NULL, 15); 532*08426edaSThilo Cestonaro 533*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); 534*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); 535*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); 536*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); 537*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); 538*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); 539*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6); 540*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7); 541*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp9_fault, S_IRUGO, show_temp_fault, NULL, 8); 542*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp10_fault, S_IRUGO, show_temp_fault, NULL, 9); 543*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp11_fault, S_IRUGO, show_temp_fault, NULL, 10); 544*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp12_fault, S_IRUGO, show_temp_fault, NULL, 11); 545*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp13_fault, S_IRUGO, show_temp_fault, NULL, 12); 546*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp14_fault, S_IRUGO, show_temp_fault, NULL, 13); 547*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp15_fault, S_IRUGO, show_temp_fault, NULL, 14); 548*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp16_fault, S_IRUGO, show_temp_fault, NULL, 15); 549*08426edaSThilo Cestonaro 550*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 551*08426edaSThilo Cestonaro clear_temp_alarm, 0); 552*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 553*08426edaSThilo Cestonaro clear_temp_alarm, 1); 554*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 555*08426edaSThilo Cestonaro clear_temp_alarm, 2); 556*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 557*08426edaSThilo Cestonaro clear_temp_alarm, 3); 558*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 559*08426edaSThilo Cestonaro clear_temp_alarm, 4); 560*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 561*08426edaSThilo Cestonaro clear_temp_alarm, 5); 562*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 563*08426edaSThilo Cestonaro clear_temp_alarm, 6); 564*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 565*08426edaSThilo Cestonaro clear_temp_alarm, 7); 566*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 567*08426edaSThilo Cestonaro clear_temp_alarm, 8); 568*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 569*08426edaSThilo Cestonaro clear_temp_alarm, 9); 570*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp11_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 571*08426edaSThilo Cestonaro clear_temp_alarm, 10); 572*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp12_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 573*08426edaSThilo Cestonaro clear_temp_alarm, 11); 574*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp13_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 575*08426edaSThilo Cestonaro clear_temp_alarm, 12); 576*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp14_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 577*08426edaSThilo Cestonaro clear_temp_alarm, 13); 578*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp15_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 579*08426edaSThilo Cestonaro clear_temp_alarm, 14); 580*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(temp16_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, 581*08426edaSThilo Cestonaro clear_temp_alarm, 15); 582*08426edaSThilo Cestonaro 583*08426edaSThilo Cestonaro static struct attribute *fts_temp_attrs[] = { 584*08426edaSThilo Cestonaro &sensor_dev_attr_temp1_input.dev_attr.attr, 585*08426edaSThilo Cestonaro &sensor_dev_attr_temp2_input.dev_attr.attr, 586*08426edaSThilo Cestonaro &sensor_dev_attr_temp3_input.dev_attr.attr, 587*08426edaSThilo Cestonaro &sensor_dev_attr_temp4_input.dev_attr.attr, 588*08426edaSThilo Cestonaro &sensor_dev_attr_temp5_input.dev_attr.attr, 589*08426edaSThilo Cestonaro &sensor_dev_attr_temp6_input.dev_attr.attr, 590*08426edaSThilo Cestonaro &sensor_dev_attr_temp7_input.dev_attr.attr, 591*08426edaSThilo Cestonaro &sensor_dev_attr_temp8_input.dev_attr.attr, 592*08426edaSThilo Cestonaro &sensor_dev_attr_temp9_input.dev_attr.attr, 593*08426edaSThilo Cestonaro &sensor_dev_attr_temp10_input.dev_attr.attr, 594*08426edaSThilo Cestonaro &sensor_dev_attr_temp11_input.dev_attr.attr, 595*08426edaSThilo Cestonaro &sensor_dev_attr_temp12_input.dev_attr.attr, 596*08426edaSThilo Cestonaro &sensor_dev_attr_temp13_input.dev_attr.attr, 597*08426edaSThilo Cestonaro &sensor_dev_attr_temp14_input.dev_attr.attr, 598*08426edaSThilo Cestonaro &sensor_dev_attr_temp15_input.dev_attr.attr, 599*08426edaSThilo Cestonaro &sensor_dev_attr_temp16_input.dev_attr.attr, 600*08426edaSThilo Cestonaro 601*08426edaSThilo Cestonaro &sensor_dev_attr_temp1_fault.dev_attr.attr, 602*08426edaSThilo Cestonaro &sensor_dev_attr_temp2_fault.dev_attr.attr, 603*08426edaSThilo Cestonaro &sensor_dev_attr_temp3_fault.dev_attr.attr, 604*08426edaSThilo Cestonaro &sensor_dev_attr_temp4_fault.dev_attr.attr, 605*08426edaSThilo Cestonaro &sensor_dev_attr_temp5_fault.dev_attr.attr, 606*08426edaSThilo Cestonaro &sensor_dev_attr_temp6_fault.dev_attr.attr, 607*08426edaSThilo Cestonaro &sensor_dev_attr_temp7_fault.dev_attr.attr, 608*08426edaSThilo Cestonaro &sensor_dev_attr_temp8_fault.dev_attr.attr, 609*08426edaSThilo Cestonaro &sensor_dev_attr_temp9_fault.dev_attr.attr, 610*08426edaSThilo Cestonaro &sensor_dev_attr_temp10_fault.dev_attr.attr, 611*08426edaSThilo Cestonaro &sensor_dev_attr_temp11_fault.dev_attr.attr, 612*08426edaSThilo Cestonaro &sensor_dev_attr_temp12_fault.dev_attr.attr, 613*08426edaSThilo Cestonaro &sensor_dev_attr_temp13_fault.dev_attr.attr, 614*08426edaSThilo Cestonaro &sensor_dev_attr_temp14_fault.dev_attr.attr, 615*08426edaSThilo Cestonaro &sensor_dev_attr_temp15_fault.dev_attr.attr, 616*08426edaSThilo Cestonaro &sensor_dev_attr_temp16_fault.dev_attr.attr, 617*08426edaSThilo Cestonaro 618*08426edaSThilo Cestonaro &sensor_dev_attr_temp1_alarm.dev_attr.attr, 619*08426edaSThilo Cestonaro &sensor_dev_attr_temp2_alarm.dev_attr.attr, 620*08426edaSThilo Cestonaro &sensor_dev_attr_temp3_alarm.dev_attr.attr, 621*08426edaSThilo Cestonaro &sensor_dev_attr_temp4_alarm.dev_attr.attr, 622*08426edaSThilo Cestonaro &sensor_dev_attr_temp5_alarm.dev_attr.attr, 623*08426edaSThilo Cestonaro &sensor_dev_attr_temp6_alarm.dev_attr.attr, 624*08426edaSThilo Cestonaro &sensor_dev_attr_temp7_alarm.dev_attr.attr, 625*08426edaSThilo Cestonaro &sensor_dev_attr_temp8_alarm.dev_attr.attr, 626*08426edaSThilo Cestonaro &sensor_dev_attr_temp9_alarm.dev_attr.attr, 627*08426edaSThilo Cestonaro &sensor_dev_attr_temp10_alarm.dev_attr.attr, 628*08426edaSThilo Cestonaro &sensor_dev_attr_temp11_alarm.dev_attr.attr, 629*08426edaSThilo Cestonaro &sensor_dev_attr_temp12_alarm.dev_attr.attr, 630*08426edaSThilo Cestonaro &sensor_dev_attr_temp13_alarm.dev_attr.attr, 631*08426edaSThilo Cestonaro &sensor_dev_attr_temp14_alarm.dev_attr.attr, 632*08426edaSThilo Cestonaro &sensor_dev_attr_temp15_alarm.dev_attr.attr, 633*08426edaSThilo Cestonaro &sensor_dev_attr_temp16_alarm.dev_attr.attr, 634*08426edaSThilo Cestonaro NULL 635*08426edaSThilo Cestonaro }; 636*08426edaSThilo Cestonaro 637*08426edaSThilo Cestonaro /* Fans */ 638*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_value, NULL, 0); 639*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_value, NULL, 1); 640*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_value, NULL, 2); 641*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_value, NULL, 3); 642*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_value, NULL, 4); 643*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_value, NULL, 5); 644*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_value, NULL, 6); 645*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_value, NULL, 7); 646*08426edaSThilo Cestonaro 647*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan1_source, S_IRUGO, show_fan_source, NULL, 0); 648*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan2_source, S_IRUGO, show_fan_source, NULL, 1); 649*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan3_source, S_IRUGO, show_fan_source, NULL, 2); 650*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan4_source, S_IRUGO, show_fan_source, NULL, 3); 651*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan5_source, S_IRUGO, show_fan_source, NULL, 4); 652*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan6_source, S_IRUGO, show_fan_source, NULL, 5); 653*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan7_source, S_IRUGO, show_fan_source, NULL, 6); 654*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan8_source, S_IRUGO, show_fan_source, NULL, 7); 655*08426edaSThilo Cestonaro 656*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO | S_IWUSR, 657*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 0); 658*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO | S_IWUSR, 659*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 1); 660*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO | S_IWUSR, 661*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 2); 662*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO | S_IWUSR, 663*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 3); 664*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO | S_IWUSR, 665*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 4); 666*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO | S_IWUSR, 667*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 5); 668*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO | S_IWUSR, 669*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 6); 670*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO | S_IWUSR, 671*08426edaSThilo Cestonaro show_fan_alarm, clear_fan_alarm, 7); 672*08426edaSThilo Cestonaro 673*08426edaSThilo Cestonaro static struct attribute *fts_fan_attrs[] = { 674*08426edaSThilo Cestonaro &sensor_dev_attr_fan1_input.dev_attr.attr, 675*08426edaSThilo Cestonaro &sensor_dev_attr_fan2_input.dev_attr.attr, 676*08426edaSThilo Cestonaro &sensor_dev_attr_fan3_input.dev_attr.attr, 677*08426edaSThilo Cestonaro &sensor_dev_attr_fan4_input.dev_attr.attr, 678*08426edaSThilo Cestonaro &sensor_dev_attr_fan5_input.dev_attr.attr, 679*08426edaSThilo Cestonaro &sensor_dev_attr_fan6_input.dev_attr.attr, 680*08426edaSThilo Cestonaro &sensor_dev_attr_fan7_input.dev_attr.attr, 681*08426edaSThilo Cestonaro &sensor_dev_attr_fan8_input.dev_attr.attr, 682*08426edaSThilo Cestonaro 683*08426edaSThilo Cestonaro &sensor_dev_attr_fan1_source.dev_attr.attr, 684*08426edaSThilo Cestonaro &sensor_dev_attr_fan2_source.dev_attr.attr, 685*08426edaSThilo Cestonaro &sensor_dev_attr_fan3_source.dev_attr.attr, 686*08426edaSThilo Cestonaro &sensor_dev_attr_fan4_source.dev_attr.attr, 687*08426edaSThilo Cestonaro &sensor_dev_attr_fan5_source.dev_attr.attr, 688*08426edaSThilo Cestonaro &sensor_dev_attr_fan6_source.dev_attr.attr, 689*08426edaSThilo Cestonaro &sensor_dev_attr_fan7_source.dev_attr.attr, 690*08426edaSThilo Cestonaro &sensor_dev_attr_fan8_source.dev_attr.attr, 691*08426edaSThilo Cestonaro 692*08426edaSThilo Cestonaro &sensor_dev_attr_fan1_alarm.dev_attr.attr, 693*08426edaSThilo Cestonaro &sensor_dev_attr_fan2_alarm.dev_attr.attr, 694*08426edaSThilo Cestonaro &sensor_dev_attr_fan3_alarm.dev_attr.attr, 695*08426edaSThilo Cestonaro &sensor_dev_attr_fan4_alarm.dev_attr.attr, 696*08426edaSThilo Cestonaro &sensor_dev_attr_fan5_alarm.dev_attr.attr, 697*08426edaSThilo Cestonaro &sensor_dev_attr_fan6_alarm.dev_attr.attr, 698*08426edaSThilo Cestonaro &sensor_dev_attr_fan7_alarm.dev_attr.attr, 699*08426edaSThilo Cestonaro &sensor_dev_attr_fan8_alarm.dev_attr.attr, 700*08426edaSThilo Cestonaro NULL 701*08426edaSThilo Cestonaro }; 702*08426edaSThilo Cestonaro 703*08426edaSThilo Cestonaro /* Voltages */ 704*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_value, NULL, 0); 705*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_value, NULL, 1); 706*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_value, NULL, 2); 707*08426edaSThilo Cestonaro static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_value, NULL, 3); 708*08426edaSThilo Cestonaro static struct attribute *fts_voltage_attrs[] = { 709*08426edaSThilo Cestonaro &sensor_dev_attr_in1_input.dev_attr.attr, 710*08426edaSThilo Cestonaro &sensor_dev_attr_in2_input.dev_attr.attr, 711*08426edaSThilo Cestonaro &sensor_dev_attr_in3_input.dev_attr.attr, 712*08426edaSThilo Cestonaro &sensor_dev_attr_in4_input.dev_attr.attr, 713*08426edaSThilo Cestonaro NULL 714*08426edaSThilo Cestonaro }; 715*08426edaSThilo Cestonaro 716*08426edaSThilo Cestonaro static const struct attribute_group fts_voltage_attr_group = { 717*08426edaSThilo Cestonaro .attrs = fts_voltage_attrs 718*08426edaSThilo Cestonaro }; 719*08426edaSThilo Cestonaro 720*08426edaSThilo Cestonaro static const struct attribute_group fts_temp_attr_group = { 721*08426edaSThilo Cestonaro .attrs = fts_temp_attrs 722*08426edaSThilo Cestonaro }; 723*08426edaSThilo Cestonaro 724*08426edaSThilo Cestonaro static const struct attribute_group fts_fan_attr_group = { 725*08426edaSThilo Cestonaro .attrs = fts_fan_attrs 726*08426edaSThilo Cestonaro }; 727*08426edaSThilo Cestonaro 728*08426edaSThilo Cestonaro static const struct attribute_group *fts_attr_groups[] = { 729*08426edaSThilo Cestonaro &fts_voltage_attr_group, 730*08426edaSThilo Cestonaro &fts_temp_attr_group, 731*08426edaSThilo Cestonaro &fts_fan_attr_group, 732*08426edaSThilo Cestonaro NULL 733*08426edaSThilo Cestonaro }; 734*08426edaSThilo Cestonaro 735*08426edaSThilo Cestonaro /*****************************************************************************/ 736*08426edaSThilo Cestonaro /* Module initialization / remove functions */ 737*08426edaSThilo Cestonaro /*****************************************************************************/ 738*08426edaSThilo Cestonaro static int fts_remove(struct i2c_client *client) 739*08426edaSThilo Cestonaro { 740*08426edaSThilo Cestonaro struct fts_data *data = dev_get_drvdata(&client->dev); 741*08426edaSThilo Cestonaro 742*08426edaSThilo Cestonaro watchdog_unregister_device(&data->wdd); 743*08426edaSThilo Cestonaro return 0; 744*08426edaSThilo Cestonaro } 745*08426edaSThilo Cestonaro 746*08426edaSThilo Cestonaro static int fts_probe(struct i2c_client *client, const struct i2c_device_id *id) 747*08426edaSThilo Cestonaro { 748*08426edaSThilo Cestonaro u8 revision; 749*08426edaSThilo Cestonaro struct fts_data *data; 750*08426edaSThilo Cestonaro int err; 751*08426edaSThilo Cestonaro s8 deviceid; 752*08426edaSThilo Cestonaro struct device *hwmon_dev; 753*08426edaSThilo Cestonaro 754*08426edaSThilo Cestonaro if (client->addr != 0x73) 755*08426edaSThilo Cestonaro return -ENODEV; 756*08426edaSThilo Cestonaro 757*08426edaSThilo Cestonaro /* Baseboard Management Controller check */ 758*08426edaSThilo Cestonaro deviceid = i2c_smbus_read_byte_data(client, FTS_DEVICE_ID_REG); 759*08426edaSThilo Cestonaro if (deviceid > 0 && (deviceid & 0xF0) == 0x10) { 760*08426edaSThilo Cestonaro switch (deviceid & 0x0F) { 761*08426edaSThilo Cestonaro case 0x01: 762*08426edaSThilo Cestonaro break; 763*08426edaSThilo Cestonaro default: 764*08426edaSThilo Cestonaro dev_dbg(&client->dev, 765*08426edaSThilo Cestonaro "No Baseboard Management Controller\n"); 766*08426edaSThilo Cestonaro return -ENODEV; 767*08426edaSThilo Cestonaro } 768*08426edaSThilo Cestonaro } else { 769*08426edaSThilo Cestonaro dev_dbg(&client->dev, "No fujitsu board\n"); 770*08426edaSThilo Cestonaro return -ENODEV; 771*08426edaSThilo Cestonaro } 772*08426edaSThilo Cestonaro 773*08426edaSThilo Cestonaro data = devm_kzalloc(&client->dev, sizeof(struct fts_data), 774*08426edaSThilo Cestonaro GFP_KERNEL); 775*08426edaSThilo Cestonaro if (!data) 776*08426edaSThilo Cestonaro return -ENOMEM; 777*08426edaSThilo Cestonaro 778*08426edaSThilo Cestonaro mutex_init(&data->update_lock); 779*08426edaSThilo Cestonaro mutex_init(&data->access_lock); 780*08426edaSThilo Cestonaro data->client = client; 781*08426edaSThilo Cestonaro dev_set_drvdata(&client->dev, data); 782*08426edaSThilo Cestonaro 783*08426edaSThilo Cestonaro err = i2c_smbus_read_byte_data(client, FTS_DEVICE_REVISION_REG); 784*08426edaSThilo Cestonaro if (err < 0) 785*08426edaSThilo Cestonaro return err; 786*08426edaSThilo Cestonaro revision = err; 787*08426edaSThilo Cestonaro 788*08426edaSThilo Cestonaro hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, 789*08426edaSThilo Cestonaro "ftsteutates", 790*08426edaSThilo Cestonaro data, 791*08426edaSThilo Cestonaro fts_attr_groups); 792*08426edaSThilo Cestonaro if (IS_ERR(hwmon_dev)) 793*08426edaSThilo Cestonaro return PTR_ERR(hwmon_dev); 794*08426edaSThilo Cestonaro 795*08426edaSThilo Cestonaro err = fts_watchdog_init(data); 796*08426edaSThilo Cestonaro if (err) 797*08426edaSThilo Cestonaro return err; 798*08426edaSThilo Cestonaro 799*08426edaSThilo Cestonaro dev_info(&client->dev, "Detected FTS Teutates chip, revision: %d.%d\n", 800*08426edaSThilo Cestonaro (revision & 0xF0) >> 4, revision & 0x0F); 801*08426edaSThilo Cestonaro return 0; 802*08426edaSThilo Cestonaro } 803*08426edaSThilo Cestonaro 804*08426edaSThilo Cestonaro /*****************************************************************************/ 805*08426edaSThilo Cestonaro /* Module Details */ 806*08426edaSThilo Cestonaro /*****************************************************************************/ 807*08426edaSThilo Cestonaro static struct i2c_driver fts_driver = { 808*08426edaSThilo Cestonaro .driver = { 809*08426edaSThilo Cestonaro .name = "ftsteutates", 810*08426edaSThilo Cestonaro }, 811*08426edaSThilo Cestonaro .id_table = fts_id, 812*08426edaSThilo Cestonaro .probe = fts_probe, 813*08426edaSThilo Cestonaro .remove = fts_remove, 814*08426edaSThilo Cestonaro }; 815*08426edaSThilo Cestonaro 816*08426edaSThilo Cestonaro module_i2c_driver(fts_driver); 817*08426edaSThilo Cestonaro 818*08426edaSThilo Cestonaro MODULE_AUTHOR("Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>"); 819*08426edaSThilo Cestonaro MODULE_DESCRIPTION("FTS Teutates driver"); 820*08426edaSThilo Cestonaro MODULE_LICENSE("GPL"); 821