linux/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Author: Dan Scally <djrscally@gmail.com> */
   3
   4#include <linux/acpi.h>
   5#include <linux/i2c.h>
   6#include <linux/platform_device.h>
   7#include <linux/slab.h>
   8
   9#include "intel_skl_int3472_common.h"
  10
  11union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id)
  12{
  13        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  14        acpi_handle handle = adev->handle;
  15        union acpi_object *obj;
  16        acpi_status status;
  17
  18        status = acpi_evaluate_object(handle, id, NULL, &buffer);
  19        if (ACPI_FAILURE(status))
  20                return ERR_PTR(-ENODEV);
  21
  22        obj = buffer.pointer;
  23        if (!obj)
  24                return ERR_PTR(-ENODEV);
  25
  26        if (obj->type != ACPI_TYPE_BUFFER) {
  27                acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id);
  28                kfree(obj);
  29                return ERR_PTR(-EINVAL);
  30        }
  31
  32        return obj;
  33}
  34
  35int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
  36{
  37        union acpi_object *obj;
  38        int ret;
  39
  40        obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
  41        if (IS_ERR(obj))
  42                return PTR_ERR(obj);
  43
  44        if (obj->buffer.length > sizeof(*cldb)) {
  45                acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
  46                ret = -EINVAL;
  47                goto out_free_obj;
  48        }
  49
  50        memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
  51        ret = 0;
  52
  53out_free_obj:
  54        kfree(obj);
  55        return ret;
  56}
  57
  58static const struct acpi_device_id int3472_device_id[] = {
  59        { "INT3472", 0 },
  60        { }
  61};
  62MODULE_DEVICE_TABLE(acpi, int3472_device_id);
  63
  64static struct platform_driver int3472_discrete = {
  65        .driver = {
  66                .name = "int3472-discrete",
  67                .acpi_match_table = int3472_device_id,
  68        },
  69        .probe = skl_int3472_discrete_probe,
  70        .remove = skl_int3472_discrete_remove,
  71};
  72
  73static struct i2c_driver int3472_tps68470 = {
  74        .driver = {
  75                .name = "int3472-tps68470",
  76                .acpi_match_table = int3472_device_id,
  77        },
  78        .probe_new = skl_int3472_tps68470_probe,
  79};
  80
  81static int skl_int3472_init(void)
  82{
  83        int ret;
  84
  85        ret = platform_driver_register(&int3472_discrete);
  86        if (ret)
  87                return ret;
  88
  89        ret = i2c_register_driver(THIS_MODULE, &int3472_tps68470);
  90        if (ret)
  91                platform_driver_unregister(&int3472_discrete);
  92
  93        return ret;
  94}
  95module_init(skl_int3472_init);
  96
  97static void skl_int3472_exit(void)
  98{
  99        platform_driver_unregister(&int3472_discrete);
 100        i2c_del_driver(&int3472_tps68470);
 101}
 102module_exit(skl_int3472_exit);
 103
 104MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver");
 105MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
 106MODULE_LICENSE("GPL v2");
 107