Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 HWMON_NR_SENSOR_TYPES		(hwmon_pwm + 1)
 14
 15int hl_build_hwmon_channel_info(struct hl_device *hdev,
 16				struct armcp_sensor *sensors_arr)
 17{
 18	u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
 19	u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
 20	u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
 21	struct hwmon_channel_info **channels_info;
 22	u32 num_sensors_for_type, num_active_sensor_types = 0,
 23			arr_size = 0, *curr_arr;
 24	enum hwmon_sensor_types type;
 25	int rc, i, j;
 26
 27	for (i = 0 ; i < ARMCP_MAX_SENSORS ; i++) {
 28		type = le32_to_cpu(sensors_arr[i].type);
 29
 30		if ((type == 0) && (sensors_arr[i].flags == 0))
 31			break;
 32
 33		if (type >= HWMON_NR_SENSOR_TYPES) {
 34			dev_err(hdev->dev,
 35				"Got wrong sensor type %d from device\n", type);
 36			return -EINVAL;
 37		}
 38
 39		counts[type]++;
 40		arr_size++;
 41	}
 42
 43	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
 44		if (counts[i] == 0)
 45			continue;
 46
 47		num_sensors_for_type = counts[i] + 1;
 48		curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr),
 49				GFP_KERNEL);
 50		if (!curr_arr) {
 51			rc = -ENOMEM;
 52			goto sensors_type_err;
 53		}
 54
 55		num_active_sensor_types++;
 56		sensors_by_type[i] = curr_arr;
 57	}
 58
 59	for (i = 0 ; i < arr_size ; i++) {
 60		type = le32_to_cpu(sensors_arr[i].type);
 61		curr_arr = sensors_by_type[type];
 62		curr_arr[sensors_by_type_next_index[type]++] =
 63				le32_to_cpu(sensors_arr[i].flags);
 64	}
 65
 66	channels_info = kcalloc(num_active_sensor_types + 1,
 67			sizeof(*channels_info), GFP_KERNEL);
 68	if (!channels_info) {
 69		rc = -ENOMEM;
 70		goto channels_info_array_err;
 71	}
 72
 73	for (i = 0 ; i < num_active_sensor_types ; i++) {
 74		channels_info[i] = kzalloc(sizeof(*channels_info[i]),
 75				GFP_KERNEL);
 76		if (!channels_info[i]) {
 77			rc = -ENOMEM;
 78			goto channel_info_err;
 79		}
 80	}
 81
 82	for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
 83		if (!sensors_by_type[i])
 84			continue;
 85
 86		channels_info[j]->type = i;
 87		channels_info[j]->config = sensors_by_type[i];
 88		j++;
 89	}
 90
 91	hdev->hl_chip_info->info =
 92			(const struct hwmon_channel_info **)channels_info;
 93
 94	return 0;
 95
 96channel_info_err:
 97	for (i = 0 ; i < num_active_sensor_types ; i++)
 98		if (channels_info[i]) {
 99			kfree(channels_info[i]->config);
100			kfree(channels_info[i]);
101		}
102	kfree(channels_info);
103channels_info_array_err:
104sensors_type_err:
105	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
106		kfree(sensors_by_type[i]);
107
108	return rc;
109}
110
111static int hl_read(struct device *dev, enum hwmon_sensor_types type,
112			u32 attr, int channel, long *val)
113{
114	struct hl_device *hdev = dev_get_drvdata(dev);
115	int rc;
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		case hwmon_temp_offset:
129		case hwmon_temp_highest:
130			break;
131		default:
132			return -EINVAL;
133		}
134
135		rc = hl_get_temperature(hdev, channel, attr, val);
136		break;
137	case hwmon_in:
138		switch (attr) {
139		case hwmon_in_input:
140		case hwmon_in_min:
141		case hwmon_in_max:
142		case hwmon_in_highest:
143			break;
144		default:
145			return -EINVAL;
146		}
147
148		rc = hl_get_voltage(hdev, channel, attr, val);
149		break;
150	case hwmon_curr:
151		switch (attr) {
152		case hwmon_curr_input:
153		case hwmon_curr_min:
154		case hwmon_curr_max:
155		case hwmon_curr_highest:
156			break;
157		default:
158			return -EINVAL;
159		}
160
161		rc = hl_get_current(hdev, channel, attr, val);
162		break;
163	case hwmon_fan:
164		switch (attr) {
165		case hwmon_fan_input:
166		case hwmon_fan_min:
167		case hwmon_fan_max:
168			break;
169		default:
170			return -EINVAL;
171		}
172		rc = hl_get_fan_speed(hdev, channel, attr, val);
173		break;
174	case hwmon_pwm:
175		switch (attr) {
176		case hwmon_pwm_input:
177		case hwmon_pwm_enable:
178			break;
179		default:
180			return -EINVAL;
181		}
182		rc = hl_get_pwm_info(hdev, channel, attr, val);
183		break;
184	default:
185		return -EINVAL;
186	}
187	return rc;
188}
189
190static int hl_write(struct device *dev, enum hwmon_sensor_types type,
191			u32 attr, int channel, long val)
192{
193	struct hl_device *hdev = dev_get_drvdata(dev);
194
195	if (hl_device_disabled_or_in_reset(hdev))
196		return -ENODEV;
197
198	switch (type) {
199	case hwmon_temp:
200		switch (attr) {
201		case hwmon_temp_offset:
202		case hwmon_temp_reset_history:
203			break;
204		default:
205			return -EINVAL;
206		}
207		hl_set_temperature(hdev, channel, attr, val);
208		break;
209	case hwmon_pwm:
210		switch (attr) {
211		case hwmon_pwm_input:
212		case hwmon_pwm_enable:
213			break;
214		default:
215			return -EINVAL;
216		}
217		hl_set_pwm_info(hdev, channel, attr, val);
218		break;
219	case hwmon_in:
220		switch (attr) {
221		case hwmon_in_reset_history:
222			break;
223		default:
224			return -EINVAL;
225		}
226		hl_set_voltage(hdev, channel, attr, val);
227		break;
228	case hwmon_curr:
229		switch (attr) {
230		case hwmon_curr_reset_history:
231			break;
232		default:
233			return -EINVAL;
234		}
235		hl_set_current(hdev, channel, attr, val);
236		break;
237	default:
238		return -EINVAL;
239	}
240	return 0;
241}
242
243static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
244				u32 attr, int channel)
245{
246	switch (type) {
247	case hwmon_temp:
248		switch (attr) {
249		case hwmon_temp_input:
250		case hwmon_temp_max:
251		case hwmon_temp_max_hyst:
252		case hwmon_temp_crit:
253		case hwmon_temp_crit_hyst:
254		case hwmon_temp_highest:
255			return 0444;
256		case hwmon_temp_offset:
257			return 0644;
258		case hwmon_temp_reset_history:
259			return 0200;
260		}
261		break;
262	case hwmon_in:
263		switch (attr) {
264		case hwmon_in_input:
265		case hwmon_in_min:
266		case hwmon_in_max:
267		case hwmon_in_highest:
268			return 0444;
269		case hwmon_in_reset_history:
270			return 0200;
271		}
272		break;
273	case hwmon_curr:
274		switch (attr) {
275		case hwmon_curr_input:
276		case hwmon_curr_min:
277		case hwmon_curr_max:
278		case hwmon_curr_highest:
279			return 0444;
280		case hwmon_curr_reset_history:
281			return 0200;
282		}
283		break;
284	case hwmon_fan:
285		switch (attr) {
286		case hwmon_fan_input:
287		case hwmon_fan_min:
288		case hwmon_fan_max:
289			return 0444;
290		}
291		break;
292	case hwmon_pwm:
293		switch (attr) {
294		case hwmon_pwm_input:
295		case hwmon_pwm_enable:
296			return 0644;
297		}
298		break;
299	default:
300		break;
301	}
302	return 0;
303}
304
305static const struct hwmon_ops hl_hwmon_ops = {
306	.is_visible = hl_is_visible,
307	.read = hl_read,
308	.write = hl_write
309};
310
311int hl_get_temperature(struct hl_device *hdev,
312			int sensor_index, u32 attr, long *value)
313{
314	struct armcp_packet pkt;
315	int rc;
316
317	memset(&pkt, 0, sizeof(pkt));
318
319	pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEMPERATURE_GET <<
320				ARMCP_PKT_CTL_OPCODE_SHIFT);
321	pkt.sensor_index = __cpu_to_le16(sensor_index);
322	pkt.type = __cpu_to_le16(attr);
323
324	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
325						0, value);
326
327	if (rc) {
328		dev_err(hdev->dev,
329			"Failed to get temperature from sensor %d, error %d\n",
330			sensor_index, rc);
331		*value = 0;
332	}
333
334	return rc;
335}
336
337int hl_set_temperature(struct hl_device *hdev,
338			int sensor_index, u32 attr, long value)
339{
340	struct armcp_packet pkt;
341	int rc;
342
343	memset(&pkt, 0, sizeof(pkt));
344
345	pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEMPERATURE_SET <<
346				ARMCP_PKT_CTL_OPCODE_SHIFT);
347	pkt.sensor_index = __cpu_to_le16(sensor_index);
348	pkt.type = __cpu_to_le16(attr);
349	pkt.value = __cpu_to_le64(value);
350
351	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
352						0, NULL);
353
354	if (rc)
355		dev_err(hdev->dev,
356			"Failed to set temperature of sensor %d, error %d\n",
357			sensor_index, rc);
358
359	return rc;
360}
361
362int hl_get_voltage(struct hl_device *hdev,
363			int sensor_index, u32 attr, long *value)
364{
365	struct armcp_packet pkt;
366	int rc;
367
368	memset(&pkt, 0, sizeof(pkt));
369
370	pkt.ctl = cpu_to_le32(ARMCP_PACKET_VOLTAGE_GET <<
371				ARMCP_PKT_CTL_OPCODE_SHIFT);
372	pkt.sensor_index = __cpu_to_le16(sensor_index);
373	pkt.type = __cpu_to_le16(attr);
374
375	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
376						0, value);
377
378	if (rc) {
379		dev_err(hdev->dev,
380			"Failed to get voltage from sensor %d, error %d\n",
381			sensor_index, rc);
382		*value = 0;
383	}
384
385	return rc;
386}
387
388int hl_get_current(struct hl_device *hdev,
389			int sensor_index, u32 attr, long *value)
390{
391	struct armcp_packet pkt;
392	int rc;
393
394	memset(&pkt, 0, sizeof(pkt));
395
396	pkt.ctl = cpu_to_le32(ARMCP_PACKET_CURRENT_GET <<
397				ARMCP_PKT_CTL_OPCODE_SHIFT);
398	pkt.sensor_index = __cpu_to_le16(sensor_index);
399	pkt.type = __cpu_to_le16(attr);
400
401	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
402						0, value);
403
404	if (rc) {
405		dev_err(hdev->dev,
406			"Failed to get current from sensor %d, error %d\n",
407			sensor_index, rc);
408		*value = 0;
409	}
410
411	return rc;
412}
413
414int hl_get_fan_speed(struct hl_device *hdev,
415			int sensor_index, u32 attr, long *value)
416{
417	struct armcp_packet pkt;
418	int rc;
419
420	memset(&pkt, 0, sizeof(pkt));
421
422	pkt.ctl = cpu_to_le32(ARMCP_PACKET_FAN_SPEED_GET <<
423				ARMCP_PKT_CTL_OPCODE_SHIFT);
424	pkt.sensor_index = __cpu_to_le16(sensor_index);
425	pkt.type = __cpu_to_le16(attr);
426
427	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
428						0, value);
429
430	if (rc) {
431		dev_err(hdev->dev,
432			"Failed to get fan speed from sensor %d, error %d\n",
433			sensor_index, rc);
434		*value = 0;
435	}
436
437	return rc;
438}
439
440int hl_get_pwm_info(struct hl_device *hdev,
441			int sensor_index, u32 attr, long *value)
442{
443	struct armcp_packet pkt;
444	int rc;
445
446	memset(&pkt, 0, sizeof(pkt));
447
448	pkt.ctl = cpu_to_le32(ARMCP_PACKET_PWM_GET <<
449				ARMCP_PKT_CTL_OPCODE_SHIFT);
450	pkt.sensor_index = __cpu_to_le16(sensor_index);
451	pkt.type = __cpu_to_le16(attr);
452
453	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
454						0, value);
455
456	if (rc) {
457		dev_err(hdev->dev,
458			"Failed to get pwm info from sensor %d, error %d\n",
459			sensor_index, rc);
460		*value = 0;
461	}
462
463	return rc;
464}
465
466void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
467			long value)
468{
469	struct armcp_packet pkt;
470	int rc;
471
472	memset(&pkt, 0, sizeof(pkt));
473
474	pkt.ctl = cpu_to_le32(ARMCP_PACKET_PWM_SET <<
475				ARMCP_PKT_CTL_OPCODE_SHIFT);
476	pkt.sensor_index = __cpu_to_le16(sensor_index);
477	pkt.type = __cpu_to_le16(attr);
478	pkt.value = cpu_to_le64(value);
479
480	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
481						0, NULL);
482
483	if (rc)
484		dev_err(hdev->dev,
485			"Failed to set pwm info to sensor %d, error %d\n",
486			sensor_index, rc);
487}
488
489int hl_set_voltage(struct hl_device *hdev,
490			int sensor_index, u32 attr, long value)
491{
492	struct armcp_packet pkt;
493	int rc;
494
495	memset(&pkt, 0, sizeof(pkt));
496
497	pkt.ctl = cpu_to_le32(ARMCP_PACKET_VOLTAGE_SET <<
498				ARMCP_PKT_CTL_OPCODE_SHIFT);
499	pkt.sensor_index = __cpu_to_le16(sensor_index);
500	pkt.type = __cpu_to_le16(attr);
501	pkt.value = __cpu_to_le64(value);
502
503	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
504						0, NULL);
505
506	if (rc)
507		dev_err(hdev->dev,
508			"Failed to set voltage of sensor %d, error %d\n",
509			sensor_index, rc);
510
511	return rc;
512}
513
514int hl_set_current(struct hl_device *hdev,
515			int sensor_index, u32 attr, long value)
516{
517	struct armcp_packet pkt;
518	int rc;
519
520	memset(&pkt, 0, sizeof(pkt));
521
522	pkt.ctl = cpu_to_le32(ARMCP_PACKET_CURRENT_SET <<
523				ARMCP_PKT_CTL_OPCODE_SHIFT);
524	pkt.sensor_index = __cpu_to_le16(sensor_index);
525	pkt.type = __cpu_to_le16(attr);
526	pkt.value = __cpu_to_le64(value);
527
528	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
529						0, NULL);
530
531	if (rc)
532		dev_err(hdev->dev,
533			"Failed to set current of sensor %d, error %d\n",
534			sensor_index, rc);
535
536	return rc;
537}
538
539int hl_hwmon_init(struct hl_device *hdev)
540{
541	struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
542	struct asic_fixed_properties *prop = &hdev->asic_prop;
543	int rc;
544
545	if ((hdev->hwmon_initialized) || !(hdev->fw_loading))
546		return 0;
547
548	if (hdev->hl_chip_info->info) {
549		hdev->hl_chip_info->ops = &hl_hwmon_ops;
550
551		hdev->hwmon_dev = hwmon_device_register_with_info(dev,
552					prop->armcp_info.card_name, hdev,
553					hdev->hl_chip_info, NULL);
554		if (IS_ERR(hdev->hwmon_dev)) {
555			rc = PTR_ERR(hdev->hwmon_dev);
556			dev_err(hdev->dev,
557				"Unable to register hwmon device: %d\n", rc);
558			return rc;
559		}
560
561		dev_info(hdev->dev, "%s: add sensors information\n",
562			dev_name(hdev->hwmon_dev));
563
564		hdev->hwmon_initialized = true;
565	} else {
566		dev_info(hdev->dev, "no available sensors\n");
567	}
568
569	return 0;
570}
571
572void hl_hwmon_fini(struct hl_device *hdev)
573{
574	if (!hdev->hwmon_initialized)
575		return;
576
577	hwmon_device_unregister(hdev->hwmon_dev);
578}