1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright 2016-2019 HabanaLabs, Ltd.
5  * All Rights Reserved.
6  */
7 
8 #include "habanalabs.h"
9 
10 #include <linux/pci.h>
11 #include <linux/hwmon.h>
12 
13 #define SENSORS_PKT_TIMEOUT		1000000	/* 1s */
14 #define HWMON_NR_SENSOR_TYPES		(hwmon_pwm + 1)
15 
hl_build_hwmon_channel_info(struct hl_device * hdev,struct armcp_sensor * sensors_arr)16 int hl_build_hwmon_channel_info(struct hl_device *hdev,
17 				struct armcp_sensor *sensors_arr)
18 {
19 	u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
20 	u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
21 	u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
22 	struct hwmon_channel_info **channels_info;
23 	u32 num_sensors_for_type, num_active_sensor_types = 0,
24 			arr_size = 0, *curr_arr;
25 	enum hwmon_sensor_types type;
26 	int rc, i, j;
27 
28 	for (i = 0 ; i < ARMCP_MAX_SENSORS ; i++) {
29 		type = le32_to_cpu(sensors_arr[i].type);
30 
31 		if ((type == 0) && (sensors_arr[i].flags == 0))
32 			break;
33 
34 		if (type >= HWMON_NR_SENSOR_TYPES) {
35 			dev_err(hdev->dev,
36 				"Got wrong sensor type %d from device\n", type);
37 			return -EINVAL;
38 		}
39 
40 		counts[type]++;
41 		arr_size++;
42 	}
43 
44 	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
45 		if (counts[i] == 0)
46 			continue;
47 
48 		num_sensors_for_type = counts[i] + 1;
49 		curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr),
50 				GFP_KERNEL);
51 		if (!curr_arr) {
52 			rc = -ENOMEM;
53 			goto sensors_type_err;
54 		}
55 
56 		num_active_sensor_types++;
57 		sensors_by_type[i] = curr_arr;
58 	}
59 
60 	for (i = 0 ; i < arr_size ; i++) {
61 		type = le32_to_cpu(sensors_arr[i].type);
62 		curr_arr = sensors_by_type[type];
63 		curr_arr[sensors_by_type_next_index[type]++] =
64 				le32_to_cpu(sensors_arr[i].flags);
65 	}
66 
67 	channels_info = kcalloc(num_active_sensor_types + 1,
68 			sizeof(*channels_info), GFP_KERNEL);
69 	if (!channels_info) {
70 		rc = -ENOMEM;
71 		goto channels_info_array_err;
72 	}
73 
74 	for (i = 0 ; i < num_active_sensor_types ; i++) {
75 		channels_info[i] = kzalloc(sizeof(*channels_info[i]),
76 				GFP_KERNEL);
77 		if (!channels_info[i]) {
78 			rc = -ENOMEM;
79 			goto channel_info_err;
80 		}
81 	}
82 
83 	for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
84 		if (!sensors_by_type[i])
85 			continue;
86 
87 		channels_info[j]->type = i;
88 		channels_info[j]->config = sensors_by_type[i];
89 		j++;
90 	}
91 
92 	hdev->hl_chip_info->info =
93 			(const struct hwmon_channel_info **)channels_info;
94 
95 	return 0;
96 
97 channel_info_err:
98 	for (i = 0 ; i < num_active_sensor_types ; i++)
99 		if (channels_info[i]) {
100 			kfree(channels_info[i]->config);
101 			kfree(channels_info[i]);
102 		}
103 	kfree(channels_info);
104 channels_info_array_err:
105 sensors_type_err:
106 	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
107 		kfree(sensors_by_type[i]);
108 
109 	return rc;
110 }
111 
hl_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)112 static int hl_read(struct device *dev, enum hwmon_sensor_types type,
113 			u32 attr, int channel, long *val)
114 {
115 	struct hl_device *hdev = dev_get_drvdata(dev);
116 
117 	if (hl_device_disabled_or_in_reset(hdev))
118 		return -ENODEV;
119 
120 	switch (type) {
121 	case hwmon_temp:
122 		switch (attr) {
123 		case hwmon_temp_input:
124 		case hwmon_temp_max:
125 		case hwmon_temp_crit:
126 		case hwmon_temp_max_hyst:
127 		case hwmon_temp_crit_hyst:
128 			break;
129 		default:
130 			return -EINVAL;
131 		}
132 
133 		*val = hl_get_temperature(hdev, channel, attr);
134 		break;
135 	case hwmon_in:
136 		switch (attr) {
137 		case hwmon_in_input:
138 		case hwmon_in_min:
139 		case hwmon_in_max:
140 			break;
141 		default:
142 			return -EINVAL;
143 		}
144 
145 		*val = hl_get_voltage(hdev, channel, attr);
146 		break;
147 	case hwmon_curr:
148 		switch (attr) {
149 		case hwmon_curr_input:
150 		case hwmon_curr_min:
151 		case hwmon_curr_max:
152 			break;
153 		default:
154 			return -EINVAL;
155 		}
156 
157 		*val = hl_get_current(hdev, channel, attr);
158 		break;
159 	case hwmon_fan:
160 		switch (attr) {
161 		case hwmon_fan_input:
162 		case hwmon_fan_min:
163 		case hwmon_fan_max:
164 			break;
165 		default:
166 			return -EINVAL;
167 		}
168 		*val = hl_get_fan_speed(hdev, channel, attr);
169 		break;
170 	case hwmon_pwm:
171 		switch (attr) {
172 		case hwmon_pwm_input:
173 		case hwmon_pwm_enable:
174 			break;
175 		default:
176 			return -EINVAL;
177 		}
178 		*val = hl_get_pwm_info(hdev, channel, attr);
179 		break;
180 	default:
181 		return -EINVAL;
182 	}
183 	return 0;
184 }
185 
hl_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)186 static int hl_write(struct device *dev, enum hwmon_sensor_types type,
187 			u32 attr, int channel, long val)
188 {
189 	struct hl_device *hdev = dev_get_drvdata(dev);
190 
191 	if (hl_device_disabled_or_in_reset(hdev))
192 		return -ENODEV;
193 
194 	switch (type) {
195 	case hwmon_pwm:
196 		switch (attr) {
197 		case hwmon_pwm_input:
198 		case hwmon_pwm_enable:
199 			break;
200 		default:
201 			return -EINVAL;
202 		}
203 		hl_set_pwm_info(hdev, channel, attr, val);
204 		break;
205 	default:
206 		return -EINVAL;
207 	}
208 	return 0;
209 }
210 
hl_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)211 static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
212 				u32 attr, int channel)
213 {
214 	switch (type) {
215 	case hwmon_temp:
216 		switch (attr) {
217 		case hwmon_temp_input:
218 		case hwmon_temp_max:
219 		case hwmon_temp_max_hyst:
220 		case hwmon_temp_crit:
221 		case hwmon_temp_crit_hyst:
222 			return 0444;
223 		}
224 		break;
225 	case hwmon_in:
226 		switch (attr) {
227 		case hwmon_in_input:
228 		case hwmon_in_min:
229 		case hwmon_in_max:
230 			return 0444;
231 		}
232 		break;
233 	case hwmon_curr:
234 		switch (attr) {
235 		case hwmon_curr_input:
236 		case hwmon_curr_min:
237 		case hwmon_curr_max:
238 			return 0444;
239 		}
240 		break;
241 	case hwmon_fan:
242 		switch (attr) {
243 		case hwmon_fan_input:
244 		case hwmon_fan_min:
245 		case hwmon_fan_max:
246 			return 0444;
247 		}
248 		break;
249 	case hwmon_pwm:
250 		switch (attr) {
251 		case hwmon_pwm_input:
252 		case hwmon_pwm_enable:
253 			return 0644;
254 		}
255 		break;
256 	default:
257 		break;
258 	}
259 	return 0;
260 }
261 
262 static const struct hwmon_ops hl_hwmon_ops = {
263 	.is_visible = hl_is_visible,
264 	.read = hl_read,
265 	.write = hl_write
266 };
267 
hl_get_temperature(struct hl_device * hdev,int sensor_index,u32 attr)268 long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr)
269 {
270 	struct armcp_packet pkt;
271 	long result;
272 	int rc;
273 
274 	memset(&pkt, 0, sizeof(pkt));
275 
276 	pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEMPERATURE_GET <<
277 				ARMCP_PKT_CTL_OPCODE_SHIFT);
278 	pkt.sensor_index = __cpu_to_le16(sensor_index);
279 	pkt.type = __cpu_to_le16(attr);
280 
281 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
282 			SENSORS_PKT_TIMEOUT, &result);
283 
284 	if (rc) {
285 		dev_err(hdev->dev,
286 			"Failed to get temperature from sensor %d, error %d\n",
287 			sensor_index, rc);
288 		result = 0;
289 	}
290 
291 	return result;
292 }
293 
hl_get_voltage(struct hl_device * hdev,int sensor_index,u32 attr)294 long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr)
295 {
296 	struct armcp_packet pkt;
297 	long result;
298 	int rc;
299 
300 	memset(&pkt, 0, sizeof(pkt));
301 
302 	pkt.ctl = cpu_to_le32(ARMCP_PACKET_VOLTAGE_GET <<
303 				ARMCP_PKT_CTL_OPCODE_SHIFT);
304 	pkt.sensor_index = __cpu_to_le16(sensor_index);
305 	pkt.type = __cpu_to_le16(attr);
306 
307 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
308 					SENSORS_PKT_TIMEOUT, &result);
309 
310 	if (rc) {
311 		dev_err(hdev->dev,
312 			"Failed to get voltage from sensor %d, error %d\n",
313 			sensor_index, rc);
314 		result = 0;
315 	}
316 
317 	return result;
318 }
319 
hl_get_current(struct hl_device * hdev,int sensor_index,u32 attr)320 long hl_get_current(struct hl_device *hdev, int sensor_index, u32 attr)
321 {
322 	struct armcp_packet pkt;
323 	long result;
324 	int rc;
325 
326 	memset(&pkt, 0, sizeof(pkt));
327 
328 	pkt.ctl = cpu_to_le32(ARMCP_PACKET_CURRENT_GET <<
329 				ARMCP_PKT_CTL_OPCODE_SHIFT);
330 	pkt.sensor_index = __cpu_to_le16(sensor_index);
331 	pkt.type = __cpu_to_le16(attr);
332 
333 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
334 					SENSORS_PKT_TIMEOUT, &result);
335 
336 	if (rc) {
337 		dev_err(hdev->dev,
338 			"Failed to get current from sensor %d, error %d\n",
339 			sensor_index, rc);
340 		result = 0;
341 	}
342 
343 	return result;
344 }
345 
hl_get_fan_speed(struct hl_device * hdev,int sensor_index,u32 attr)346 long hl_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr)
347 {
348 	struct armcp_packet pkt;
349 	long result;
350 	int rc;
351 
352 	memset(&pkt, 0, sizeof(pkt));
353 
354 	pkt.ctl = cpu_to_le32(ARMCP_PACKET_FAN_SPEED_GET <<
355 				ARMCP_PKT_CTL_OPCODE_SHIFT);
356 	pkt.sensor_index = __cpu_to_le16(sensor_index);
357 	pkt.type = __cpu_to_le16(attr);
358 
359 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
360 					SENSORS_PKT_TIMEOUT, &result);
361 
362 	if (rc) {
363 		dev_err(hdev->dev,
364 			"Failed to get fan speed from sensor %d, error %d\n",
365 			sensor_index, rc);
366 		result = 0;
367 	}
368 
369 	return result;
370 }
371 
hl_get_pwm_info(struct hl_device * hdev,int sensor_index,u32 attr)372 long hl_get_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr)
373 {
374 	struct armcp_packet pkt;
375 	long result;
376 	int rc;
377 
378 	memset(&pkt, 0, sizeof(pkt));
379 
380 	pkt.ctl = cpu_to_le32(ARMCP_PACKET_PWM_GET <<
381 				ARMCP_PKT_CTL_OPCODE_SHIFT);
382 	pkt.sensor_index = __cpu_to_le16(sensor_index);
383 	pkt.type = __cpu_to_le16(attr);
384 
385 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
386 					SENSORS_PKT_TIMEOUT, &result);
387 
388 	if (rc) {
389 		dev_err(hdev->dev,
390 			"Failed to get pwm info from sensor %d, error %d\n",
391 			sensor_index, rc);
392 		result = 0;
393 	}
394 
395 	return result;
396 }
397 
hl_set_pwm_info(struct hl_device * hdev,int sensor_index,u32 attr,long value)398 void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
399 			long value)
400 {
401 	struct armcp_packet pkt;
402 	int rc;
403 
404 	memset(&pkt, 0, sizeof(pkt));
405 
406 	pkt.ctl = cpu_to_le32(ARMCP_PACKET_PWM_SET <<
407 				ARMCP_PKT_CTL_OPCODE_SHIFT);
408 	pkt.sensor_index = __cpu_to_le16(sensor_index);
409 	pkt.type = __cpu_to_le16(attr);
410 	pkt.value = cpu_to_le64(value);
411 
412 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
413 					SENSORS_PKT_TIMEOUT, NULL);
414 
415 	if (rc)
416 		dev_err(hdev->dev,
417 			"Failed to set pwm info to sensor %d, error %d\n",
418 			sensor_index, rc);
419 }
420 
hl_hwmon_init(struct hl_device * hdev)421 int hl_hwmon_init(struct hl_device *hdev)
422 {
423 	struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
424 	struct asic_fixed_properties *prop = &hdev->asic_prop;
425 	int rc;
426 
427 	if ((hdev->hwmon_initialized) || !(hdev->fw_loading))
428 		return 0;
429 
430 	if (hdev->hl_chip_info->info) {
431 		hdev->hl_chip_info->ops = &hl_hwmon_ops;
432 
433 		hdev->hwmon_dev = hwmon_device_register_with_info(dev,
434 					prop->armcp_info.card_name, hdev,
435 					hdev->hl_chip_info, NULL);
436 		if (IS_ERR(hdev->hwmon_dev)) {
437 			rc = PTR_ERR(hdev->hwmon_dev);
438 			dev_err(hdev->dev,
439 				"Unable to register hwmon device: %d\n", rc);
440 			return rc;
441 		}
442 
443 		dev_info(hdev->dev, "%s: add sensors information\n",
444 			dev_name(hdev->hwmon_dev));
445 
446 		hdev->hwmon_initialized = true;
447 	} else {
448 		dev_info(hdev->dev, "no available sensors\n");
449 	}
450 
451 	return 0;
452 }
453 
hl_hwmon_fini(struct hl_device * hdev)454 void hl_hwmon_fini(struct hl_device *hdev)
455 {
456 	if (!hdev->hwmon_initialized)
457 		return;
458 
459 	hwmon_device_unregister(hdev->hwmon_dev);
460 }
461