blob: 8705c1e34a48a92d47abaaefc98cfb8f2e3e3f24 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Duncan Lauriea12fc812016-12-13 16:43:40 -08002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpigen_dsm.h>
Karthikeyan Ramasubramaniana7e67882021-02-09 10:07:47 -07004#include <acpi/acpi_device.h>
5#include <assert.h>
Duncan Lauriea12fc812016-12-13 16:43:40 -08006#include <device/device.h>
Duncan Lauriea12fc812016-12-13 16:43:40 -08007#include <string.h>
8#include "chip.h"
Eric Lai18060d72019-04-24 14:21:04 +08009#include <gpio.h>
10#include <console/console.h>
Duncan Lauriea12fc812016-12-13 16:43:40 -080011
Julius Wernercd49cce2019-03-05 16:53:33 -080012#if CONFIG(HAVE_ACPI_TABLES)
Furquan Shaikh8220c4b2020-04-24 21:44:27 -070013static void i2c_hid_fill_dsm(const struct device *dev)
Duncan Lauriea12fc812016-12-13 16:43:40 -080014{
15 struct drivers_i2c_hid_config *config = dev->chip_info;
16 struct dsm_i2c_hid_config dsm_config = {
17 .hid_desc_reg_offset = config->hid_desc_reg_offset,
18 };
19
20 acpigen_write_dsm_i2c_hid(&dsm_config);
21}
22
Furquan Shaikh7536a392020-04-24 21:59:21 -070023static void i2c_hid_fill_ssdt_generator(const struct device *dev)
Duncan Lauriea12fc812016-12-13 16:43:40 -080024{
25 struct drivers_i2c_hid_config *config = dev->chip_info;
26 config->generic.cid = I2C_HID_CID;
27 i2c_generic_fill_ssdt(dev, &i2c_hid_fill_dsm, &config->generic);
28}
29
Aaron Durbinaa090cb2017-09-13 16:01:52 -060030static const char *i2c_hid_acpi_name(const struct device *dev)
Duncan Lauriea12fc812016-12-13 16:43:40 -080031{
32 static char name[5];
Matt DeVillier3d627812020-11-19 18:31:17 -060033 struct drivers_i2c_hid_config *config = dev->chip_info;
34 if (config->generic.name)
35 return config->generic.name;
36
Duncan Lauriea12fc812016-12-13 16:43:40 -080037 snprintf(name, sizeof(name), "H%03.3X", dev->path.i2c.device);
38 name[4] = '\0';
39 return name;
40}
41#endif
42
43static struct device_operations i2c_hid_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +020044 .read_resources = noop_read_resources,
45 .set_resources = noop_set_resources,
Julius Wernercd49cce2019-03-05 16:53:33 -080046#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +020047 .acpi_name = i2c_hid_acpi_name,
48 .acpi_fill_ssdt = i2c_hid_fill_ssdt_generator,
Duncan Lauriea12fc812016-12-13 16:43:40 -080049#endif
50};
51
52static void i2c_hid_enable(struct device *dev)
53{
Naresh G Solanki69e9e712018-06-04 17:45:19 +053054 struct drivers_i2c_hid_config *config = dev->chip_info;
55
Eric Lai18060d72019-04-24 14:21:04 +080056 if (!config)
57 return;
58
59 /* Check if device is present by reading GPIO */
60 if (config->generic.device_present_gpio) {
61 int present = gpio_get(config->generic.device_present_gpio);
62 present ^= config->generic.device_present_gpio_invert;
63
64 printk(BIOS_INFO, "%s is %spresent\n",
65 dev->chip_ops->name, present ? "" : "not ");
66
67 if (!present) {
68 dev->enabled = 0;
69 return;
70 }
71 }
72
Karthikeyan Ramasubramaniana7e67882021-02-09 10:07:47 -070073 /*
74 * Ensure that I2C HID devices use level triggered interrupts as per ACPI
75 * I2C HID requirement. Check interrupt and GPIO interrupt.
76 */
77 if ((!config->generic.irq_gpio.pin_count &&
78 config->generic.irq.mode != ACPI_IRQ_LEVEL_TRIGGERED) ||
79 (config->generic.irq_gpio.pin_count &&
80 config->generic.irq_gpio.irq.mode != ACPI_IRQ_LEVEL_TRIGGERED)) {
81 printk(BIOS_ERR, "%s IRQ is not level triggered.\n", config->generic.hid);
82 BUG();
83 }
84
Duncan Lauriea12fc812016-12-13 16:43:40 -080085 dev->ops = &i2c_hid_ops;
Naresh G Solanki69e9e712018-06-04 17:45:19 +053086
87 if (config && config->generic.desc) {
88 dev->name = config->generic.desc;
89 }
Duncan Lauriea12fc812016-12-13 16:43:40 -080090}
91
92struct chip_operations drivers_i2c_hid_ops = {
93 CHIP_NAME("I2C HID Device")
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +010094 .enable_dev = i2c_hid_enable
Duncan Lauriea12fc812016-12-13 16:43:40 -080095};