xref: /openbmc/linux/drivers/hwmon/scmi-hwmon.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1b23688aeSSudeep Holla // SPDX-License-Identifier: GPL-2.0
2b23688aeSSudeep Holla /*
3b23688aeSSudeep Holla  * System Control and Management Interface(SCMI) based hwmon sensor driver
4b23688aeSSudeep Holla  *
5987bae41SCristian Marussi  * Copyright (C) 2018-2021 ARM Ltd.
6b23688aeSSudeep Holla  * Sudeep Holla <sudeep.holla@arm.com>
7b23688aeSSudeep Holla  */
8b23688aeSSudeep Holla 
9b23688aeSSudeep Holla #include <linux/hwmon.h>
10b23688aeSSudeep Holla #include <linux/module.h>
11b23688aeSSudeep Holla #include <linux/scmi_protocol.h>
12b23688aeSSudeep Holla #include <linux/slab.h>
13b23688aeSSudeep Holla #include <linux/sysfs.h>
14b23688aeSSudeep Holla #include <linux/thermal.h>
15b23688aeSSudeep Holla 
16987bae41SCristian Marussi static const struct scmi_sensor_proto_ops *sensor_ops;
17987bae41SCristian Marussi 
18b23688aeSSudeep Holla struct scmi_sensors {
19987bae41SCristian Marussi 	const struct scmi_protocol_handle *ph;
20b23688aeSSudeep Holla 	const struct scmi_sensor_info **info[hwmon_max];
21b23688aeSSudeep Holla };
22b23688aeSSudeep Holla 
23c4f68373SCristian Marussi struct scmi_thermal_sensor {
24c4f68373SCristian Marussi 	const struct scmi_protocol_handle *ph;
25c4f68373SCristian Marussi 	const struct scmi_sensor_info *info;
26c4f68373SCristian Marussi };
27c4f68373SCristian Marussi 
__pow10(u8 x)28ac778e62SFlorian Fainelli static inline u64 __pow10(u8 x)
29ac778e62SFlorian Fainelli {
30ac778e62SFlorian Fainelli 	u64 r = 1;
31ac778e62SFlorian Fainelli 
32ac778e62SFlorian Fainelli 	while (x--)
33ac778e62SFlorian Fainelli 		r *= 10;
34ac778e62SFlorian Fainelli 
35ac778e62SFlorian Fainelli 	return r;
36ac778e62SFlorian Fainelli }
37ac778e62SFlorian Fainelli 
scmi_hwmon_scale(const struct scmi_sensor_info * sensor,u64 * value)38ac778e62SFlorian Fainelli static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value)
39ac778e62SFlorian Fainelli {
40d7971d57SCristian Marussi 	int scale = sensor->scale;
41ac778e62SFlorian Fainelli 	u64 f;
42ac778e62SFlorian Fainelli 
43ac778e62SFlorian Fainelli 	switch (sensor->type) {
44ac778e62SFlorian Fainelli 	case TEMPERATURE_C:
45ac778e62SFlorian Fainelli 	case VOLTAGE:
46ac778e62SFlorian Fainelli 	case CURRENT:
47ac778e62SFlorian Fainelli 		scale += 3;
48ac778e62SFlorian Fainelli 		break;
49ac778e62SFlorian Fainelli 	case POWER:
50ac778e62SFlorian Fainelli 	case ENERGY:
51ac778e62SFlorian Fainelli 		scale += 6;
52ac778e62SFlorian Fainelli 		break;
53ac778e62SFlorian Fainelli 	default:
54ac778e62SFlorian Fainelli 		break;
55ac778e62SFlorian Fainelli 	}
56ac778e62SFlorian Fainelli 
57ac778e62SFlorian Fainelli 	if (scale == 0)
58ac778e62SFlorian Fainelli 		return 0;
59ac778e62SFlorian Fainelli 
60ac778e62SFlorian Fainelli 	if (abs(scale) > 19)
61ac778e62SFlorian Fainelli 		return -E2BIG;
62ac778e62SFlorian Fainelli 
63ac778e62SFlorian Fainelli 	f = __pow10(abs(scale));
64ac778e62SFlorian Fainelli 	if (scale > 0)
65ac778e62SFlorian Fainelli 		*value *= f;
66ac778e62SFlorian Fainelli 	else
67ac778e62SFlorian Fainelli 		*value = div64_u64(*value, f);
68ac778e62SFlorian Fainelli 
69ac778e62SFlorian Fainelli 	return 0;
70ac778e62SFlorian Fainelli }
71ac778e62SFlorian Fainelli 
scmi_hwmon_read_scaled_value(const struct scmi_protocol_handle * ph,const struct scmi_sensor_info * sensor,long * val)72c4f68373SCristian Marussi static int scmi_hwmon_read_scaled_value(const struct scmi_protocol_handle *ph,
73c4f68373SCristian Marussi 					const struct scmi_sensor_info *sensor,
74c4f68373SCristian Marussi 					long *val)
75b23688aeSSudeep Holla {
76b23688aeSSudeep Holla 	int ret;
77b23688aeSSudeep Holla 	u64 value;
78b23688aeSSudeep Holla 
79c4f68373SCristian Marussi 	ret = sensor_ops->reading_get(ph, sensor->id, &value);
80ac778e62SFlorian Fainelli 	if (ret)
81ac778e62SFlorian Fainelli 		return ret;
82ac778e62SFlorian Fainelli 
83ac778e62SFlorian Fainelli 	ret = scmi_hwmon_scale(sensor, &value);
84b23688aeSSudeep Holla 	if (!ret)
85b23688aeSSudeep Holla 		*val = value;
86b23688aeSSudeep Holla 
87b23688aeSSudeep Holla 	return ret;
88b23688aeSSudeep Holla }
89b23688aeSSudeep Holla 
scmi_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)90c4f68373SCristian Marussi static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
91c4f68373SCristian Marussi 			   u32 attr, int channel, long *val)
92c4f68373SCristian Marussi {
93c4f68373SCristian Marussi 	const struct scmi_sensor_info *sensor;
94c4f68373SCristian Marussi 	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
95c4f68373SCristian Marussi 
96c4f68373SCristian Marussi 	sensor = *(scmi_sensors->info[type] + channel);
97c4f68373SCristian Marussi 
98c4f68373SCristian Marussi 	return scmi_hwmon_read_scaled_value(scmi_sensors->ph, sensor, val);
99c4f68373SCristian Marussi }
100c4f68373SCristian Marussi 
101b23688aeSSudeep Holla static int
scmi_hwmon_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)102b23688aeSSudeep Holla scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
103b23688aeSSudeep Holla 		       u32 attr, int channel, const char **str)
104b23688aeSSudeep Holla {
105b23688aeSSudeep Holla 	const struct scmi_sensor_info *sensor;
106b23688aeSSudeep Holla 	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
107b23688aeSSudeep Holla 
108b23688aeSSudeep Holla 	sensor = *(scmi_sensors->info[type] + channel);
109b23688aeSSudeep Holla 	*str = sensor->name;
110b23688aeSSudeep Holla 
111b23688aeSSudeep Holla 	return 0;
112b23688aeSSudeep Holla }
113b23688aeSSudeep Holla 
114b23688aeSSudeep Holla static umode_t
scmi_hwmon_is_visible(const void * drvdata,enum hwmon_sensor_types type,u32 attr,int channel)115b23688aeSSudeep Holla scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
116b23688aeSSudeep Holla 		      u32 attr, int channel)
117b23688aeSSudeep Holla {
118b23688aeSSudeep Holla 	const struct scmi_sensor_info *sensor;
119b23688aeSSudeep Holla 	const struct scmi_sensors *scmi_sensors = drvdata;
120b23688aeSSudeep Holla 
121b23688aeSSudeep Holla 	sensor = *(scmi_sensors->info[type] + channel);
122a31796c3SNathan Chancellor 	if (sensor)
123626c4a06SGuenter Roeck 		return 0444;
124b23688aeSSudeep Holla 
125b23688aeSSudeep Holla 	return 0;
126b23688aeSSudeep Holla }
127b23688aeSSudeep Holla 
128b23688aeSSudeep Holla static const struct hwmon_ops scmi_hwmon_ops = {
129b23688aeSSudeep Holla 	.is_visible = scmi_hwmon_is_visible,
130b23688aeSSudeep Holla 	.read = scmi_hwmon_read,
131b23688aeSSudeep Holla 	.read_string = scmi_hwmon_read_string,
132b23688aeSSudeep Holla };
133b23688aeSSudeep Holla 
134b23688aeSSudeep Holla static struct hwmon_chip_info scmi_chip_info = {
135b23688aeSSudeep Holla 	.ops = &scmi_hwmon_ops,
136b23688aeSSudeep Holla 	.info = NULL,
137b23688aeSSudeep Holla };
138b23688aeSSudeep Holla 
scmi_hwmon_thermal_get_temp(struct thermal_zone_device * tz,int * temp)139c4f68373SCristian Marussi static int scmi_hwmon_thermal_get_temp(struct thermal_zone_device *tz,
140c4f68373SCristian Marussi 				       int *temp)
141c4f68373SCristian Marussi {
142c4f68373SCristian Marussi 	int ret;
143c4f68373SCristian Marussi 	long value;
1440ce637a5SDaniel Lezcano 	struct scmi_thermal_sensor *th_sensor = thermal_zone_device_priv(tz);
145c4f68373SCristian Marussi 
146c4f68373SCristian Marussi 	ret = scmi_hwmon_read_scaled_value(th_sensor->ph, th_sensor->info,
147c4f68373SCristian Marussi 					   &value);
148c4f68373SCristian Marussi 	if (!ret)
149c4f68373SCristian Marussi 		*temp = value;
150c4f68373SCristian Marussi 
151c4f68373SCristian Marussi 	return ret;
152c4f68373SCristian Marussi }
153c4f68373SCristian Marussi 
154c4f68373SCristian Marussi static const struct thermal_zone_device_ops scmi_hwmon_thermal_ops = {
155c4f68373SCristian Marussi 	.get_temp = scmi_hwmon_thermal_get_temp,
156c4f68373SCristian Marussi };
157c4f68373SCristian Marussi 
scmi_hwmon_add_chan_info(struct hwmon_channel_info * scmi_hwmon_chan,struct device * dev,int num,enum hwmon_sensor_types type,u32 config)158b23688aeSSudeep Holla static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
159b23688aeSSudeep Holla 				    struct device *dev, int num,
160b23688aeSSudeep Holla 				    enum hwmon_sensor_types type, u32 config)
161b23688aeSSudeep Holla {
162b23688aeSSudeep Holla 	int i;
163b23688aeSSudeep Holla 	u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
164b23688aeSSudeep Holla 
165b23688aeSSudeep Holla 	if (!cfg)
166b23688aeSSudeep Holla 		return -ENOMEM;
167b23688aeSSudeep Holla 
168b23688aeSSudeep Holla 	scmi_hwmon_chan->type = type;
169b23688aeSSudeep Holla 	scmi_hwmon_chan->config = cfg;
170b23688aeSSudeep Holla 	for (i = 0; i < num; i++, cfg++)
171b23688aeSSudeep Holla 		*cfg = config;
172b23688aeSSudeep Holla 
173b23688aeSSudeep Holla 	return 0;
174b23688aeSSudeep Holla }
175b23688aeSSudeep Holla 
176b23688aeSSudeep Holla static enum hwmon_sensor_types scmi_types[] = {
177b23688aeSSudeep Holla 	[TEMPERATURE_C] = hwmon_temp,
178b23688aeSSudeep Holla 	[VOLTAGE] = hwmon_in,
179b23688aeSSudeep Holla 	[CURRENT] = hwmon_curr,
180b23688aeSSudeep Holla 	[POWER] = hwmon_power,
181b23688aeSSudeep Holla 	[ENERGY] = hwmon_energy,
182b23688aeSSudeep Holla };
183b23688aeSSudeep Holla 
1843ce17cd2SCristian Marussi static u32 hwmon_attributes[hwmon_max] = {
185b23688aeSSudeep Holla 	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
186b23688aeSSudeep Holla 	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
187b23688aeSSudeep Holla 	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
188b23688aeSSudeep Holla 	[hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
189b23688aeSSudeep Holla 	[hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
190b23688aeSSudeep Holla };
191b23688aeSSudeep Holla 
scmi_thermal_sensor_register(struct device * dev,const struct scmi_protocol_handle * ph,const struct scmi_sensor_info * sensor)192c4f68373SCristian Marussi static int scmi_thermal_sensor_register(struct device *dev,
193c4f68373SCristian Marussi 					const struct scmi_protocol_handle *ph,
194c4f68373SCristian Marussi 					const struct scmi_sensor_info *sensor)
195c4f68373SCristian Marussi {
196c4f68373SCristian Marussi 	struct scmi_thermal_sensor *th_sensor;
197c4f68373SCristian Marussi 	struct thermal_zone_device *tzd;
198c4f68373SCristian Marussi 
199c4f68373SCristian Marussi 	th_sensor = devm_kzalloc(dev, sizeof(*th_sensor), GFP_KERNEL);
200c4f68373SCristian Marussi 	if (!th_sensor)
201c4f68373SCristian Marussi 		return -ENOMEM;
202c4f68373SCristian Marussi 
203c4f68373SCristian Marussi 	th_sensor->ph = ph;
204c4f68373SCristian Marussi 	th_sensor->info = sensor;
205c4f68373SCristian Marussi 
206c4f68373SCristian Marussi 	/*
207c4f68373SCristian Marussi 	 * Try to register a temperature sensor with the Thermal Framework:
208c4f68373SCristian Marussi 	 * skip sensors not defined as part of any thermal zone (-ENODEV) but
209c4f68373SCristian Marussi 	 * report any other errors related to misconfigured zones/sensors.
210c4f68373SCristian Marussi 	 */
211c4f68373SCristian Marussi 	tzd = devm_thermal_of_zone_register(dev, th_sensor->info->id, th_sensor,
212c4f68373SCristian Marussi 					    &scmi_hwmon_thermal_ops);
213c4f68373SCristian Marussi 	if (IS_ERR(tzd)) {
214c4f68373SCristian Marussi 		devm_kfree(dev, th_sensor);
215c4f68373SCristian Marussi 
216c4f68373SCristian Marussi 		if (PTR_ERR(tzd) != -ENODEV)
217c4f68373SCristian Marussi 			return PTR_ERR(tzd);
218c4f68373SCristian Marussi 
219c4f68373SCristian Marussi 		dev_dbg(dev, "Sensor '%s' not attached to any thermal zone.\n",
220c4f68373SCristian Marussi 			sensor->name);
221c4f68373SCristian Marussi 	} else {
222c4f68373SCristian Marussi 		dev_dbg(dev, "Sensor '%s' attached to thermal zone ID:%d\n",
223*3034f859SDaniel Lezcano 			sensor->name, thermal_zone_device_id(tzd));
224c4f68373SCristian Marussi 	}
225c4f68373SCristian Marussi 
226c4f68373SCristian Marussi 	return 0;
227c4f68373SCristian Marussi }
228c4f68373SCristian Marussi 
scmi_hwmon_probe(struct scmi_device * sdev)229b23688aeSSudeep Holla static int scmi_hwmon_probe(struct scmi_device *sdev)
230b23688aeSSudeep Holla {
231b23688aeSSudeep Holla 	int i, idx;
232b23688aeSSudeep Holla 	u16 nr_sensors;
233b23688aeSSudeep Holla 	enum hwmon_sensor_types type;
234b23688aeSSudeep Holla 	struct scmi_sensors *scmi_sensors;
235b23688aeSSudeep Holla 	const struct scmi_sensor_info *sensor;
236c4f68373SCristian Marussi 	int nr_count[hwmon_max] = {0}, nr_types = 0, nr_count_temp = 0;
237b23688aeSSudeep Holla 	const struct hwmon_chip_info *chip_info;
238b23688aeSSudeep Holla 	struct device *hwdev, *dev = &sdev->dev;
239b23688aeSSudeep Holla 	struct hwmon_channel_info *scmi_hwmon_chan;
240b23688aeSSudeep Holla 	const struct hwmon_channel_info **ptr_scmi_ci;
241b23688aeSSudeep Holla 	const struct scmi_handle *handle = sdev->handle;
242987bae41SCristian Marussi 	struct scmi_protocol_handle *ph;
243b23688aeSSudeep Holla 
244987bae41SCristian Marussi 	if (!handle)
245b23688aeSSudeep Holla 		return -ENODEV;
246b23688aeSSudeep Holla 
247987bae41SCristian Marussi 	sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
248987bae41SCristian Marussi 	if (IS_ERR(sensor_ops))
249987bae41SCristian Marussi 		return PTR_ERR(sensor_ops);
250987bae41SCristian Marussi 
251987bae41SCristian Marussi 	nr_sensors = sensor_ops->count_get(ph);
252b23688aeSSudeep Holla 	if (!nr_sensors)
253b23688aeSSudeep Holla 		return -EIO;
254b23688aeSSudeep Holla 
255b23688aeSSudeep Holla 	scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
256b23688aeSSudeep Holla 	if (!scmi_sensors)
257b23688aeSSudeep Holla 		return -ENOMEM;
258b23688aeSSudeep Holla 
259987bae41SCristian Marussi 	scmi_sensors->ph = ph;
260b23688aeSSudeep Holla 
261b23688aeSSudeep Holla 	for (i = 0; i < nr_sensors; i++) {
262987bae41SCristian Marussi 		sensor = sensor_ops->info_get(ph, i);
263b23688aeSSudeep Holla 		if (!sensor)
264c09880ceSSudeep Holla 			return -EINVAL;
265b23688aeSSudeep Holla 
266b23688aeSSudeep Holla 		switch (sensor->type) {
267b23688aeSSudeep Holla 		case TEMPERATURE_C:
268b23688aeSSudeep Holla 		case VOLTAGE:
269b23688aeSSudeep Holla 		case CURRENT:
270b23688aeSSudeep Holla 		case POWER:
271b23688aeSSudeep Holla 		case ENERGY:
272b23688aeSSudeep Holla 			type = scmi_types[sensor->type];
273b23688aeSSudeep Holla 			if (!nr_count[type])
274b23688aeSSudeep Holla 				nr_types++;
275b23688aeSSudeep Holla 			nr_count[type]++;
276b23688aeSSudeep Holla 			break;
277b23688aeSSudeep Holla 		}
278b23688aeSSudeep Holla 	}
279b23688aeSSudeep Holla 
280c4f68373SCristian Marussi 	if (nr_count[hwmon_temp])
281c4f68373SCristian Marussi 		nr_count_temp = nr_count[hwmon_temp];
282b23688aeSSudeep Holla 
283b23688aeSSudeep Holla 	scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
284b23688aeSSudeep Holla 				       GFP_KERNEL);
285b23688aeSSudeep Holla 	if (!scmi_hwmon_chan)
286b23688aeSSudeep Holla 		return -ENOMEM;
287b23688aeSSudeep Holla 
288b23688aeSSudeep Holla 	ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
289b23688aeSSudeep Holla 				   GFP_KERNEL);
290b23688aeSSudeep Holla 	if (!ptr_scmi_ci)
291b23688aeSSudeep Holla 		return -ENOMEM;
292b23688aeSSudeep Holla 
293b23688aeSSudeep Holla 	scmi_chip_info.info = ptr_scmi_ci;
294b23688aeSSudeep Holla 	chip_info = &scmi_chip_info;
295b23688aeSSudeep Holla 
296f18a36cfSSudeep Holla 	for (type = 0; type < hwmon_max; type++) {
297f18a36cfSSudeep Holla 		if (!nr_count[type])
298f18a36cfSSudeep Holla 			continue;
299f18a36cfSSudeep Holla 
300b23688aeSSudeep Holla 		scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
301b23688aeSSudeep Holla 					 type, hwmon_attributes[type]);
302b23688aeSSudeep Holla 		*ptr_scmi_ci++ = scmi_hwmon_chan++;
303b23688aeSSudeep Holla 
304b23688aeSSudeep Holla 		scmi_sensors->info[type] =
305b23688aeSSudeep Holla 			devm_kcalloc(dev, nr_count[type],
306b23688aeSSudeep Holla 				     sizeof(*scmi_sensors->info), GFP_KERNEL);
307b23688aeSSudeep Holla 		if (!scmi_sensors->info[type])
308b23688aeSSudeep Holla 			return -ENOMEM;
309b23688aeSSudeep Holla 	}
310b23688aeSSudeep Holla 
311b23688aeSSudeep Holla 	for (i = nr_sensors - 1; i >= 0 ; i--) {
312987bae41SCristian Marussi 		sensor = sensor_ops->info_get(ph, i);
313b23688aeSSudeep Holla 		if (!sensor)
314b23688aeSSudeep Holla 			continue;
315b23688aeSSudeep Holla 
316b23688aeSSudeep Holla 		switch (sensor->type) {
317b23688aeSSudeep Holla 		case TEMPERATURE_C:
318b23688aeSSudeep Holla 		case VOLTAGE:
319b23688aeSSudeep Holla 		case CURRENT:
320b23688aeSSudeep Holla 		case POWER:
321b23688aeSSudeep Holla 		case ENERGY:
322b23688aeSSudeep Holla 			type = scmi_types[sensor->type];
323b23688aeSSudeep Holla 			idx = --nr_count[type];
324b23688aeSSudeep Holla 			*(scmi_sensors->info[type] + idx) = sensor;
325b23688aeSSudeep Holla 			break;
326b23688aeSSudeep Holla 		}
327b23688aeSSudeep Holla 	}
328b23688aeSSudeep Holla 
329b23688aeSSudeep Holla 	hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
330b23688aeSSudeep Holla 						     scmi_sensors, chip_info,
331b23688aeSSudeep Holla 						     NULL);
332c4f68373SCristian Marussi 	if (IS_ERR(hwdev))
333c4f68373SCristian Marussi 		return PTR_ERR(hwdev);
334b23688aeSSudeep Holla 
335c4f68373SCristian Marussi 	for (i = 0; i < nr_count_temp; i++) {
336c4f68373SCristian Marussi 		int ret;
337c4f68373SCristian Marussi 
338c4f68373SCristian Marussi 		sensor = *(scmi_sensors->info[hwmon_temp] + i);
339c4f68373SCristian Marussi 		if (!sensor)
340c4f68373SCristian Marussi 			continue;
341c4f68373SCristian Marussi 
342c4f68373SCristian Marussi 		/*
343c4f68373SCristian Marussi 		 * Warn on any misconfiguration related to thermal zones but
344c4f68373SCristian Marussi 		 * bail out of probing only on memory errors.
345c4f68373SCristian Marussi 		 */
346c4f68373SCristian Marussi 		ret = scmi_thermal_sensor_register(dev, ph, sensor);
347c4f68373SCristian Marussi 		if (ret) {
348c4f68373SCristian Marussi 			if (ret == -ENOMEM)
349c4f68373SCristian Marussi 				return ret;
350c4f68373SCristian Marussi 			dev_warn(dev,
351c4f68373SCristian Marussi 				 "Thermal zone misconfigured for %s. err=%d\n",
352c4f68373SCristian Marussi 				 sensor->name, ret);
353c4f68373SCristian Marussi 		}
354c4f68373SCristian Marussi 	}
355c4f68373SCristian Marussi 
356c4f68373SCristian Marussi 	return 0;
357b23688aeSSudeep Holla }
358b23688aeSSudeep Holla 
359b23688aeSSudeep Holla static const struct scmi_device_id scmi_id_table[] = {
360b017b279SSudeep Holla 	{ SCMI_PROTOCOL_SENSOR, "hwmon" },
361b23688aeSSudeep Holla 	{ },
362b23688aeSSudeep Holla };
363b23688aeSSudeep Holla MODULE_DEVICE_TABLE(scmi, scmi_id_table);
364b23688aeSSudeep Holla 
365b23688aeSSudeep Holla static struct scmi_driver scmi_hwmon_drv = {
366b23688aeSSudeep Holla 	.name		= "scmi-hwmon",
367b23688aeSSudeep Holla 	.probe		= scmi_hwmon_probe,
368b23688aeSSudeep Holla 	.id_table	= scmi_id_table,
369b23688aeSSudeep Holla };
370b23688aeSSudeep Holla module_scmi_driver(scmi_hwmon_drv);
371b23688aeSSudeep Holla 
372b23688aeSSudeep Holla MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
373b23688aeSSudeep Holla MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
374b23688aeSSudeep Holla MODULE_LICENSE("GPL v2");
375