xref: /linux/drivers/platform/x86/intel/int3472/common.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1a2f9fbc2SHans de Goede // SPDX-License-Identifier: GPL-2.0
2a2f9fbc2SHans de Goede /* Author: Dan Scally <djrscally@gmail.com> */
3a2f9fbc2SHans de Goede 
4a2f9fbc2SHans de Goede #include <linux/acpi.h>
5a2f9fbc2SHans de Goede #include <linux/slab.h>
6a2f9fbc2SHans de Goede 
7a2f9fbc2SHans de Goede #include "common.h"
8a2f9fbc2SHans de Goede 
skl_int3472_get_acpi_buffer(struct acpi_device * adev,char * id)9a2f9fbc2SHans de Goede union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id)
10a2f9fbc2SHans de Goede {
11a2f9fbc2SHans de Goede 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
12a2f9fbc2SHans de Goede 	acpi_handle handle = adev->handle;
13a2f9fbc2SHans de Goede 	union acpi_object *obj;
14a2f9fbc2SHans de Goede 	acpi_status status;
15a2f9fbc2SHans de Goede 
16a2f9fbc2SHans de Goede 	status = acpi_evaluate_object(handle, id, NULL, &buffer);
17a2f9fbc2SHans de Goede 	if (ACPI_FAILURE(status))
18a2f9fbc2SHans de Goede 		return ERR_PTR(-ENODEV);
19a2f9fbc2SHans de Goede 
20a2f9fbc2SHans de Goede 	obj = buffer.pointer;
21a2f9fbc2SHans de Goede 	if (!obj)
22a2f9fbc2SHans de Goede 		return ERR_PTR(-ENODEV);
23a2f9fbc2SHans de Goede 
24a2f9fbc2SHans de Goede 	if (obj->type != ACPI_TYPE_BUFFER) {
25a2f9fbc2SHans de Goede 		acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id);
26a2f9fbc2SHans de Goede 		kfree(obj);
27a2f9fbc2SHans de Goede 		return ERR_PTR(-EINVAL);
28a2f9fbc2SHans de Goede 	}
29a2f9fbc2SHans de Goede 
30a2f9fbc2SHans de Goede 	return obj;
31a2f9fbc2SHans de Goede }
32*4c29e80aSArnd Bergmann EXPORT_SYMBOL_GPL(skl_int3472_get_acpi_buffer);
33a2f9fbc2SHans de Goede 
skl_int3472_fill_cldb(struct acpi_device * adev,struct int3472_cldb * cldb)34a2f9fbc2SHans de Goede int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
35a2f9fbc2SHans de Goede {
36a2f9fbc2SHans de Goede 	union acpi_object *obj;
37a2f9fbc2SHans de Goede 	int ret;
38a2f9fbc2SHans de Goede 
39a2f9fbc2SHans de Goede 	obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
40a2f9fbc2SHans de Goede 	if (IS_ERR(obj))
41a2f9fbc2SHans de Goede 		return PTR_ERR(obj);
42a2f9fbc2SHans de Goede 
43a2f9fbc2SHans de Goede 	if (obj->buffer.length > sizeof(*cldb)) {
44a2f9fbc2SHans de Goede 		acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
45a2f9fbc2SHans de Goede 		ret = -EINVAL;
46a2f9fbc2SHans de Goede 		goto out_free_obj;
47a2f9fbc2SHans de Goede 	}
48a2f9fbc2SHans de Goede 
49a2f9fbc2SHans de Goede 	memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
50a2f9fbc2SHans de Goede 	ret = 0;
51a2f9fbc2SHans de Goede 
52a2f9fbc2SHans de Goede out_free_obj:
53a2f9fbc2SHans de Goede 	kfree(obj);
54a2f9fbc2SHans de Goede 	return ret;
55a2f9fbc2SHans de Goede }
56*4c29e80aSArnd Bergmann EXPORT_SYMBOL_GPL(skl_int3472_fill_cldb);
5771102bc7SHans de Goede 
5871102bc7SHans de Goede /* sensor_adev_ret may be NULL, name_ret must not be NULL */
skl_int3472_get_sensor_adev_and_name(struct device * dev,struct acpi_device ** sensor_adev_ret,const char ** name_ret)5971102bc7SHans de Goede int skl_int3472_get_sensor_adev_and_name(struct device *dev,
6071102bc7SHans de Goede 					 struct acpi_device **sensor_adev_ret,
6171102bc7SHans de Goede 					 const char **name_ret)
6271102bc7SHans de Goede {
6371102bc7SHans de Goede 	struct acpi_device *adev = ACPI_COMPANION(dev);
6471102bc7SHans de Goede 	struct acpi_device *sensor;
6571102bc7SHans de Goede 	int ret = 0;
6671102bc7SHans de Goede 
67cca8a7efSDaniel Scally 	sensor = acpi_dev_get_next_consumer_dev(adev, NULL);
6871102bc7SHans de Goede 	if (!sensor) {
6971102bc7SHans de Goede 		dev_err(dev, "INT3472 seems to have no dependents.\n");
7071102bc7SHans de Goede 		return -ENODEV;
7171102bc7SHans de Goede 	}
7271102bc7SHans de Goede 
7371102bc7SHans de Goede 	*name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
7471102bc7SHans de Goede 				   acpi_dev_name(sensor));
7571102bc7SHans de Goede 	if (!*name_ret)
7671102bc7SHans de Goede 		ret = -ENOMEM;
7771102bc7SHans de Goede 
7871102bc7SHans de Goede 	if (ret == 0 && sensor_adev_ret)
7971102bc7SHans de Goede 		*sensor_adev_ret = sensor;
8071102bc7SHans de Goede 	else
8171102bc7SHans de Goede 		acpi_dev_put(sensor);
8271102bc7SHans de Goede 
8371102bc7SHans de Goede 	return ret;
8471102bc7SHans de Goede }
85*4c29e80aSArnd Bergmann EXPORT_SYMBOL_GPL(skl_int3472_get_sensor_adev_and_name);
86*4c29e80aSArnd Bergmann 
87*4c29e80aSArnd Bergmann MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver library");
88*4c29e80aSArnd Bergmann MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
89*4c29e80aSArnd Bergmann MODULE_LICENSE("GPL");
90