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