1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for Gateworks System Controller Hardware Monitor module
5 * Copyright (C) 2020 Gateworks Corporation
7 #include <linux/hwmon.h>
8 #include <linux/hwmon-sysfs.h>
9 #include <linux/mfd/gsc.h>
10 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/slab.h>
16 #include <linux/platform_data/gsc_hwmon.h>
18 #define GSC_HWMON_MAX_TEMP_CH 16
19 #define GSC_HWMON_MAX_IN_CH 16
20 #define GSC_HWMON_MAX_FAN_CH 16
22 #define GSC_HWMON_RESOLUTION 12
23 #define GSC_HWMON_VREF 2500
25 struct gsc_hwmon_data
{
27 struct gsc_hwmon_platform_data
*pdata
;
28 struct regmap
*regmap
;
29 const struct gsc_hwmon_channel
*temp_ch
[GSC_HWMON_MAX_TEMP_CH
];
30 const struct gsc_hwmon_channel
*in_ch
[GSC_HWMON_MAX_IN_CH
];
31 const struct gsc_hwmon_channel
*fan_ch
[GSC_HWMON_MAX_FAN_CH
];
32 u32 temp_config
[GSC_HWMON_MAX_TEMP_CH
+ 1];
33 u32 in_config
[GSC_HWMON_MAX_IN_CH
+ 1];
34 u32 fan_config
[GSC_HWMON_MAX_FAN_CH
+ 1];
35 struct hwmon_channel_info temp_info
;
36 struct hwmon_channel_info in_info
;
37 struct hwmon_channel_info fan_info
;
38 const struct hwmon_channel_info
*info
[4];
39 struct hwmon_chip_info chip
;
42 static const struct regmap_bus gsc_hwmon_regmap_bus
= {
44 .reg_write
= gsc_write
,
47 static const struct regmap_config gsc_hwmon_regmap_config
= {
50 .cache_type
= REGCACHE_NONE
,
53 static ssize_t
pwm_auto_point_temp_show(struct device
*dev
,
54 struct device_attribute
*devattr
,
57 struct gsc_hwmon_data
*hwmon
= dev_get_drvdata(dev
);
58 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
59 u8 reg
= hwmon
->pdata
->fan_base
+ (2 * attr
->index
);
63 ret
= regmap_bulk_read(hwmon
->regmap
, reg
, regs
, 2);
67 ret
= regs
[0] | regs
[1] << 8;
68 return sprintf(buf
, "%d\n", ret
* 10);
71 static ssize_t
pwm_auto_point_temp_store(struct device
*dev
,
72 struct device_attribute
*devattr
,
73 const char *buf
, size_t count
)
75 struct gsc_hwmon_data
*hwmon
= dev_get_drvdata(dev
);
76 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
77 u8 reg
= hwmon
->pdata
->fan_base
+ (2 * attr
->index
);
82 if (kstrtol(buf
, 10, &temp
))
85 temp
= clamp_val(temp
, 0, 100000);
86 temp
= DIV_ROUND_CLOSEST(temp
, 100);
88 regs
[0] = temp
& 0xff;
89 regs
[1] = (temp
>> 8) & 0xff;
90 err
= regmap_bulk_write(hwmon
->regmap
, reg
, regs
, 2);
97 static ssize_t
pwm_auto_point_pwm_show(struct device
*dev
,
98 struct device_attribute
*devattr
,
101 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
103 return sprintf(buf
, "%d\n", 255 * (50 + (attr
->index
* 10)));
106 static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm
, pwm_auto_point_pwm
, 0);
107 static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp
, pwm_auto_point_temp
, 0);
109 static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point2_pwm
, pwm_auto_point_pwm
, 1);
110 static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp
, pwm_auto_point_temp
, 1);
112 static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point3_pwm
, pwm_auto_point_pwm
, 2);
113 static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp
, pwm_auto_point_temp
, 2);
115 static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point4_pwm
, pwm_auto_point_pwm
, 3);
116 static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp
, pwm_auto_point_temp
, 3);
118 static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point5_pwm
, pwm_auto_point_pwm
, 4);
119 static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point5_temp
, pwm_auto_point_temp
, 4);
121 static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point6_pwm
, pwm_auto_point_pwm
, 5);
122 static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point6_temp
, pwm_auto_point_temp
, 5);
124 static struct attribute
*gsc_hwmon_attributes
[] = {
125 &sensor_dev_attr_pwm1_auto_point1_pwm
.dev_attr
.attr
,
126 &sensor_dev_attr_pwm1_auto_point1_temp
.dev_attr
.attr
,
127 &sensor_dev_attr_pwm1_auto_point2_pwm
.dev_attr
.attr
,
128 &sensor_dev_attr_pwm1_auto_point2_temp
.dev_attr
.attr
,
129 &sensor_dev_attr_pwm1_auto_point3_pwm
.dev_attr
.attr
,
130 &sensor_dev_attr_pwm1_auto_point3_temp
.dev_attr
.attr
,
131 &sensor_dev_attr_pwm1_auto_point4_pwm
.dev_attr
.attr
,
132 &sensor_dev_attr_pwm1_auto_point4_temp
.dev_attr
.attr
,
133 &sensor_dev_attr_pwm1_auto_point5_pwm
.dev_attr
.attr
,
134 &sensor_dev_attr_pwm1_auto_point5_temp
.dev_attr
.attr
,
135 &sensor_dev_attr_pwm1_auto_point6_pwm
.dev_attr
.attr
,
136 &sensor_dev_attr_pwm1_auto_point6_temp
.dev_attr
.attr
,
140 static const struct attribute_group gsc_hwmon_group
= {
141 .attrs
= gsc_hwmon_attributes
,
143 __ATTRIBUTE_GROUPS(gsc_hwmon
);
146 gsc_hwmon_read(struct device
*dev
, enum hwmon_sensor_types type
, u32 attr
,
147 int channel
, long *val
)
149 struct gsc_hwmon_data
*hwmon
= dev_get_drvdata(dev
);
150 const struct gsc_hwmon_channel
*ch
;
157 ch
= hwmon
->in_ch
[channel
];
160 ch
= hwmon
->temp_ch
[channel
];
163 ch
= hwmon
->fan_ch
[channel
];
169 sz
= (ch
->mode
== mode_voltage_24bit
) ? 3 : 2;
170 ret
= regmap_bulk_read(hwmon
->regmap
, ch
->reg
, buf
, sz
);
176 tmp
|= (buf
[sz
] << (8 * sz
));
179 case mode_temperature
:
182 tmp
*= 100; /* convert to millidegrees celsius */
184 case mode_voltage_raw
:
185 tmp
= clamp_val(tmp
, 0, BIT(GSC_HWMON_RESOLUTION
));
186 /* scale based on ref voltage and ADC resolution */
187 tmp
*= GSC_HWMON_VREF
;
188 tmp
>>= GSC_HWMON_RESOLUTION
;
189 /* scale based on optional voltage divider */
190 if (ch
->vdiv
[0] && ch
->vdiv
[1]) {
191 tmp
*= (ch
->vdiv
[0] + ch
->vdiv
[1]);
194 /* adjust by uV offset */
198 tmp
*= 30; /* convert to revolutions per minute */
200 case mode_voltage_24bit
:
201 case mode_voltage_16bit
:
202 /* no adjustment needed */
212 gsc_hwmon_read_string(struct device
*dev
, enum hwmon_sensor_types type
,
213 u32 attr
, int channel
, const char **buf
)
215 struct gsc_hwmon_data
*hwmon
= dev_get_drvdata(dev
);
219 *buf
= hwmon
->in_ch
[channel
]->name
;
222 *buf
= hwmon
->temp_ch
[channel
]->name
;
225 *buf
= hwmon
->fan_ch
[channel
]->name
;
234 static const struct hwmon_ops gsc_hwmon_ops
= {
236 .read
= gsc_hwmon_read
,
237 .read_string
= gsc_hwmon_read_string
,
240 static struct gsc_hwmon_platform_data
*
241 gsc_hwmon_get_devtree_pdata(struct device
*dev
)
243 struct gsc_hwmon_platform_data
*pdata
;
244 struct gsc_hwmon_channel
*ch
;
245 struct device_node
*fan
;
248 nchannels
= device_get_child_node_count(dev
);
250 return ERR_PTR(-ENODEV
);
252 pdata
= devm_kzalloc(dev
, struct_size(pdata
, channels
, nchannels
),
255 return ERR_PTR(-ENOMEM
);
256 pdata
->nchannels
= nchannels
;
258 /* fan controller base address */
259 of_node_get(dev
->parent
->of_node
);
260 fan
= of_find_compatible_node(dev
->parent
->of_node
, NULL
, "gw,gsc-fan");
261 if (fan
&& of_property_read_u32(fan
, "reg", &pdata
->fan_base
)) {
263 dev_err(dev
, "fan node without base\n");
264 return ERR_PTR(-EINVAL
);
269 ch
= pdata
->channels
;
270 /* allocate structures for channels and count instances of each type */
271 device_for_each_child_node_scoped(dev
, child
) {
272 if (fwnode_property_read_string(child
, "label", &ch
->name
)) {
273 dev_err(dev
, "channel without label\n");
274 return ERR_PTR(-EINVAL
);
276 if (fwnode_property_read_u32(child
, "reg", &ch
->reg
)) {
277 dev_err(dev
, "channel without reg\n");
278 return ERR_PTR(-EINVAL
);
280 if (fwnode_property_read_u32(child
, "gw,mode", &ch
->mode
)) {
281 dev_err(dev
, "channel without mode\n");
282 return ERR_PTR(-EINVAL
);
284 if (ch
->mode
> mode_max
) {
285 dev_err(dev
, "invalid channel mode\n");
286 return ERR_PTR(-EINVAL
);
289 if (!fwnode_property_read_u32(child
,
290 "gw,voltage-offset-microvolt",
292 ch
->mvoffset
/= 1000;
293 fwnode_property_read_u32_array(child
,
294 "gw,voltage-divider-ohms",
295 ch
->vdiv
, ARRAY_SIZE(ch
->vdiv
));
302 static int gsc_hwmon_probe(struct platform_device
*pdev
)
304 struct gsc_dev
*gsc
= dev_get_drvdata(pdev
->dev
.parent
);
305 struct device
*dev
= &pdev
->dev
;
306 struct device
*hwmon_dev
;
307 struct gsc_hwmon_platform_data
*pdata
= dev_get_platdata(dev
);
308 struct gsc_hwmon_data
*hwmon
;
309 const struct attribute_group
**groups
;
310 int i
, i_in
, i_temp
, i_fan
;
313 pdata
= gsc_hwmon_get_devtree_pdata(dev
);
315 return PTR_ERR(pdata
);
318 hwmon
= devm_kzalloc(dev
, sizeof(*hwmon
), GFP_KERNEL
);
322 hwmon
->pdata
= pdata
;
324 hwmon
->regmap
= devm_regmap_init(dev
, &gsc_hwmon_regmap_bus
,
326 &gsc_hwmon_regmap_config
);
327 if (IS_ERR(hwmon
->regmap
))
328 return PTR_ERR(hwmon
->regmap
);
330 for (i
= 0, i_in
= 0, i_temp
= 0, i_fan
= 0; i
< hwmon
->pdata
->nchannels
; i
++) {
331 const struct gsc_hwmon_channel
*ch
= &pdata
->channels
[i
];
334 case mode_temperature
:
335 if (i_temp
== GSC_HWMON_MAX_TEMP_CH
) {
336 dev_err(gsc
->dev
, "too many temp channels\n");
339 hwmon
->temp_ch
[i_temp
] = ch
;
340 hwmon
->temp_config
[i_temp
] = HWMON_T_INPUT
|
345 if (i_fan
== GSC_HWMON_MAX_FAN_CH
) {
346 dev_err(gsc
->dev
, "too many fan channels\n");
349 hwmon
->fan_ch
[i_fan
] = ch
;
350 hwmon
->fan_config
[i_fan
] = HWMON_F_INPUT
|
354 case mode_voltage_24bit
:
355 case mode_voltage_16bit
:
356 case mode_voltage_raw
:
357 if (i_in
== GSC_HWMON_MAX_IN_CH
) {
358 dev_err(gsc
->dev
, "too many input channels\n");
361 hwmon
->in_ch
[i_in
] = ch
;
362 hwmon
->in_config
[i_in
] =
363 HWMON_I_INPUT
| HWMON_I_LABEL
;
367 dev_err(gsc
->dev
, "invalid mode: %d\n", ch
->mode
);
372 /* setup config structures */
373 hwmon
->chip
.ops
= &gsc_hwmon_ops
;
374 hwmon
->chip
.info
= hwmon
->info
;
375 hwmon
->info
[0] = &hwmon
->temp_info
;
376 hwmon
->info
[1] = &hwmon
->in_info
;
377 hwmon
->info
[2] = &hwmon
->fan_info
;
378 hwmon
->temp_info
.type
= hwmon_temp
;
379 hwmon
->temp_info
.config
= hwmon
->temp_config
;
380 hwmon
->in_info
.type
= hwmon_in
;
381 hwmon
->in_info
.config
= hwmon
->in_config
;
382 hwmon
->fan_info
.type
= hwmon_fan
;
383 hwmon
->fan_info
.config
= hwmon
->fan_config
;
385 groups
= pdata
->fan_base
? gsc_hwmon_groups
: NULL
;
386 hwmon_dev
= devm_hwmon_device_register_with_info(dev
,
387 KBUILD_MODNAME
, hwmon
,
388 &hwmon
->chip
, groups
);
389 return PTR_ERR_OR_ZERO(hwmon_dev
);
392 static const struct of_device_id gsc_hwmon_of_match
[] = {
393 { .compatible
= "gw,gsc-adc", },
396 MODULE_DEVICE_TABLE(of
, gsc_hwmon_of_match
);
398 static struct platform_driver gsc_hwmon_driver
= {
401 .of_match_table
= gsc_hwmon_of_match
,
403 .probe
= gsc_hwmon_probe
,
406 module_platform_driver(gsc_hwmon_driver
);
408 MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>");
409 MODULE_DESCRIPTION("GSC hardware monitor driver");
410 MODULE_LICENSE("GPL v2");