^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Gateworks System Controller Hardware Monitor module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2020 Gateworks Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/mfd/gsc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_data/gsc_hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define GSC_HWMON_MAX_TEMP_CH 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define GSC_HWMON_MAX_IN_CH 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define GSC_HWMON_MAX_FAN_CH 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define GSC_HWMON_RESOLUTION 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define GSC_HWMON_VREF 2500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct gsc_hwmon_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct gsc_dev *gsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct gsc_hwmon_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) const struct gsc_hwmon_channel *temp_ch[GSC_HWMON_MAX_TEMP_CH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) const struct gsc_hwmon_channel *in_ch[GSC_HWMON_MAX_IN_CH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) const struct gsc_hwmon_channel *fan_ch[GSC_HWMON_MAX_FAN_CH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u32 temp_config[GSC_HWMON_MAX_TEMP_CH + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u32 in_config[GSC_HWMON_MAX_IN_CH + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 fan_config[GSC_HWMON_MAX_FAN_CH + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct hwmon_channel_info temp_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct hwmon_channel_info in_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct hwmon_channel_info fan_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) const struct hwmon_channel_info *info[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct hwmon_chip_info chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static struct regmap_bus gsc_hwmon_regmap_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .reg_read = gsc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .reg_write = gsc_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static const struct regmap_config gsc_hwmon_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static ssize_t pwm_auto_point_temp_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 reg = hwmon->pdata->fan_base + (2 * attr->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 regs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ret = regmap_bulk_read(hwmon->regmap, reg, regs, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ret = regs[0] | regs[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return sprintf(buf, "%d\n", ret * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static ssize_t pwm_auto_point_temp_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u8 reg = hwmon->pdata->fan_base + (2 * attr->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u8 regs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) long temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (kstrtol(buf, 10, &temp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) temp = clamp_val(temp, 0, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) temp = DIV_ROUND_CLOSEST(temp, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) regs[0] = temp & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) regs[1] = (temp >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) err = regmap_bulk_write(hwmon->regmap, reg, regs, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static ssize_t pwm_auto_point_pwm_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, pwm_auto_point_temp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point2_pwm, pwm_auto_point_pwm, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp, pwm_auto_point_temp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point3_pwm, pwm_auto_point_pwm, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp, pwm_auto_point_temp, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point4_pwm, pwm_auto_point_pwm, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp, pwm_auto_point_temp, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point5_pwm, pwm_auto_point_pwm, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point5_temp, pwm_auto_point_temp, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point6_pwm, pwm_auto_point_pwm, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point6_temp, pwm_auto_point_temp, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static struct attribute *gsc_hwmon_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static const struct attribute_group gsc_hwmon_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .attrs = gsc_hwmon_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) __ATTRIBUTE_GROUPS(gsc_hwmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) gsc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int channel, long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) const struct gsc_hwmon_channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int sz, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u8 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case hwmon_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ch = hwmon->in_ch[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case hwmon_temp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ch = hwmon->temp_ch[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case hwmon_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ch = hwmon->fan_ch[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) sz = (ch->mode == mode_voltage_24bit) ? 3 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ret = regmap_bulk_read(hwmon->regmap, ch->reg, buf, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) while (sz-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) tmp |= (buf[sz] << (8 * sz));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) switch (ch->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case mode_temperature:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (tmp > 0x8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) tmp -= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) tmp *= 100; /* convert to millidegrees celsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) case mode_voltage_raw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) tmp = clamp_val(tmp, 0, BIT(GSC_HWMON_RESOLUTION));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* scale based on ref voltage and ADC resolution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) tmp *= GSC_HWMON_VREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) tmp >>= GSC_HWMON_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* scale based on optional voltage divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (ch->vdiv[0] && ch->vdiv[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) tmp *= (ch->vdiv[0] + ch->vdiv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) tmp /= ch->vdiv[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* adjust by uV offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tmp += ch->mvoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case mode_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tmp *= 30; /* convert to revolutions per minute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case mode_voltage_24bit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case mode_voltage_16bit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* no adjustment needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *val = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) gsc_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u32 attr, int channel, const char **buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case hwmon_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *buf = hwmon->in_ch[channel]->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case hwmon_temp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) *buf = hwmon->temp_ch[channel]->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case hwmon_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *buf = hwmon->fan_ch[channel]->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static umode_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) gsc_hwmon_is_visible(const void *_data, enum hwmon_sensor_types type, u32 attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static const struct hwmon_ops gsc_hwmon_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .is_visible = gsc_hwmon_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .read = gsc_hwmon_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .read_string = gsc_hwmon_read_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static struct gsc_hwmon_platform_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) gsc_hwmon_get_devtree_pdata(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct gsc_hwmon_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct gsc_hwmon_channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct fwnode_handle *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct device_node *fan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int nchannels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) nchannels = device_get_child_node_count(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (nchannels == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pdata = devm_kzalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) sizeof(*pdata) + nchannels * sizeof(*ch),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ch = (struct gsc_hwmon_channel *)(pdata + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pdata->channels = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) pdata->nchannels = nchannels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* fan controller base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) fan = of_find_compatible_node(dev->parent->of_node, NULL, "gw,gsc-fan");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (fan && of_property_read_u32(fan, "reg", &pdata->fan_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dev_err(dev, "fan node without base\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* allocate structures for channels and count instances of each type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) device_for_each_child_node(dev, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (fwnode_property_read_string(child, "label", &ch->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) dev_err(dev, "channel without label\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) fwnode_handle_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (fwnode_property_read_u32(child, "reg", &ch->reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) dev_err(dev, "channel without reg\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) fwnode_handle_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (fwnode_property_read_u32(child, "gw,mode", &ch->mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dev_err(dev, "channel without mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) fwnode_handle_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (ch->mode > mode_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dev_err(dev, "invalid channel mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) fwnode_handle_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!fwnode_property_read_u32(child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) "gw,voltage-offset-microvolt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) &ch->mvoffset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ch->mvoffset /= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fwnode_property_read_u32_array(child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "gw,voltage-divider-ohms",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ch->vdiv, ARRAY_SIZE(ch->vdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ch++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int gsc_hwmon_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct gsc_dev *gsc = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct gsc_hwmon_platform_data *pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct gsc_hwmon_data *hwmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) const struct attribute_group **groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int i, i_in, i_temp, i_fan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) pdata = gsc_hwmon_get_devtree_pdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (IS_ERR(pdata))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return PTR_ERR(pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!hwmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) hwmon->gsc = gsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) hwmon->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) hwmon->regmap = devm_regmap_init(dev, &gsc_hwmon_regmap_bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) gsc->i2c_hwmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) &gsc_hwmon_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (IS_ERR(hwmon->regmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return PTR_ERR(hwmon->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) for (i = 0, i_in = 0, i_temp = 0, i_fan = 0; i < hwmon->pdata->nchannels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) const struct gsc_hwmon_channel *ch = &pdata->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) switch (ch->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case mode_temperature:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (i_temp == GSC_HWMON_MAX_TEMP_CH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) dev_err(gsc->dev, "too many temp channels\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) hwmon->temp_ch[i_temp] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) hwmon->temp_config[i_temp] = HWMON_T_INPUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) HWMON_T_LABEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) i_temp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case mode_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (i_fan == GSC_HWMON_MAX_FAN_CH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_err(gsc->dev, "too many fan channels\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) hwmon->fan_ch[i_fan] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) hwmon->fan_config[i_fan] = HWMON_F_INPUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) HWMON_F_LABEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) i_fan++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) case mode_voltage_24bit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case mode_voltage_16bit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case mode_voltage_raw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (i_in == GSC_HWMON_MAX_IN_CH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dev_err(gsc->dev, "too many input channels\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) hwmon->in_ch[i_in] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) hwmon->in_config[i_in] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) HWMON_I_INPUT | HWMON_I_LABEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) i_in++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) dev_err(gsc->dev, "invalid mode: %d\n", ch->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* setup config structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) hwmon->chip.ops = &gsc_hwmon_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) hwmon->chip.info = hwmon->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) hwmon->info[0] = &hwmon->temp_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) hwmon->info[1] = &hwmon->in_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) hwmon->info[2] = &hwmon->fan_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) hwmon->temp_info.type = hwmon_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) hwmon->temp_info.config = hwmon->temp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) hwmon->in_info.type = hwmon_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) hwmon->in_info.config = hwmon->in_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) hwmon->fan_info.type = hwmon_fan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) hwmon->fan_info.config = hwmon->fan_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) groups = pdata->fan_base ? gsc_hwmon_groups : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) hwmon_dev = devm_hwmon_device_register_with_info(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) KBUILD_MODNAME, hwmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) &hwmon->chip, groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return PTR_ERR_OR_ZERO(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static const struct of_device_id gsc_hwmon_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) { .compatible = "gw,gsc-adc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static struct platform_driver gsc_hwmon_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .name = "gsc-hwmon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .of_match_table = gsc_hwmon_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .probe = gsc_hwmon_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) module_platform_driver(gsc_hwmon_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) MODULE_DESCRIPTION("GSC hardware monitor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) MODULE_LICENSE("GPL v2");