From 14a1c2778fda7e4ed25d6cd4aecfb2d4e672dbed Mon Sep 17 00:00:00 2001 From: Seunghwan Kim Date: Mon, 8 Nov 2021 15:55:01 +0900 Subject: [PATCH] driver/i2c: Add sx9360 driver Add driver for setting up Semtech sx9360 SAR sensor. The driver is based on sx9310.c. The core of the driver is the same, but the bindings are slightly different. Registers are documented in the kernel tree: Documentation/devicetree/bindings/iio/proximity/semtech,sx9360.yaml [https://patchwork.kernel.org/project/linux-iio/patch/20211213024057.3824985-4-gwendal@chromium.org/] Signed-off-by: Seunghwan Kim Signed-off-by: Gwendal Grignou Change-Id: I0a912f184e6f3501f894cca24c0d71a2c3087516 Reviewed-on: https://review.coreboot.org/c/coreboot/+/59608 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Tim Wawrzynczak --- src/drivers/i2c/sx9360/Kconfig | 6 ++ src/drivers/i2c/sx9360/Makefile.inc | 1 + src/drivers/i2c/sx9360/chip.h | 40 +++++++++++ src/drivers/i2c/sx9360/sx9360.c | 107 ++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 src/drivers/i2c/sx9360/Kconfig create mode 100644 src/drivers/i2c/sx9360/Makefile.inc create mode 100644 src/drivers/i2c/sx9360/chip.h create mode 100644 src/drivers/i2c/sx9360/sx9360.c diff --git a/src/drivers/i2c/sx9360/Kconfig b/src/drivers/i2c/sx9360/Kconfig new file mode 100644 index 0000000000..ea28564fb9 --- /dev/null +++ b/src/drivers/i2c/sx9360/Kconfig @@ -0,0 +1,6 @@ +config DRIVERS_I2C_SX9360 + bool + default n + depends on HAVE_ACPI_TABLES + help + Board has a Semtech SX9360 proximity sensor. diff --git a/src/drivers/i2c/sx9360/Makefile.inc b/src/drivers/i2c/sx9360/Makefile.inc new file mode 100644 index 0000000000..695bb527c7 --- /dev/null +++ b/src/drivers/i2c/sx9360/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_DRIVERS_I2C_SX9360) += sx9360.c diff --git a/src/drivers/i2c/sx9360/chip.h b/src/drivers/i2c/sx9360/chip.h new file mode 100644 index 0000000000..397ea3f5d2 --- /dev/null +++ b/src/drivers/i2c/sx9360/chip.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __DRIVERS_I2C_SX9360_CHIP_H__ +#define __DRIVERS_I2C_SX9360_CHIP_H__ + +#include +#include + +struct drivers_i2c_sx9360_config { + /* Device Description */ + const char *desc; + + /* ACPI _UID */ + unsigned int uid; + + /* Bus speed in Hz, default is I2C_SPEED_FAST */ + enum i2c_speed speed; + + /* Use GPIO-based interrupt instead of IO-APIC */ + struct acpi_gpio irq_gpio; + + /* IO-APIC interrupt */ + struct acpi_irq irq; + + /* + * Registers definition in the kernel source tree at: + * Documentation/devicetree/bindings/iio/proximity/semtech,sx9360.yaml + */ + + /* Raw Proximity filter strength: When not set, disabled. */ + uint32_t proxraw_strength; + + /* Average Proximity filter strength: When not set, disabled. */ + uint32_t avg_pos_strength; + + /* Capacitance measure resolution. Driver default: 128. */ + uint32_t resolution; +}; + +#endif /* __DRIVERS_I2C_SX9360_CHIP_H__ */ diff --git a/src/drivers/i2c/sx9360/sx9360.c b/src/drivers/i2c/sx9360/sx9360.c new file mode 100644 index 0000000000..9ea4c8b90c --- /dev/null +++ b/src/drivers/i2c/sx9360/sx9360.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" + +#define I2C_SX9360_ACPI_ID "STH9360" +#define I2C_SX9360_CHIP_NAME "Semtech SX9360" + +static void i2c_sx9360_fill_ssdt(const struct device *dev) +{ + struct drivers_i2c_sx9360_config *config = dev->chip_info; + const char *scope = acpi_device_scope(dev); + struct acpi_i2c i2c = { + .address = dev->path.i2c.device, + .mode_10bit = dev->path.i2c.mode_10bit, + .speed = I2C_SPEED_FAST, + .resource = scope, + }; + struct acpi_dp *dsd; + + if (!scope || !config) + return; + + if (config->speed) + i2c.speed = config->speed; + + /* Device */ + acpigen_write_scope(scope); + acpigen_write_device(acpi_device_name(dev)); + acpigen_write_name_string("_HID", I2C_SX9360_ACPI_ID); + acpigen_write_name_integer("_UID", config->uid); + acpigen_write_name_string("_DDN", config->desc); + acpigen_write_STA(acpi_device_status(dev)); + + /* Resources */ + acpigen_write_name("_CRS"); + acpigen_write_resourcetemplate_header(); + acpi_device_write_i2c(&i2c); + + if (config->irq_gpio.pin_count) + acpi_device_write_gpio(&config->irq_gpio); + else + acpi_device_write_interrupt(&config->irq); + + acpigen_write_resourcetemplate_footer(); + + /* DSD */ + dsd = acpi_dp_new_table("_DSD"); + + /* + * Format described in linux kernel documentation. See + * https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/proximity/semtech%2Csx9360.yaml + */ + acpi_dp_add_integer(dsd, "semtech,proxraw-strength", + config->proxraw_strength); + acpi_dp_add_integer(dsd, "semtech,avg-pos-strength", + config->avg_pos_strength); + acpi_dp_add_integer(dsd, "semtech,resolution", + config->resolution); + + acpi_dp_write(dsd); + + acpigen_pop_len(); /* Device */ + acpigen_pop_len(); /* Scope */ + + printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), + config->desc ? : dev->chip_ops->name, dev_path(dev)); +} + +static const char *i2c_sx9360_acpi_name(const struct device *dev) +{ + static char name[5]; + + snprintf(name, sizeof(name), "SX%02.2X", dev->path.i2c.device); + return name; +} + +static struct device_operations i2c_sx9360_ops = { + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, + .acpi_name = i2c_sx9360_acpi_name, + .acpi_fill_ssdt = i2c_sx9360_fill_ssdt, +}; + +static void i2c_sx9360_enable(struct device *dev) +{ + struct drivers_i2c_sx9360_config *config = config_of(dev); + + if (!is_dev_enabled(dev)) + return; + + dev->ops = &i2c_sx9360_ops; + + if (config->desc) + dev->name = config->desc; +} + +struct chip_operations drivers_i2c_sx9360_ops = { + CHIP_NAME(I2C_SX9360_CHIP_NAME) + .enable_dev = i2c_sx9360_enable +};