11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20772a640SHans de Goede /***************************************************************************
3312869ecSHans de Goede * Copyright (C) 2011-2012 Hans de Goede <hdegoede@redhat.com> *
40772a640SHans de Goede * *
50772a640SHans de Goede ***************************************************************************/
60772a640SHans de Goede
70772a640SHans de Goede #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
80772a640SHans de Goede
90772a640SHans de Goede #include <linux/module.h>
10*4db3c092SArmin Wolf #include <linux/mod_devicetable.h>
110772a640SHans de Goede #include <linux/init.h>
120772a640SHans de Goede #include <linux/slab.h>
130772a640SHans de Goede #include <linux/jiffies.h>
140772a640SHans de Goede #include <linux/platform_device.h>
150772a640SHans de Goede #include <linux/hwmon.h>
160772a640SHans de Goede #include <linux/hwmon-sysfs.h>
170772a640SHans de Goede #include <linux/err.h>
180772a640SHans de Goede #include <linux/mutex.h>
190772a640SHans de Goede #include "sch56xx-common.h"
200772a640SHans de Goede
210772a640SHans de Goede #define DRVNAME "sch5636"
220772a640SHans de Goede #define DEVNAME "theseus" /* We only support one model for now */
230772a640SHans de Goede
240772a640SHans de Goede #define SCH5636_REG_FUJITSU_ID 0x780
250772a640SHans de Goede #define SCH5636_REG_FUJITSU_REV 0x783
260772a640SHans de Goede
270772a640SHans de Goede #define SCH5636_NO_INS 5
280772a640SHans de Goede #define SCH5636_NO_TEMPS 16
290772a640SHans de Goede #define SCH5636_NO_FANS 8
300772a640SHans de Goede
310772a640SHans de Goede static const u16 SCH5636_REG_IN_VAL[SCH5636_NO_INS] = {
320772a640SHans de Goede 0x22, 0x23, 0x24, 0x25, 0x189 };
330772a640SHans de Goede static const u16 SCH5636_REG_IN_FACTORS[SCH5636_NO_INS] = {
340772a640SHans de Goede 4400, 1500, 4000, 4400, 16000 };
350772a640SHans de Goede static const char * const SCH5636_IN_LABELS[SCH5636_NO_INS] = {
360772a640SHans de Goede "3.3V", "VREF", "VBAT", "3.3AUX", "12V" };
370772a640SHans de Goede
380772a640SHans de Goede static const u16 SCH5636_REG_TEMP_VAL[SCH5636_NO_TEMPS] = {
390772a640SHans de Goede 0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181,
400772a640SHans de Goede 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C };
410772a640SHans de Goede #define SCH5636_REG_TEMP_CTRL(i) (0x790 + (i))
420772a640SHans de Goede #define SCH5636_TEMP_WORKING 0x01
430772a640SHans de Goede #define SCH5636_TEMP_ALARM 0x02
440772a640SHans de Goede #define SCH5636_TEMP_DEACTIVATED 0x80
450772a640SHans de Goede
460772a640SHans de Goede static const u16 SCH5636_REG_FAN_VAL[SCH5636_NO_FANS] = {
470772a640SHans de Goede 0x2C, 0x2E, 0x30, 0x32, 0x62, 0x64, 0x66, 0x68 };
480772a640SHans de Goede #define SCH5636_REG_FAN_CTRL(i) (0x880 + (i))
490772a640SHans de Goede /* FAULT in datasheet, but acts as an alarm */
500772a640SHans de Goede #define SCH5636_FAN_ALARM 0x04
510772a640SHans de Goede #define SCH5636_FAN_NOT_PRESENT 0x08
520772a640SHans de Goede #define SCH5636_FAN_DEACTIVATED 0x80
530772a640SHans de Goede
540772a640SHans de Goede
550772a640SHans de Goede struct sch5636_data {
560772a640SHans de Goede unsigned short addr;
570772a640SHans de Goede struct device *hwmon_dev;
580772a640SHans de Goede
590772a640SHans de Goede struct mutex update_lock;
60952a11caSPaul Fertser bool valid; /* true if following fields are valid */
610772a640SHans de Goede unsigned long last_updated; /* In jiffies */
620772a640SHans de Goede u8 in[SCH5636_NO_INS];
630772a640SHans de Goede u8 temp_val[SCH5636_NO_TEMPS];
640772a640SHans de Goede u8 temp_ctrl[SCH5636_NO_TEMPS];
650772a640SHans de Goede u16 fan_val[SCH5636_NO_FANS];
660772a640SHans de Goede u8 fan_ctrl[SCH5636_NO_FANS];
670772a640SHans de Goede };
680772a640SHans de Goede
sch5636_update_device(struct device * dev)690772a640SHans de Goede static struct sch5636_data *sch5636_update_device(struct device *dev)
700772a640SHans de Goede {
710772a640SHans de Goede struct sch5636_data *data = dev_get_drvdata(dev);
720772a640SHans de Goede struct sch5636_data *ret = data;
730772a640SHans de Goede int i, val;
740772a640SHans de Goede
750772a640SHans de Goede mutex_lock(&data->update_lock);
760772a640SHans de Goede
770772a640SHans de Goede /* Cache the values for 1 second */
780772a640SHans de Goede if (data->valid && !time_after(jiffies, data->last_updated + HZ))
790772a640SHans de Goede goto abort;
800772a640SHans de Goede
810772a640SHans de Goede for (i = 0; i < SCH5636_NO_INS; i++) {
820772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
830772a640SHans de Goede SCH5636_REG_IN_VAL[i]);
840772a640SHans de Goede if (unlikely(val < 0)) {
850772a640SHans de Goede ret = ERR_PTR(val);
860772a640SHans de Goede goto abort;
870772a640SHans de Goede }
880772a640SHans de Goede data->in[i] = val;
890772a640SHans de Goede }
900772a640SHans de Goede
910772a640SHans de Goede for (i = 0; i < SCH5636_NO_TEMPS; i++) {
920772a640SHans de Goede if (data->temp_ctrl[i] & SCH5636_TEMP_DEACTIVATED)
930772a640SHans de Goede continue;
940772a640SHans de Goede
950772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
960772a640SHans de Goede SCH5636_REG_TEMP_VAL[i]);
970772a640SHans de Goede if (unlikely(val < 0)) {
980772a640SHans de Goede ret = ERR_PTR(val);
990772a640SHans de Goede goto abort;
1000772a640SHans de Goede }
1010772a640SHans de Goede data->temp_val[i] = val;
1020772a640SHans de Goede
1030772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
1040772a640SHans de Goede SCH5636_REG_TEMP_CTRL(i));
1050772a640SHans de Goede if (unlikely(val < 0)) {
1060772a640SHans de Goede ret = ERR_PTR(val);
1070772a640SHans de Goede goto abort;
1080772a640SHans de Goede }
1090772a640SHans de Goede data->temp_ctrl[i] = val;
1100772a640SHans de Goede /* Alarms need to be explicitly write-cleared */
1110772a640SHans de Goede if (val & SCH5636_TEMP_ALARM) {
1120772a640SHans de Goede sch56xx_write_virtual_reg(data->addr,
1130772a640SHans de Goede SCH5636_REG_TEMP_CTRL(i), val);
1140772a640SHans de Goede }
1150772a640SHans de Goede }
1160772a640SHans de Goede
1170772a640SHans de Goede for (i = 0; i < SCH5636_NO_FANS; i++) {
1180772a640SHans de Goede if (data->fan_ctrl[i] & SCH5636_FAN_DEACTIVATED)
1190772a640SHans de Goede continue;
1200772a640SHans de Goede
1210772a640SHans de Goede val = sch56xx_read_virtual_reg16(data->addr,
1220772a640SHans de Goede SCH5636_REG_FAN_VAL[i]);
1230772a640SHans de Goede if (unlikely(val < 0)) {
1240772a640SHans de Goede ret = ERR_PTR(val);
1250772a640SHans de Goede goto abort;
1260772a640SHans de Goede }
1270772a640SHans de Goede data->fan_val[i] = val;
1280772a640SHans de Goede
1290772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
1300772a640SHans de Goede SCH5636_REG_FAN_CTRL(i));
1310772a640SHans de Goede if (unlikely(val < 0)) {
1320772a640SHans de Goede ret = ERR_PTR(val);
1330772a640SHans de Goede goto abort;
1340772a640SHans de Goede }
1350772a640SHans de Goede data->fan_ctrl[i] = val;
1360772a640SHans de Goede /* Alarms need to be explicitly write-cleared */
1370772a640SHans de Goede if (val & SCH5636_FAN_ALARM) {
1380772a640SHans de Goede sch56xx_write_virtual_reg(data->addr,
1390772a640SHans de Goede SCH5636_REG_FAN_CTRL(i), val);
1400772a640SHans de Goede }
1410772a640SHans de Goede }
1420772a640SHans de Goede
1430772a640SHans de Goede data->last_updated = jiffies;
144952a11caSPaul Fertser data->valid = true;
1450772a640SHans de Goede abort:
1460772a640SHans de Goede mutex_unlock(&data->update_lock);
1470772a640SHans de Goede return ret;
1480772a640SHans de Goede }
1490772a640SHans de Goede
reg_to_rpm(u16 reg)1500772a640SHans de Goede static int reg_to_rpm(u16 reg)
1510772a640SHans de Goede {
1520772a640SHans de Goede if (reg == 0)
1530772a640SHans de Goede return -EIO;
1540772a640SHans de Goede if (reg == 0xffff)
1550772a640SHans de Goede return 0;
1560772a640SHans de Goede
1570772a640SHans de Goede return 5400540 / reg;
1580772a640SHans de Goede }
1590772a640SHans de Goede
name_show(struct device * dev,struct device_attribute * devattr,char * buf)16080c6b121SGuenter Roeck static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
1610772a640SHans de Goede char *buf)
1620772a640SHans de Goede {
1631f4d4af4SGuenter Roeck return sysfs_emit(buf, "%s\n", DEVNAME);
1640772a640SHans de Goede }
1650772a640SHans de Goede
in_value_show(struct device * dev,struct device_attribute * devattr,char * buf)16680c6b121SGuenter Roeck static ssize_t in_value_show(struct device *dev,
16780c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
1680772a640SHans de Goede {
1690772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1700772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
1710772a640SHans de Goede int val;
1720772a640SHans de Goede
1730772a640SHans de Goede if (IS_ERR(data))
1740772a640SHans de Goede return PTR_ERR(data);
1750772a640SHans de Goede
1760772a640SHans de Goede val = DIV_ROUND_CLOSEST(
1770772a640SHans de Goede data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index],
1780772a640SHans de Goede 255);
1791f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
1800772a640SHans de Goede }
1810772a640SHans de Goede
in_label_show(struct device * dev,struct device_attribute * devattr,char * buf)18280c6b121SGuenter Roeck static ssize_t in_label_show(struct device *dev,
18380c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
1840772a640SHans de Goede {
1850772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1860772a640SHans de Goede
1871f4d4af4SGuenter Roeck return sysfs_emit(buf, "%s\n",
1880772a640SHans de Goede SCH5636_IN_LABELS[attr->index]);
1890772a640SHans de Goede }
1900772a640SHans de Goede
temp_value_show(struct device * dev,struct device_attribute * devattr,char * buf)19180c6b121SGuenter Roeck static ssize_t temp_value_show(struct device *dev,
19280c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
1930772a640SHans de Goede {
1940772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1950772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
1960772a640SHans de Goede int val;
1970772a640SHans de Goede
1980772a640SHans de Goede if (IS_ERR(data))
1990772a640SHans de Goede return PTR_ERR(data);
2000772a640SHans de Goede
2010772a640SHans de Goede val = (data->temp_val[attr->index] - 64) * 1000;
2021f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
2030772a640SHans de Goede }
2040772a640SHans de Goede
temp_fault_show(struct device * dev,struct device_attribute * devattr,char * buf)20580c6b121SGuenter Roeck static ssize_t temp_fault_show(struct device *dev,
20680c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
2070772a640SHans de Goede {
2080772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
2090772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
2100772a640SHans de Goede int val;
2110772a640SHans de Goede
2120772a640SHans de Goede if (IS_ERR(data))
2130772a640SHans de Goede return PTR_ERR(data);
2140772a640SHans de Goede
2150772a640SHans de Goede val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1;
2161f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
2170772a640SHans de Goede }
2180772a640SHans de Goede
temp_alarm_show(struct device * dev,struct device_attribute * devattr,char * buf)21980c6b121SGuenter Roeck static ssize_t temp_alarm_show(struct device *dev,
22080c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
2210772a640SHans de Goede {
2220772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
2230772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
2240772a640SHans de Goede int val;
2250772a640SHans de Goede
2260772a640SHans de Goede if (IS_ERR(data))
2270772a640SHans de Goede return PTR_ERR(data);
2280772a640SHans de Goede
2290772a640SHans de Goede val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0;
2301f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
2310772a640SHans de Goede }
2320772a640SHans de Goede
fan_value_show(struct device * dev,struct device_attribute * devattr,char * buf)23380c6b121SGuenter Roeck static ssize_t fan_value_show(struct device *dev,
23480c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
2350772a640SHans de Goede {
2360772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
2370772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
2380772a640SHans de Goede int val;
2390772a640SHans de Goede
2400772a640SHans de Goede if (IS_ERR(data))
2410772a640SHans de Goede return PTR_ERR(data);
2420772a640SHans de Goede
2430772a640SHans de Goede val = reg_to_rpm(data->fan_val[attr->index]);
2440772a640SHans de Goede if (val < 0)
2450772a640SHans de Goede return val;
2460772a640SHans de Goede
2471f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
2480772a640SHans de Goede }
2490772a640SHans de Goede
fan_fault_show(struct device * dev,struct device_attribute * devattr,char * buf)25080c6b121SGuenter Roeck static ssize_t fan_fault_show(struct device *dev,
25180c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
2520772a640SHans de Goede {
2530772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
2540772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
2550772a640SHans de Goede int val;
2560772a640SHans de Goede
2570772a640SHans de Goede if (IS_ERR(data))
2580772a640SHans de Goede return PTR_ERR(data);
2590772a640SHans de Goede
2600772a640SHans de Goede val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0;
2611f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
2620772a640SHans de Goede }
2630772a640SHans de Goede
fan_alarm_show(struct device * dev,struct device_attribute * devattr,char * buf)26480c6b121SGuenter Roeck static ssize_t fan_alarm_show(struct device *dev,
26580c6b121SGuenter Roeck struct device_attribute *devattr, char *buf)
2660772a640SHans de Goede {
2670772a640SHans de Goede struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
2680772a640SHans de Goede struct sch5636_data *data = sch5636_update_device(dev);
2690772a640SHans de Goede int val;
2700772a640SHans de Goede
2710772a640SHans de Goede if (IS_ERR(data))
2720772a640SHans de Goede return PTR_ERR(data);
2730772a640SHans de Goede
2740772a640SHans de Goede val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0;
2751f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", val);
2760772a640SHans de Goede }
2770772a640SHans de Goede
2780772a640SHans de Goede static struct sensor_device_attribute sch5636_attr[] = {
27980c6b121SGuenter Roeck SENSOR_ATTR_RO(name, name, 0),
28080c6b121SGuenter Roeck SENSOR_ATTR_RO(in0_input, in_value, 0),
28180c6b121SGuenter Roeck SENSOR_ATTR_RO(in0_label, in_label, 0),
28280c6b121SGuenter Roeck SENSOR_ATTR_RO(in1_input, in_value, 1),
28380c6b121SGuenter Roeck SENSOR_ATTR_RO(in1_label, in_label, 1),
28480c6b121SGuenter Roeck SENSOR_ATTR_RO(in2_input, in_value, 2),
28580c6b121SGuenter Roeck SENSOR_ATTR_RO(in2_label, in_label, 2),
28680c6b121SGuenter Roeck SENSOR_ATTR_RO(in3_input, in_value, 3),
28780c6b121SGuenter Roeck SENSOR_ATTR_RO(in3_label, in_label, 3),
28880c6b121SGuenter Roeck SENSOR_ATTR_RO(in4_input, in_value, 4),
28980c6b121SGuenter Roeck SENSOR_ATTR_RO(in4_label, in_label, 4),
2900772a640SHans de Goede };
2910772a640SHans de Goede
2920772a640SHans de Goede static struct sensor_device_attribute sch5636_temp_attr[] = {
29380c6b121SGuenter Roeck SENSOR_ATTR_RO(temp1_input, temp_value, 0),
29480c6b121SGuenter Roeck SENSOR_ATTR_RO(temp1_fault, temp_fault, 0),
29580c6b121SGuenter Roeck SENSOR_ATTR_RO(temp1_alarm, temp_alarm, 0),
29680c6b121SGuenter Roeck SENSOR_ATTR_RO(temp2_input, temp_value, 1),
29780c6b121SGuenter Roeck SENSOR_ATTR_RO(temp2_fault, temp_fault, 1),
29880c6b121SGuenter Roeck SENSOR_ATTR_RO(temp2_alarm, temp_alarm, 1),
29980c6b121SGuenter Roeck SENSOR_ATTR_RO(temp3_input, temp_value, 2),
30080c6b121SGuenter Roeck SENSOR_ATTR_RO(temp3_fault, temp_fault, 2),
30180c6b121SGuenter Roeck SENSOR_ATTR_RO(temp3_alarm, temp_alarm, 2),
30280c6b121SGuenter Roeck SENSOR_ATTR_RO(temp4_input, temp_value, 3),
30380c6b121SGuenter Roeck SENSOR_ATTR_RO(temp4_fault, temp_fault, 3),
30480c6b121SGuenter Roeck SENSOR_ATTR_RO(temp4_alarm, temp_alarm, 3),
30580c6b121SGuenter Roeck SENSOR_ATTR_RO(temp5_input, temp_value, 4),
30680c6b121SGuenter Roeck SENSOR_ATTR_RO(temp5_fault, temp_fault, 4),
30780c6b121SGuenter Roeck SENSOR_ATTR_RO(temp5_alarm, temp_alarm, 4),
30880c6b121SGuenter Roeck SENSOR_ATTR_RO(temp6_input, temp_value, 5),
30980c6b121SGuenter Roeck SENSOR_ATTR_RO(temp6_fault, temp_fault, 5),
31080c6b121SGuenter Roeck SENSOR_ATTR_RO(temp6_alarm, temp_alarm, 5),
31180c6b121SGuenter Roeck SENSOR_ATTR_RO(temp7_input, temp_value, 6),
31280c6b121SGuenter Roeck SENSOR_ATTR_RO(temp7_fault, temp_fault, 6),
31380c6b121SGuenter Roeck SENSOR_ATTR_RO(temp7_alarm, temp_alarm, 6),
31480c6b121SGuenter Roeck SENSOR_ATTR_RO(temp8_input, temp_value, 7),
31580c6b121SGuenter Roeck SENSOR_ATTR_RO(temp8_fault, temp_fault, 7),
31680c6b121SGuenter Roeck SENSOR_ATTR_RO(temp8_alarm, temp_alarm, 7),
31780c6b121SGuenter Roeck SENSOR_ATTR_RO(temp9_input, temp_value, 8),
31880c6b121SGuenter Roeck SENSOR_ATTR_RO(temp9_fault, temp_fault, 8),
31980c6b121SGuenter Roeck SENSOR_ATTR_RO(temp9_alarm, temp_alarm, 8),
32080c6b121SGuenter Roeck SENSOR_ATTR_RO(temp10_input, temp_value, 9),
32180c6b121SGuenter Roeck SENSOR_ATTR_RO(temp10_fault, temp_fault, 9),
32280c6b121SGuenter Roeck SENSOR_ATTR_RO(temp10_alarm, temp_alarm, 9),
32380c6b121SGuenter Roeck SENSOR_ATTR_RO(temp11_input, temp_value, 10),
32480c6b121SGuenter Roeck SENSOR_ATTR_RO(temp11_fault, temp_fault, 10),
32580c6b121SGuenter Roeck SENSOR_ATTR_RO(temp11_alarm, temp_alarm, 10),
32680c6b121SGuenter Roeck SENSOR_ATTR_RO(temp12_input, temp_value, 11),
32780c6b121SGuenter Roeck SENSOR_ATTR_RO(temp12_fault, temp_fault, 11),
32880c6b121SGuenter Roeck SENSOR_ATTR_RO(temp12_alarm, temp_alarm, 11),
32980c6b121SGuenter Roeck SENSOR_ATTR_RO(temp13_input, temp_value, 12),
33080c6b121SGuenter Roeck SENSOR_ATTR_RO(temp13_fault, temp_fault, 12),
33180c6b121SGuenter Roeck SENSOR_ATTR_RO(temp13_alarm, temp_alarm, 12),
33280c6b121SGuenter Roeck SENSOR_ATTR_RO(temp14_input, temp_value, 13),
33380c6b121SGuenter Roeck SENSOR_ATTR_RO(temp14_fault, temp_fault, 13),
33480c6b121SGuenter Roeck SENSOR_ATTR_RO(temp14_alarm, temp_alarm, 13),
33580c6b121SGuenter Roeck SENSOR_ATTR_RO(temp15_input, temp_value, 14),
33680c6b121SGuenter Roeck SENSOR_ATTR_RO(temp15_fault, temp_fault, 14),
33780c6b121SGuenter Roeck SENSOR_ATTR_RO(temp15_alarm, temp_alarm, 14),
33880c6b121SGuenter Roeck SENSOR_ATTR_RO(temp16_input, temp_value, 15),
33980c6b121SGuenter Roeck SENSOR_ATTR_RO(temp16_fault, temp_fault, 15),
34080c6b121SGuenter Roeck SENSOR_ATTR_RO(temp16_alarm, temp_alarm, 15),
3410772a640SHans de Goede };
3420772a640SHans de Goede
3430772a640SHans de Goede static struct sensor_device_attribute sch5636_fan_attr[] = {
34480c6b121SGuenter Roeck SENSOR_ATTR_RO(fan1_input, fan_value, 0),
34580c6b121SGuenter Roeck SENSOR_ATTR_RO(fan1_fault, fan_fault, 0),
34680c6b121SGuenter Roeck SENSOR_ATTR_RO(fan1_alarm, fan_alarm, 0),
34780c6b121SGuenter Roeck SENSOR_ATTR_RO(fan2_input, fan_value, 1),
34880c6b121SGuenter Roeck SENSOR_ATTR_RO(fan2_fault, fan_fault, 1),
34980c6b121SGuenter Roeck SENSOR_ATTR_RO(fan2_alarm, fan_alarm, 1),
35080c6b121SGuenter Roeck SENSOR_ATTR_RO(fan3_input, fan_value, 2),
35180c6b121SGuenter Roeck SENSOR_ATTR_RO(fan3_fault, fan_fault, 2),
35280c6b121SGuenter Roeck SENSOR_ATTR_RO(fan3_alarm, fan_alarm, 2),
35380c6b121SGuenter Roeck SENSOR_ATTR_RO(fan4_input, fan_value, 3),
35480c6b121SGuenter Roeck SENSOR_ATTR_RO(fan4_fault, fan_fault, 3),
35580c6b121SGuenter Roeck SENSOR_ATTR_RO(fan4_alarm, fan_alarm, 3),
35680c6b121SGuenter Roeck SENSOR_ATTR_RO(fan5_input, fan_value, 4),
35780c6b121SGuenter Roeck SENSOR_ATTR_RO(fan5_fault, fan_fault, 4),
35880c6b121SGuenter Roeck SENSOR_ATTR_RO(fan5_alarm, fan_alarm, 4),
35980c6b121SGuenter Roeck SENSOR_ATTR_RO(fan6_input, fan_value, 5),
36080c6b121SGuenter Roeck SENSOR_ATTR_RO(fan6_fault, fan_fault, 5),
36180c6b121SGuenter Roeck SENSOR_ATTR_RO(fan6_alarm, fan_alarm, 5),
36280c6b121SGuenter Roeck SENSOR_ATTR_RO(fan7_input, fan_value, 6),
36380c6b121SGuenter Roeck SENSOR_ATTR_RO(fan7_fault, fan_fault, 6),
36480c6b121SGuenter Roeck SENSOR_ATTR_RO(fan7_alarm, fan_alarm, 6),
36580c6b121SGuenter Roeck SENSOR_ATTR_RO(fan8_input, fan_value, 7),
36680c6b121SGuenter Roeck SENSOR_ATTR_RO(fan8_fault, fan_fault, 7),
36780c6b121SGuenter Roeck SENSOR_ATTR_RO(fan8_alarm, fan_alarm, 7),
3680772a640SHans de Goede };
3690772a640SHans de Goede
sch5636_remove(struct platform_device * pdev)3700772a640SHans de Goede static int sch5636_remove(struct platform_device *pdev)
3710772a640SHans de Goede {
3720772a640SHans de Goede struct sch5636_data *data = platform_get_drvdata(pdev);
3730772a640SHans de Goede int i;
3740772a640SHans de Goede
3750772a640SHans de Goede if (data->hwmon_dev)
3760772a640SHans de Goede hwmon_device_unregister(data->hwmon_dev);
3770772a640SHans de Goede
3780772a640SHans de Goede for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++)
3790772a640SHans de Goede device_remove_file(&pdev->dev, &sch5636_attr[i].dev_attr);
3800772a640SHans de Goede
3810772a640SHans de Goede for (i = 0; i < SCH5636_NO_TEMPS * 3; i++)
3820772a640SHans de Goede device_remove_file(&pdev->dev,
3830772a640SHans de Goede &sch5636_temp_attr[i].dev_attr);
3840772a640SHans de Goede
3850772a640SHans de Goede for (i = 0; i < SCH5636_NO_FANS * 3; i++)
3860772a640SHans de Goede device_remove_file(&pdev->dev,
3870772a640SHans de Goede &sch5636_fan_attr[i].dev_attr);
3880772a640SHans de Goede
3890772a640SHans de Goede return 0;
3900772a640SHans de Goede }
3910772a640SHans de Goede
sch5636_probe(struct platform_device * pdev)3926c931ae1SBill Pemberton static int sch5636_probe(struct platform_device *pdev)
3930772a640SHans de Goede {
3940772a640SHans de Goede struct sch5636_data *data;
3950772a640SHans de Goede int i, err, val, revision[2];
3960772a640SHans de Goede char id[4];
3970772a640SHans de Goede
3989220f1e4SGuenter Roeck data = devm_kzalloc(&pdev->dev, sizeof(struct sch5636_data),
3999220f1e4SGuenter Roeck GFP_KERNEL);
4000772a640SHans de Goede if (!data)
4010772a640SHans de Goede return -ENOMEM;
4020772a640SHans de Goede
4030772a640SHans de Goede data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
4040772a640SHans de Goede mutex_init(&data->update_lock);
4050772a640SHans de Goede platform_set_drvdata(pdev, data);
4060772a640SHans de Goede
4070772a640SHans de Goede for (i = 0; i < 3; i++) {
4080772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
4090772a640SHans de Goede SCH5636_REG_FUJITSU_ID + i);
4100772a640SHans de Goede if (val < 0) {
4110772a640SHans de Goede pr_err("Could not read Fujitsu id byte at %#x\n",
4120772a640SHans de Goede SCH5636_REG_FUJITSU_ID + i);
4130772a640SHans de Goede err = val;
4140772a640SHans de Goede goto error;
4150772a640SHans de Goede }
4160772a640SHans de Goede id[i] = val;
4170772a640SHans de Goede }
4180772a640SHans de Goede id[i] = '\0';
4190772a640SHans de Goede
4200772a640SHans de Goede if (strcmp(id, "THS")) {
4210772a640SHans de Goede pr_err("Unknown Fujitsu id: %02x%02x%02x\n",
4220772a640SHans de Goede id[0], id[1], id[2]);
4230772a640SHans de Goede err = -ENODEV;
4240772a640SHans de Goede goto error;
4250772a640SHans de Goede }
4260772a640SHans de Goede
4270772a640SHans de Goede for (i = 0; i < 2; i++) {
4280772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
4290772a640SHans de Goede SCH5636_REG_FUJITSU_REV + i);
4300772a640SHans de Goede if (val < 0) {
4310772a640SHans de Goede err = val;
4320772a640SHans de Goede goto error;
4330772a640SHans de Goede }
4340772a640SHans de Goede revision[i] = val;
4350772a640SHans de Goede }
436d6a442dfSColin Ian King pr_info("Found %s chip at %#hx, revision: %d.%02d\n", DEVNAME,
4370772a640SHans de Goede data->addr, revision[0], revision[1]);
4380772a640SHans de Goede
4390772a640SHans de Goede /* Read all temp + fan ctrl registers to determine which are active */
4400772a640SHans de Goede for (i = 0; i < SCH5636_NO_TEMPS; i++) {
4410772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
4420772a640SHans de Goede SCH5636_REG_TEMP_CTRL(i));
4430772a640SHans de Goede if (unlikely(val < 0)) {
4440772a640SHans de Goede err = val;
4450772a640SHans de Goede goto error;
4460772a640SHans de Goede }
4470772a640SHans de Goede data->temp_ctrl[i] = val;
4480772a640SHans de Goede }
4490772a640SHans de Goede
4500772a640SHans de Goede for (i = 0; i < SCH5636_NO_FANS; i++) {
4510772a640SHans de Goede val = sch56xx_read_virtual_reg(data->addr,
4520772a640SHans de Goede SCH5636_REG_FAN_CTRL(i));
4530772a640SHans de Goede if (unlikely(val < 0)) {
4540772a640SHans de Goede err = val;
4550772a640SHans de Goede goto error;
4560772a640SHans de Goede }
4570772a640SHans de Goede data->fan_ctrl[i] = val;
4580772a640SHans de Goede }
4590772a640SHans de Goede
4600772a640SHans de Goede for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) {
4610772a640SHans de Goede err = device_create_file(&pdev->dev,
4620772a640SHans de Goede &sch5636_attr[i].dev_attr);
4630772a640SHans de Goede if (err)
4640772a640SHans de Goede goto error;
4650772a640SHans de Goede }
4660772a640SHans de Goede
4670772a640SHans de Goede for (i = 0; i < (SCH5636_NO_TEMPS * 3); i++) {
4680772a640SHans de Goede if (data->temp_ctrl[i/3] & SCH5636_TEMP_DEACTIVATED)
4690772a640SHans de Goede continue;
4700772a640SHans de Goede
4710772a640SHans de Goede err = device_create_file(&pdev->dev,
4720772a640SHans de Goede &sch5636_temp_attr[i].dev_attr);
4730772a640SHans de Goede if (err)
4740772a640SHans de Goede goto error;
4750772a640SHans de Goede }
4760772a640SHans de Goede
4770772a640SHans de Goede for (i = 0; i < (SCH5636_NO_FANS * 3); i++) {
4780772a640SHans de Goede if (data->fan_ctrl[i/3] & SCH5636_FAN_DEACTIVATED)
4790772a640SHans de Goede continue;
4800772a640SHans de Goede
4810772a640SHans de Goede err = device_create_file(&pdev->dev,
4820772a640SHans de Goede &sch5636_fan_attr[i].dev_attr);
4830772a640SHans de Goede if (err)
4840772a640SHans de Goede goto error;
4850772a640SHans de Goede }
4860772a640SHans de Goede
4870772a640SHans de Goede data->hwmon_dev = hwmon_device_register(&pdev->dev);
4880772a640SHans de Goede if (IS_ERR(data->hwmon_dev)) {
4890772a640SHans de Goede err = PTR_ERR(data->hwmon_dev);
4900772a640SHans de Goede data->hwmon_dev = NULL;
4910772a640SHans de Goede goto error;
4920772a640SHans de Goede }
4930772a640SHans de Goede
494312869ecSHans de Goede /* Note failing to register the watchdog is not a fatal error */
4952be5f0d7SArmin Wolf sch56xx_watchdog_register(&pdev->dev, data->addr, (revision[0] << 8) | revision[1],
496312869ecSHans de Goede &data->update_lock, 0);
497312869ecSHans de Goede
4980772a640SHans de Goede return 0;
4990772a640SHans de Goede
5000772a640SHans de Goede error:
5010772a640SHans de Goede sch5636_remove(pdev);
5020772a640SHans de Goede return err;
5030772a640SHans de Goede }
5040772a640SHans de Goede
505*4db3c092SArmin Wolf static const struct platform_device_id sch5636_device_id[] = {
506*4db3c092SArmin Wolf {
507*4db3c092SArmin Wolf .name = "sch5636",
508*4db3c092SArmin Wolf },
509*4db3c092SArmin Wolf { }
510*4db3c092SArmin Wolf };
511*4db3c092SArmin Wolf MODULE_DEVICE_TABLE(platform, sch5636_device_id);
512*4db3c092SArmin Wolf
5130772a640SHans de Goede static struct platform_driver sch5636_driver = {
5140772a640SHans de Goede .driver = {
5150772a640SHans de Goede .name = DRVNAME,
5160772a640SHans de Goede },
5170772a640SHans de Goede .probe = sch5636_probe,
5180772a640SHans de Goede .remove = sch5636_remove,
519*4db3c092SArmin Wolf .id_table = sch5636_device_id,
5200772a640SHans de Goede };
5210772a640SHans de Goede
52225a236a5SAxel Lin module_platform_driver(sch5636_driver);
5230772a640SHans de Goede
5240772a640SHans de Goede MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
5250772a640SHans de Goede MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
5260772a640SHans de Goede MODULE_LICENSE("GPL");
527