* [PATCH v2 4/4] input: touchscreen: add SPI support for Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2023-06-15 10:27 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg
Cc: linux-input, linux-arm-msm, devicetree, linux-kernel,
Neil Armstrong
In-Reply-To: <20230606-topic-goodix-berlin-upstream-initial-v2-0-26bc8fe1e90e@linaro.org>
Add initial support for the new Goodix "Berlin" touchscreen ICs
over the SPI interface.
The driver doesn't use the regmap_spi code since the SPI messages
needs to be prefixed, thus this custom regmap code.
This initial driver is derived from the Goodix goodix_ts_berlin
available at [1] and [2] and only supports the GT9916 IC
present on the Qualcomm SM8550 MTP & QRD touch panel.
The current implementation only supports BerlinD, aka GT9916.
[1] https://github.com/goodix/goodix_ts_berlin
[2] https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/input/touchscreen/Kconfig | 13 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/goodix_berlin_spi.c | 172 ++++++++++++++++++++++++++
3 files changed, 186 insertions(+)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 5e21cca6025d..2d86615e5090 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -435,6 +435,19 @@ config TOUCHSCREEN_GOODIX_BERLIN_I2C
To compile this driver as a module, choose M here: the
module will be called goodix_berlin_i2c.
+config TOUCHSCREEN_GOODIX_BERLIN_SPI
+ tristate "Goodix Berlin SPI touchscreen"
+ depends on SPI_MASTER
+ select TOUCHSCREEN_GOODIX_BERLIN_CORE
+ help
+ Say Y here if you have a Goodix Berlin IC connected to
+ your system via SPI.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called goodix_berlin_spi.
+
config TOUCHSCREEN_HIDEEP
tristate "HiDeep Touch IC"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 921a2da0c2be..29524e8a83db 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_CORE) += goodix_berlin_core.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C) += goodix_berlin_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_SPI) += goodix_berlin_spi.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
diff --git a/drivers/input/touchscreen/goodix_berlin_spi.c b/drivers/input/touchscreen/goodix_berlin_spi.c
new file mode 100644
index 000000000000..3a1bc251b32d
--- /dev/null
+++ b/drivers/input/touchscreen/goodix_berlin_spi.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Goodix Berlin Touchscreen Driver
+ *
+ * Copyright (C) 2020 - 2021 Goodix, Inc.
+ * Copyright (C) 2023 Linaro Ltd.
+ *
+ * Based on goodix_ts_berlin driver.
+ */
+#include <asm/unaligned.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "goodix_berlin.h"
+
+#define SPI_TRANS_PREFIX_LEN 1
+#define REGISTER_WIDTH 4
+#define SPI_READ_DUMMY_LEN 3
+#define SPI_READ_PREFIX_LEN (SPI_TRANS_PREFIX_LEN + REGISTER_WIDTH + SPI_READ_DUMMY_LEN)
+#define SPI_WRITE_PREFIX_LEN (SPI_TRANS_PREFIX_LEN + REGISTER_WIDTH)
+
+#define SPI_WRITE_FLAG 0xF0
+#define SPI_READ_FLAG 0xF1
+
+static int goodix_berlin_spi_read(void *context, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ struct spi_device *spi = context;
+ struct spi_transfer xfers;
+ struct spi_message spi_msg;
+ const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */
+ u8 *buf;
+ int ret;
+
+ if (reg_size != REGISTER_WIDTH)
+ return -EINVAL;
+
+ buf = kzalloc(SPI_READ_PREFIX_LEN + val_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ spi_message_init(&spi_msg);
+ memset(&xfers, 0, sizeof(xfers));
+
+ /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */
+ buf[0] = SPI_READ_FLAG;
+ put_unaligned_be32(*reg, buf + SPI_TRANS_PREFIX_LEN);
+ memset(buf + SPI_TRANS_PREFIX_LEN + REGISTER_WIDTH, 0xff,
+ SPI_READ_DUMMY_LEN);
+
+ xfers.tx_buf = buf;
+ xfers.rx_buf = buf;
+ xfers.len = SPI_READ_PREFIX_LEN + val_size;
+ xfers.cs_change = 0;
+ spi_message_add_tail(&xfers, &spi_msg);
+
+ ret = spi_sync(spi, &spi_msg);
+ if (ret < 0)
+ dev_err(&spi->dev, "transfer error:%d", ret);
+ else
+ memcpy(val_buf, buf + SPI_READ_PREFIX_LEN, val_size);
+
+ kfree(buf);
+ return ret;
+}
+
+static int goodix_berlin_spi_write(void *context, const void *data,
+ size_t count)
+{
+ unsigned int len = count - REGISTER_WIDTH;
+ struct spi_device *spi = context;
+ struct spi_transfer xfers;
+ struct spi_message spi_msg;
+ const u32 *reg = data; /* reg is stored as native u32 at start of buffer */
+ u8 *buf;
+ int ret;
+
+ buf = kzalloc(SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ spi_message_init(&spi_msg);
+ memset(&xfers, 0, sizeof(xfers));
+
+ buf[0] = SPI_WRITE_FLAG;
+ put_unaligned_be32(*reg, buf + SPI_TRANS_PREFIX_LEN);
+ memcpy(buf + SPI_WRITE_PREFIX_LEN, data + REGISTER_WIDTH, len);
+
+ xfers.tx_buf = buf;
+ xfers.len = SPI_WRITE_PREFIX_LEN + len;
+ xfers.cs_change = 0;
+ spi_message_add_tail(&xfers, &spi_msg);
+
+ ret = spi_sync(spi, &spi_msg);
+ if (ret < 0)
+ dev_err(&spi->dev, "transfer error:%d", ret);
+
+ kfree(buf);
+ return ret;
+}
+
+static const struct regmap_config goodix_berlin_spi_regmap_conf = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .read = goodix_berlin_spi_read,
+ .write = goodix_berlin_spi_write,
+};
+
+/* vendor & product left unassigned here, should probably be updated from fw info */
+static const struct input_id goodix_berlin_spi_input_id = {
+ .bustype = BUS_SPI,
+};
+
+static int goodix_berlin_spi_probe(struct spi_device *spi)
+{
+ struct regmap_config *regmap_config;
+ struct regmap *regmap;
+ size_t max_size;
+ int error = 0;
+
+ regmap_config = devm_kmemdup(&spi->dev, &goodix_berlin_spi_regmap_conf,
+ sizeof(*regmap_config), GFP_KERNEL);
+ if (!regmap_config)
+ return -ENOMEM;
+
+ spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ error = spi_setup(spi);
+ if (error)
+ return error;
+
+ max_size = spi_max_transfer_size(spi);
+ regmap_config->max_raw_read = max_size - SPI_READ_PREFIX_LEN;
+ regmap_config->max_raw_write = max_size - SPI_WRITE_PREFIX_LEN;
+
+ regmap = devm_regmap_init(&spi->dev, NULL, spi, regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return goodix_berlin_probe(&spi->dev, spi->irq,
+ &goodix_berlin_spi_input_id, regmap);
+}
+
+static const struct spi_device_id goodix_berlin_spi_ids[] = {
+ { "gt9916" },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids);
+
+static const struct of_device_id goodix_berlin_spi_of_match[] = {
+ { .compatible = "goodix,gt9916", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match);
+
+static struct spi_driver goodix_berlin_spi_driver = {
+ .driver = {
+ .name = "goodix-berlin-spi",
+ .of_match_table = goodix_berlin_spi_of_match,
+ .pm = pm_sleep_ptr(&goodix_berlin_pm_ops),
+ },
+ .probe = goodix_berlin_spi_probe,
+ .id_table = goodix_berlin_spi_ids,
+};
+module_spi_driver(goodix_berlin_spi_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Goodix Berlin SPI Touchscreen driver");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/4] input: touchscreen: add core support for Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2023-06-15 10:27 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg
Cc: linux-input, linux-arm-msm, devicetree, linux-kernel,
Neil Armstrong
In-Reply-To: <20230606-topic-goodix-berlin-upstream-initial-v2-0-26bc8fe1e90e@linaro.org>
Add initial support for the new Goodix "Berlin" touchscreen ICs.
These touchscreen ICs support SPI, I2C and I3C interface, up to
10 finger touch, stylus and gestures events.
This initial driver is derived from the Goodix goodix_ts_berlin
available at [1] and [2] and only supports the GT9916 IC
present on the Qualcomm SM8550 MTP & QRD touch panel.
The current implementation only supports BerlinD, aka GT9916.
Support for advanced features like:
- Firmware & config update
- Stylus events
- Gestures events
- Previous revisions support (BerlinA or BerlinB)
is not included in current version.
The current support will work with currently flashed firmware
and config, and bail out if firmware or config aren't flashed yet.
[1] https://github.com/goodix/goodix_ts_berlin
[2] https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/input/touchscreen/Kconfig | 5 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/goodix_berlin.h | 178 +++++++
drivers/input/touchscreen/goodix_berlin_core.c | 681 +++++++++++++++++++++++++
4 files changed, 865 insertions(+)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index c2cbd332af1d..1a6f6f6da991 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -416,6 +416,11 @@ config TOUCHSCREEN_GOODIX
To compile this driver as a module, choose M here: the
module will be called goodix.
+config TOUCHSCREEN_GOODIX_BERLIN_CORE
+ depends on GPIOLIB || COMPILE_TEST
+ depends on REGMAP
+ tristate
+
config TOUCHSCREEN_HIDEEP
tristate "HiDeep Touch IC"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 159cd5136fdb..29cdb042e104 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_ts.o
+obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_CORE) += goodix_berlin_core.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
diff --git a/drivers/input/touchscreen/goodix_berlin.h b/drivers/input/touchscreen/goodix_berlin.h
new file mode 100644
index 000000000000..56c110d94dff
--- /dev/null
+++ b/drivers/input/touchscreen/goodix_berlin.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Goodix Touchscreen Driver
+ * Copyright (C) 2020 - 2021 Goodix, Inc.
+ * Copyright (C) 2023 Linaro Ltd.
+ *
+ * Based on goodix_berlin_berlin driver.
+ */
+
+#ifndef __GOODIX_BERLIN_H_
+#define __GOODIX_BERLIN_H_
+
+#include <linux/input.h>
+#include <linux/of_gpio.h>
+#include <linux/input/touchscreen.h>
+#include <linux/regulator/consumer.h>
+
+#define GOODIX_MAX_TOUCH 10
+
+#define GOODIX_NORMAL_RESET_DELAY_MS 100
+
+#define MAX_SCAN_FREQ_NUM 8
+#define MAX_SCAN_RATE_NUM 8
+#define MAX_FREQ_NUM_STYLUS 8
+
+#define IRQ_EVENT_HEAD_LEN 8
+#define BYTES_PER_POINT 8
+#define COOR_DATA_CHECKSUM_SIZE 2
+
+#define GOODIX_TOUCH_EVENT BIT(7)
+#define GOODIX_REQUEST_EVENT BIT(6)
+
+#define GOODIX_REQUEST_CODE_RESET 3
+
+#define POINT_TYPE_STYLUS_HOVER 0x01
+#define POINT_TYPE_STYLUS 0x03
+
+#define DEV_CONFIRM_VAL 0xAA
+#define BOOTOPTION_ADDR 0x10000
+#define FW_VERSION_INFO_ADDR 0x10014
+
+#define GOODIX_IC_INFO_MAX_LEN 1024
+#define GOODIX_IC_INFO_ADDR 0x10070
+
+struct goodix_berlin_fw_version {
+ u8 rom_pid[6];
+ u8 rom_vid[3];
+ u8 rom_vid_reserved;
+ u8 patch_pid[8];
+ u8 patch_vid[4];
+ u8 patch_vid_reserved;
+ u8 sensor_id;
+ u8 reserved[2];
+ u16 checksum;
+} __packed;
+
+struct goodix_berlin_ic_info_version {
+ u8 info_customer_id;
+ u8 info_version_id;
+ u8 ic_die_id;
+ u8 ic_version_id;
+ u32 config_id;
+ u8 config_version;
+ u8 frame_data_customer_id;
+ u8 frame_data_version_id;
+ u8 touch_data_customer_id;
+ u8 touch_data_version_id;
+ u8 reserved[3];
+} __packed;
+
+struct goodix_berlin_ic_info_feature {
+ u16 freqhop_feature;
+ u16 calibration_feature;
+ u16 gesture_feature;
+ u16 side_touch_feature;
+ u16 stylus_feature;
+} __packed;
+
+struct goodix_berlin_ic_info_misc {
+ u32 cmd_addr;
+ u16 cmd_max_len;
+ u32 cmd_reply_addr;
+ u16 cmd_reply_len;
+ u32 fw_state_addr;
+ u16 fw_state_len;
+ u32 fw_buffer_addr;
+ u16 fw_buffer_max_len;
+ u32 frame_data_addr;
+ u16 frame_data_head_len;
+ u16 fw_attr_len;
+ u16 fw_log_len;
+ u8 pack_max_num;
+ u8 pack_compress_version;
+ u16 stylus_struct_len;
+ u16 mutual_struct_len;
+ u16 self_struct_len;
+ u16 noise_struct_len;
+ u32 touch_data_addr;
+ u16 touch_data_head_len;
+ u16 point_struct_len;
+ u16 reserved1;
+ u16 reserved2;
+ u32 mutual_rawdata_addr;
+ u32 mutual_diffdata_addr;
+ u32 mutual_refdata_addr;
+ u32 self_rawdata_addr;
+ u32 self_diffdata_addr;
+ u32 self_refdata_addr;
+ u32 iq_rawdata_addr;
+ u32 iq_refdata_addr;
+ u32 im_rawdata_addr;
+ u16 im_readata_len;
+ u32 noise_rawdata_addr;
+ u16 noise_rawdata_len;
+ u32 stylus_rawdata_addr;
+ u16 stylus_rawdata_len;
+ u32 noise_data_addr;
+ u32 esd_addr;
+} __packed;
+
+enum goodix_berlin_ts_event_type {
+ GOODIX_BERLIN_EVENT_INVALID,
+ GOODIX_BERLIN_EVENT_TOUCH,
+ GOODIX_BERLIN_EVENT_REQUEST,
+};
+
+enum goodix_berlin_ts_request_type {
+ GOODIX_BERLIN_REQUEST_TYPE_INVALID,
+ GOODIX_BERLIN_REQUEST_TYPE_RESET,
+};
+
+enum goodix_berlin_touch_point_status {
+ GOODIX_BERLIN_TS_NONE,
+ GOODIX_BERLIN_TS_TOUCH,
+};
+
+struct goodix_berlin_coords {
+ enum goodix_berlin_touch_point_status status;
+ unsigned int x, y, w, p;
+};
+
+struct goodix_berlin_touch_data {
+ int touch_num;
+ struct goodix_berlin_coords coords[GOODIX_MAX_TOUCH];
+};
+
+struct goodix_berlin_event {
+ enum goodix_berlin_ts_event_type event_type;
+ enum goodix_berlin_ts_request_type request_code;
+ struct goodix_berlin_touch_data touch_data;
+};
+
+/* Runtime parameters extracted from goodix_berlin_ic_info */
+struct goodix_berlin_params {
+ u32 touch_data_addr;
+};
+
+struct goodix_berlin_core {
+ struct device *dev;
+ struct regmap *regmap;
+ struct regulator *avdd;
+ struct regulator *iovdd;
+ struct gpio_desc *reset_gpio;
+ struct touchscreen_properties props;
+ struct goodix_berlin_fw_version fw_version;
+ struct goodix_berlin_params params;
+ struct input_dev *input_dev;
+ struct goodix_berlin_event ts_event;
+ int irq;
+ struct dentry *debugfs_root;
+};
+
+int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
+ struct regmap *regmap);
+
+extern const struct dev_pm_ops goodix_berlin_pm_ops;
+
+#endif
diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c
new file mode 100644
index 000000000000..11788662722a
--- /dev/null
+++ b/drivers/input/touchscreen/goodix_berlin_core.c
@@ -0,0 +1,681 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Goodix Touchscreen Driver
+ * Copyright (C) 2020 - 2021 Goodix, Inc.
+ * Copyright (C) 2023 Linaro Ltd.
+ *
+ * Based on goodix_ts_berlin driver.
+ */
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/regmap.h>
+
+#include "goodix_berlin.h"
+
+/*
+ * Goodix "Berlin" Touchscreen ID driver
+ *
+ * Currently only handles Multitouch events with already
+ * programmed firmware and "config" for "Revision D" Berlin IC.
+ *
+ * Support is missing for:
+ * - ESD Management
+ * - Firmware update/flashing
+ * - "Config" update/flashing
+ * - Stylus Events
+ * - Gesture Events
+ * - Support for older revisions (A, B & C)
+ */
+
+static bool goodix_berlin_check_checksum(const u8 *data, int size)
+{
+ u32 cal_checksum = 0;
+ u32 r_checksum = 0;
+ u32 i;
+
+ if (size < COOR_DATA_CHECKSUM_SIZE)
+ return false;
+
+ for (i = 0; i < size - COOR_DATA_CHECKSUM_SIZE; i++)
+ cal_checksum += data[i];
+
+ r_checksum += data[i++];
+ r_checksum += (data[i] << 8);
+
+ return (cal_checksum & 0xFFFF) == r_checksum;
+}
+
+static bool goodix_berlin_is_dummy_data(struct goodix_berlin_core *cd,
+ const u8 *data, int size)
+{
+ int zero_count = 0;
+ int ff_count = 0;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (data[i] == 0)
+ zero_count++;
+ else if (data[i] == 0xff)
+ ff_count++;
+ }
+ if (zero_count == size || ff_count == size) {
+ dev_warn(cd->dev, "warning data is all %s\n",
+ zero_count == size ? "zero" : "0xff");
+ return true;
+ }
+
+ return false;
+}
+
+static int goodix_berlin_dev_confirm(struct goodix_berlin_core *cd)
+{
+ u8 tx_buf[8], rx_buf[8];
+ int retry = 3;
+ int error;
+
+ memset(tx_buf, DEV_CONFIRM_VAL, sizeof(tx_buf));
+ while (retry--) {
+ error = regmap_raw_write(cd->regmap, BOOTOPTION_ADDR, tx_buf,
+ sizeof(tx_buf));
+ if (error < 0)
+ return error;
+
+ error = regmap_raw_read(cd->regmap, BOOTOPTION_ADDR, rx_buf,
+ sizeof(rx_buf));
+ if (error < 0)
+ return error;
+
+ if (!memcmp(tx_buf, rx_buf, sizeof(tx_buf)))
+ return 0;
+
+ usleep_range(5000, 5100);
+ }
+
+ dev_err(cd->dev, "device confirm failed, rx_buf: %*ph\n", 8, rx_buf);
+
+ return -EINVAL;
+}
+
+static int goodix_berlin_power_on(struct goodix_berlin_core *cd, bool on)
+{
+ int error = 0;
+
+ if (on) {
+ error = regulator_enable(cd->iovdd);
+ if (error < 0) {
+ dev_err(cd->dev, "Failed to enable iovdd: %d\n", error);
+ return error;
+ }
+
+ /* Vendor waits 3ms for IOVDD to settle */
+ usleep_range(3000, 3100);
+
+ error = regulator_enable(cd->avdd);
+ if (error < 0) {
+ dev_err(cd->dev, "Failed to enable avdd: %d\n", error);
+ goto power_off_iovdd;
+ }
+
+ /* Vendor waits 15ms for IOVDD to settle */
+ usleep_range(15000, 15100);
+
+ gpiod_set_value(cd->reset_gpio, 0);
+
+ /* Vendor waits 4ms for Firmware to initialize */
+ usleep_range(4000, 4100);
+
+ error = goodix_berlin_dev_confirm(cd);
+ if (error < 0)
+ goto power_off_gpio;
+
+ /* Vendor waits 100ms for Firmware to fully boot */
+ msleep(GOODIX_NORMAL_RESET_DELAY_MS);
+
+ return 0;
+ }
+
+power_off_gpio:
+ gpiod_set_value(cd->reset_gpio, 1);
+
+ regulator_disable(cd->avdd);
+
+power_off_iovdd:
+ regulator_disable(cd->iovdd);
+
+ return error;
+}
+
+static int goodix_berlin_read_version(struct goodix_berlin_core *cd)
+{
+ u8 buf[sizeof(struct goodix_berlin_fw_version)];
+ int retry = 2;
+ int error;
+
+ while (retry--) {
+ error = regmap_raw_read(cd->regmap, FW_VERSION_INFO_ADDR, buf, sizeof(buf));
+ if (error) {
+ dev_dbg(cd->dev, "read fw version: %d, retry %d\n", error, retry);
+ usleep_range(5000, 5100);
+ continue;
+ }
+
+ if (goodix_berlin_check_checksum(buf, sizeof(buf)))
+ break;
+
+ dev_dbg(cd->dev, "invalid fw version: checksum error\n");
+
+ error = -EINVAL;
+
+ /* Do not sleep on the last try */
+ if (retry)
+ usleep_range(10000, 11000);
+ }
+
+ if (error) {
+ dev_err(cd->dev, "failed to get fw version");
+ return error;
+ }
+
+ memcpy(&cd->fw_version, buf, sizeof(cd->fw_version));
+
+ return 0;
+}
+
+/* Only extract necessary data for runtime */
+static int goodix_berlin_convert_ic_info(struct goodix_berlin_core *cd,
+ const u8 *data, u16 length)
+{
+ struct goodix_berlin_ic_info_misc misc;
+ unsigned int offset = 0;
+ u8 param_num;
+
+ offset += sizeof(__le16); /* length */
+ offset += sizeof(struct goodix_berlin_ic_info_version);
+ offset += sizeof(struct goodix_berlin_ic_info_feature);
+
+ /* goodix_berlin_ic_info_param, variable width structure */
+ offset += 4 * sizeof(u8); /* drv_num, sen_num, button_num, force_num */
+
+ if (offset >= length)
+ goto invalid_offset;
+
+ param_num = data[offset++]; /* active_scan_rate_num */
+
+ offset += param_num * sizeof(__le16);
+
+ if (offset >= length)
+ goto invalid_offset;
+
+ param_num = data[offset++]; /* mutual_freq_num*/
+
+ offset += param_num * sizeof(__le16);
+
+ if (offset >= length)
+ goto invalid_offset;
+
+ param_num = data[offset++]; /* self_tx_freq_num */
+
+ offset += param_num * sizeof(__le16);
+
+ if (offset >= length)
+ goto invalid_offset;
+
+ param_num = data[offset++]; /* self_rx_freq_num */
+
+ offset += param_num * sizeof(__le16);
+
+ if (offset >= length)
+ goto invalid_offset;
+
+ param_num = data[offset++]; /* stylus_freq_num */
+
+ offset += param_num * sizeof(__le16);
+
+ if (offset + sizeof(misc) > length)
+ goto invalid_offset;
+
+ /* goodix_berlin_ic_info_misc */
+ memcpy(&misc, &data[offset], sizeof(misc));
+
+ cd->params.touch_data_addr = le32_to_cpu(misc.touch_data_addr);
+
+ return 0;
+
+invalid_offset:
+ dev_err(cd->dev, "ic_info length is invalid (offset %d length %d)\n",
+ offset, length);
+ return -EINVAL;
+}
+
+static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
+{
+ int error, i;
+ u16 length = 0;
+ u32 ic_addr;
+ u8 afe_data[GOODIX_IC_INFO_MAX_LEN] = { 0 };
+
+ ic_addr = GOODIX_IC_INFO_ADDR;
+
+ for (i = 0; i < 3; i++) {
+ error = regmap_raw_read(cd->regmap, ic_addr, (u8 *)&length, sizeof(length));
+ if (error) {
+ dev_info(cd->dev, "failed get ic info length, %d\n", error);
+ usleep_range(5000, 5100);
+ continue;
+ }
+
+ length = le16_to_cpu(length);
+ if (length >= GOODIX_IC_INFO_MAX_LEN) {
+ dev_info(cd->dev, "invalid ic info length %d, retry %d\n", length, i);
+ continue;
+ }
+
+ error = regmap_raw_read(cd->regmap, ic_addr, afe_data, length);
+ if (error) {
+ dev_info(cd->dev, "failed get ic info data, %d\n", error);
+ usleep_range(5000, 5100);
+ continue;
+ }
+
+ /* check whether the data is valid (ex. bus default values) */
+ if (goodix_berlin_is_dummy_data(cd, (const uint8_t *)afe_data, length)) {
+ dev_info(cd->dev, "fw info data invalid\n");
+ usleep_range(5000, 5100);
+ continue;
+ }
+
+ if (!goodix_berlin_check_checksum((const uint8_t *)afe_data, length)) {
+ dev_info(cd->dev, "fw info checksum error\n");
+ usleep_range(5000, 5100);
+ continue;
+ }
+
+ break;
+ }
+ if (i == 3) {
+ dev_err(cd->dev, "failed get ic info\n");
+ return -EINVAL;
+ }
+
+ error = goodix_berlin_convert_ic_info(cd, afe_data, length);
+ if (error) {
+ dev_err(cd->dev, "error converting ic info\n");
+ return error;
+ }
+
+ /* check some key info */
+ if (!cd->params.touch_data_addr) {
+ dev_err(cd->dev, "touch_data_addr is null\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int goodix_berlin_after_event_handler(struct goodix_berlin_core *cd)
+{
+ u8 sync_clean = 0;
+
+ return regmap_raw_write(cd->regmap, cd->params.touch_data_addr, &sync_clean, 1);
+}
+
+static void goodix_berlin_parse_finger(struct goodix_berlin_core *cd,
+ struct goodix_berlin_touch_data *touch_data,
+ u8 *buf, int touch_num)
+{
+ unsigned int id = 0, x = 0, y = 0, w = 0;
+ u8 *coor_data;
+ int i;
+
+ coor_data = &buf[IRQ_EVENT_HEAD_LEN];
+
+ for (i = 0; i < touch_num; i++) {
+ id = (coor_data[0] >> 4) & 0x0F;
+
+ if (id >= GOODIX_MAX_TOUCH) {
+ dev_warn(cd->dev, "invalid finger id %d\n", id);
+
+ touch_data->touch_num = 0;
+ return;
+ }
+
+ x = le16_to_cpup((__le16 *)(coor_data + 2));
+ y = le16_to_cpup((__le16 *)(coor_data + 4));
+ w = le16_to_cpup((__le16 *)(coor_data + 6));
+
+ touch_data->coords[id].status = GOODIX_BERLIN_TS_TOUCH;
+ touch_data->coords[id].x = x;
+ touch_data->coords[id].y = y;
+ touch_data->coords[id].w = w;
+
+ coor_data += BYTES_PER_POINT;
+ }
+
+ touch_data->touch_num = touch_num;
+}
+
+static int goodix_berlin_touch_handler(struct goodix_berlin_core *cd,
+ u8 *pre_buf, u32 pre_buf_len)
+{
+ static u8 buffer[IRQ_EVENT_HEAD_LEN + BYTES_PER_POINT * GOODIX_MAX_TOUCH + 2];
+ struct goodix_berlin_touch_data *touch_data = &cd->ts_event.touch_data;
+ u8 point_type = 0;
+ u8 touch_num = 0;
+ int error = 0;
+
+ memset(&cd->ts_event, 0, sizeof(cd->ts_event));
+
+ /* copy pre-data to buffer */
+ memcpy(buffer, pre_buf, pre_buf_len);
+
+ touch_num = buffer[2] & 0x0F;
+
+ if (touch_num > GOODIX_MAX_TOUCH) {
+ dev_warn(cd->dev, "invalid touch num %d\n", touch_num);
+ return -EINVAL;
+ }
+
+ /* read more data if more than 2 touch events */
+ if (unlikely(touch_num > 2)) {
+ error = regmap_raw_read(cd->regmap,
+ cd->params.touch_data_addr + pre_buf_len,
+ &buffer[pre_buf_len],
+ (touch_num - 2) * BYTES_PER_POINT);
+ if (error) {
+ dev_err(cd->dev, "failed get touch data\n");
+ return error;
+ }
+ }
+
+ goodix_berlin_after_event_handler(cd);
+
+ if (!touch_num)
+ goto out_touch_handler;
+
+ point_type = buffer[IRQ_EVENT_HEAD_LEN] & 0x0F;
+
+ if (point_type == POINT_TYPE_STYLUS || point_type == POINT_TYPE_STYLUS_HOVER) {
+ dev_warn_once(cd->dev, "Stylus event type not handled\n");
+ return 0;
+ }
+
+ if (!goodix_berlin_check_checksum(&buffer[IRQ_EVENT_HEAD_LEN],
+ touch_num * BYTES_PER_POINT + 2)) {
+ dev_dbg(cd->dev, "touch data checksum error\n");
+ dev_dbg(cd->dev, "data: %*ph\n",
+ touch_num * BYTES_PER_POINT + 2, &buffer[IRQ_EVENT_HEAD_LEN]);
+ return -EINVAL;
+ }
+
+out_touch_handler:
+ cd->ts_event.event_type = GOODIX_BERLIN_EVENT_TOUCH;
+ goodix_berlin_parse_finger(cd, touch_data, buffer, touch_num);
+
+ return 0;
+}
+
+static int goodix_berlin_event_handler(struct goodix_berlin_core *cd)
+{
+ int pre_read_len;
+ u8 pre_buf[32];
+ u8 event_status;
+ int error;
+
+ pre_read_len = IRQ_EVENT_HEAD_LEN + BYTES_PER_POINT * 2 +
+ COOR_DATA_CHECKSUM_SIZE;
+
+ error = regmap_raw_read(cd->regmap, cd->params.touch_data_addr, pre_buf,
+ pre_read_len);
+ if (error) {
+ dev_err(cd->dev, "failed get event head data\n");
+ return error;
+ }
+
+ if (pre_buf[0] == 0x00)
+ return -EINVAL;
+
+ if (!goodix_berlin_check_checksum(pre_buf, IRQ_EVENT_HEAD_LEN)) {
+ dev_warn(cd->dev, "touch head checksum err : %*ph\n",
+ IRQ_EVENT_HEAD_LEN, pre_buf);
+ return -EINVAL;
+ }
+
+ event_status = pre_buf[0];
+ if (event_status & GOODIX_TOUCH_EVENT)
+ return goodix_berlin_touch_handler(cd, pre_buf, pre_read_len);
+
+ if (event_status & GOODIX_REQUEST_EVENT) {
+ cd->ts_event.event_type = GOODIX_BERLIN_EVENT_REQUEST;
+ if (pre_buf[2] == GOODIX_REQUEST_CODE_RESET)
+ cd->ts_event.request_code = GOODIX_BERLIN_REQUEST_TYPE_RESET;
+ else
+ dev_warn(cd->dev, "unsupported request code 0x%x\n", pre_buf[2]);
+ }
+
+ goodix_berlin_after_event_handler(cd);
+
+ return 0;
+}
+
+static void goodix_berlin_report_finger(struct goodix_berlin_core *cd)
+{
+ struct goodix_berlin_touch_data *touch_data = &cd->ts_event.touch_data;
+ int i;
+
+ mutex_lock(&cd->input_dev->mutex);
+
+ for (i = 0; i < GOODIX_MAX_TOUCH; i++) {
+ bool pressed = touch_data->coords[i].status == GOODIX_BERLIN_TS_TOUCH;
+
+ input_mt_slot(cd->input_dev, i);
+ input_mt_report_slot_state(cd->input_dev, MT_TOOL_FINGER, pressed);
+
+ if (touch_data->coords[i].status == GOODIX_BERLIN_TS_TOUCH) {
+ dev_dbg(cd->dev, "report: id[%d], x %d, y %d, w %d\n", i,
+ touch_data->coords[i].x,
+ touch_data->coords[i].y,
+ touch_data->coords[i].w);
+
+ touchscreen_report_pos(cd->input_dev, &cd->props,
+ touch_data->coords[i].x,
+ touch_data->coords[i].y, true);
+ input_report_abs(cd->input_dev, ABS_MT_TOUCH_MAJOR,
+ touch_data->coords[i].w);
+ }
+ }
+
+ input_mt_sync_frame(cd->input_dev);
+ input_sync(cd->input_dev);
+
+ mutex_unlock(&cd->input_dev->mutex);
+}
+
+static int goodix_berlin_request_handle(struct goodix_berlin_core *cd)
+{
+ /* TOFIX: Handle more request codes */
+ if (cd->ts_event.request_code != GOODIX_BERLIN_REQUEST_TYPE_RESET) {
+ dev_info(cd->dev, "can't handle request type 0x%x\n",
+ cd->ts_event.request_code);
+ return -EINVAL;
+ }
+
+ gpiod_set_value(cd->reset_gpio, 1);
+ usleep_range(2000, 2100);
+ gpiod_set_value(cd->reset_gpio, 0);
+
+ msleep(GOODIX_NORMAL_RESET_DELAY_MS);
+
+ return 0;
+}
+
+static irqreturn_t goodix_berlin_threadirq_func(int irq, void *data)
+{
+ struct goodix_berlin_core *cd = data;
+ int error;
+
+ error = goodix_berlin_event_handler(cd);
+ if (likely(!error)) {
+ switch (cd->ts_event.event_type) {
+ case GOODIX_BERLIN_EVENT_TOUCH:
+ goodix_berlin_report_finger(cd);
+ break;
+
+ case GOODIX_BERLIN_EVENT_REQUEST:
+ goodix_berlin_request_handle(cd);
+ break;
+
+ /* TOFIX: Handle more request types */
+ case GOODIX_BERLIN_EVENT_INVALID:
+ break;
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int goodix_berlin_input_dev_config(struct goodix_berlin_core *cd,
+ const struct input_id *id)
+{
+ struct input_dev *input_dev;
+ int error;
+
+ input_dev = devm_input_allocate_device(cd->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ cd->input_dev = input_dev;
+ input_set_drvdata(input_dev, cd);
+
+ input_dev->name = "Goodix Berlin Capacitive TouchScreen";
+ input_dev->phys = "input/ts";
+ input_dev->dev.parent = cd->dev;
+
+ memcpy(&input_dev->id, id, sizeof(*id));
+
+ /* Set input parameters */
+ input_set_abs_params(cd->input_dev, ABS_MT_POSITION_X, 0, SZ_64K - 1, 0, 0);
+ input_set_abs_params(cd->input_dev, ABS_MT_POSITION_Y, 0, SZ_64K - 1, 0, 0);
+ input_set_abs_params(cd->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(cd->input_dev, true, &cd->props);
+
+ error = input_mt_init_slots(cd->input_dev, GOODIX_MAX_TOUCH, INPUT_MT_DIRECT);
+ if (error)
+ return error;
+
+ return input_register_device(cd->input_dev);
+}
+
+static int goodix_berlin_pm_suspend(struct device *dev)
+{
+ struct goodix_berlin_core *cd = dev_get_drvdata(dev);
+
+ disable_irq(cd->irq);
+
+ return goodix_berlin_power_on(cd, false);
+}
+
+static int goodix_berlin_pm_resume(struct device *dev)
+{
+ struct goodix_berlin_core *cd = dev_get_drvdata(dev);
+ int error;
+
+ error = goodix_berlin_power_on(cd, true);
+ if (error)
+ return error;
+
+ enable_irq(cd->irq);
+
+ return 0;
+}
+
+EXPORT_GPL_SIMPLE_DEV_PM_OPS(goodix_berlin_pm_ops,
+ goodix_berlin_pm_suspend,
+ goodix_berlin_pm_resume);
+
+static void goodix_berlin_power_off(void *data)
+{
+ struct goodix_berlin_core *cd = data;
+
+ goodix_berlin_power_on(cd, false);
+}
+
+int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
+ struct regmap *regmap)
+{
+ struct goodix_berlin_core *cd;
+ int error;
+
+ if (irq <= 0)
+ return -EINVAL;
+
+ cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL);
+ if (!cd)
+ return -ENOMEM;
+
+ cd->dev = dev;
+ cd->regmap = regmap;
+ cd->irq = irq;
+
+ cd->reset_gpio = devm_gpiod_get_optional(cd->dev, "reset", GPIOF_OUT_INIT_HIGH);
+ if (IS_ERR(cd->reset_gpio))
+ return dev_err_probe(cd->dev, PTR_ERR(cd->reset_gpio),
+ "Failed to request reset gpio\n");
+
+ cd->avdd = devm_regulator_get(cd->dev, "avdd");
+ if (IS_ERR(cd->avdd))
+ return dev_err_probe(cd->dev, PTR_ERR(cd->avdd),
+ "Failed to request avdd regulator\n");
+
+ cd->iovdd = devm_regulator_get(cd->dev, "iovdd");
+ if (IS_ERR(cd->iovdd))
+ return dev_err_probe(cd->dev, PTR_ERR(cd->iovdd),
+ "Failed to request iovdd regulator\n");
+
+ error = goodix_berlin_input_dev_config(cd, id);
+ if (error < 0) {
+ dev_err(cd->dev, "failed set input device");
+ return error;
+ }
+
+ error = devm_request_threaded_irq(dev, irq, NULL,
+ goodix_berlin_threadirq_func,
+ IRQF_ONESHOT, "goodix-berlin", cd);
+ if (error) {
+ dev_err(dev, "request threaded irq failed: %d\n", error);
+ return error;
+ }
+
+ dev_set_drvdata(dev, cd);
+
+ error = goodix_berlin_power_on(cd, true);
+ if (error) {
+ dev_err(cd->dev, "failed power on");
+ return error;
+ }
+
+ error = devm_add_action_or_reset(dev, goodix_berlin_power_off, cd);
+ if (error)
+ return error;
+
+ error = goodix_berlin_read_version(cd);
+ if (error < 0) {
+ dev_err(cd->dev, "failed to get version info");
+ return error;
+ }
+
+ error = goodix_berlin_get_ic_info(cd);
+ if (error) {
+ dev_err(cd->dev, "invalid ic info, abort");
+ return error;
+ }
+
+ dev_dbg(cd->dev, "Goodix Berlin %s Touchscreen Controller", cd->fw_version.patch_pid);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(goodix_berlin_probe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Goodix Berlin Core Touchscreen driver");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 3/4] input: touchscreen: add I2C support for Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2023-06-15 10:27 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg
Cc: linux-input, linux-arm-msm, devicetree, linux-kernel,
Neil Armstrong
In-Reply-To: <20230606-topic-goodix-berlin-upstream-initial-v2-0-26bc8fe1e90e@linaro.org>
Add initial support for the new Goodix "Berlin" touchscreen ICs
over the I2C interface.
This initial driver is derived from the Goodix goodix_ts_berlin
available at [1] and [2] and only supports the GT9916 IC
present on the Qualcomm SM8550 MTP & QRD touch panel.
The current implementation only supports BerlinD, aka GT9916.
[1] https://github.com/goodix/goodix_ts_berlin
[2] https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/input/touchscreen/Kconfig | 14 ++++++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/goodix_berlin_i2c.c | 69 +++++++++++++++++++++++++++
3 files changed, 84 insertions(+)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1a6f6f6da991..5e21cca6025d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -421,6 +421,20 @@ config TOUCHSCREEN_GOODIX_BERLIN_CORE
depends on REGMAP
tristate
+config TOUCHSCREEN_GOODIX_BERLIN_I2C
+ tristate "Goodix Berlin I2C touchscreen"
+ depends on I2C
+ depends on REGMAP_I2C
+ select TOUCHSCREEN_GOODIX_BERLIN_CORE
+ help
+ Say Y here if you have a Goodix Berlin IC connected to
+ your system via I2C.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called goodix_berlin_i2c.
+
config TOUCHSCREEN_HIDEEP
tristate "HiDeep Touch IC"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 29cdb042e104..921a2da0c2be 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_CORE) += goodix_berlin_core.o
+obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C) += goodix_berlin_i2c.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
diff --git a/drivers/input/touchscreen/goodix_berlin_i2c.c b/drivers/input/touchscreen/goodix_berlin_i2c.c
new file mode 100644
index 000000000000..6407b2258eb1
--- /dev/null
+++ b/drivers/input/touchscreen/goodix_berlin_i2c.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Goodix Berlin Touchscreen Driver
+ *
+ * Copyright (C) 2020 - 2021 Goodix, Inc.
+ * Copyright (C) 2023 Linaro Ltd.
+ *
+ * Based on goodix_ts_berlin driver.
+ */
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include "goodix_berlin.h"
+
+#define I2C_MAX_TRANSFER_SIZE 256
+
+static const struct regmap_config goodix_berlin_i2c_regmap_conf = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_raw_read = I2C_MAX_TRANSFER_SIZE,
+ .max_raw_write = I2C_MAX_TRANSFER_SIZE,
+};
+
+/* vendor & product left unassigned here, should probably be updated from fw info */
+static const struct input_id goodix_berlin_i2c_input_id = {
+ .bustype = BUS_I2C,
+};
+
+static int goodix_berlin_i2c_probe(struct i2c_client *client)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i2c(client, &goodix_berlin_i2c_regmap_conf);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return goodix_berlin_probe(&client->dev, client->irq,
+ &goodix_berlin_i2c_input_id, regmap);
+}
+
+static const struct i2c_device_id goodix_berlin_i2c_id[] = {
+ { "gt9916", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id);
+
+static const struct of_device_id goodix_berlin_i2c_of_match[] = {
+ { .compatible = "goodix,gt9916", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match);
+
+static struct i2c_driver goodix_berlin_i2c_driver = {
+ .driver = {
+ .name = "goodix-berlin-i2c",
+ .of_match_table = goodix_berlin_i2c_of_match,
+ .pm = pm_sleep_ptr(&goodix_berlin_pm_ops),
+ },
+ .probe = goodix_berlin_i2c_probe,
+ .id_table = goodix_berlin_i2c_id,
+};
+module_i2c_driver(goodix_berlin_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Goodix Berlin I2C Touchscreen driver");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/4] dt-bindings: input: document Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2023-06-15 10:27 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg
Cc: linux-input, linux-arm-msm, devicetree, linux-kernel,
Neil Armstrong
In-Reply-To: <20230606-topic-goodix-berlin-upstream-initial-v2-0-26bc8fe1e90e@linaro.org>
Document the Goodix GT9916 wich is part of the "Berlin" serie
of Touchscreen controllers IC from Goodix.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
.../bindings/input/touchscreen/goodix,gt9916.yaml | 95 ++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml b/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml
new file mode 100644
index 000000000000..d90f045ac06c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/goodix,gt9916.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Goodix Berlin series touchscreen controller
+
+description: The Goodix Berlin series of touchscreen controllers
+ be connected to either I2C or SPI buses.
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+allOf:
+ - $ref: touchscreen.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - goodix,gt9916
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ avdd-supply:
+ description: Analog power supply regulator on AVDD pin
+
+ vddio-supply:
+ description: power supply regulator on VDDIO pin
+
+ spi-max-frequency: true
+ touchscreen-inverted-x: true
+ touchscreen-inverted-y: true
+ touchscreen-size-x: true
+ touchscreen-size-y: true
+ touchscreen-swapped-x-y: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - avdd-supply
+ - touchscreen-size-x
+ - touchscreen-size-y
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ touchscreen@5d {
+ compatible = "goodix,gt9916";
+ reg = <0x5d>;
+ interrupt-parent = <&gpio>;
+ interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ avdd-supply = <&ts_avdd>;
+ touchscreen-size-x = <1024>;
+ touchscreen-size-y = <768>;
+ };
+ };
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <1>;
+ cs-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
+ touchscreen@0 {
+ compatible = "goodix,gt9916";
+ reg = <0>;
+ interrupt-parent = <&gpio>;
+ interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ avdd-supply = <&ts_avdd>;
+ spi-max-frequency = <1000000>;
+ touchscreen-size-x = <1024>;
+ touchscreen-size-y = <768>;
+ };
+ };
+
+...
--
2.34.1
^ permalink raw reply related
* [PATCH v2 0/4] input: touchscreen: add initial support for Goodix Berlin touchscreen IC
From: Neil Armstrong @ 2023-06-15 10:26 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg
Cc: linux-input, linux-arm-msm, devicetree, linux-kernel,
Neil Armstrong
These touchscreen ICs support SPI, I2C and I3C interface, up to
10 finger touch, stylus and gestures events.
This initial driver is derived from the Goodix goodix_ts_berlin
available at [1] and [2] and only supports the GT9916 IC
present on the Qualcomm SM8550 MTP & QRD touch panel.
The current implementation only supports BerlinD, aka GT9916.
Support for advanced features like:
- Firmware & config update
- Stylus events
- Gestures events
- Previous revisions support (BerlinA or BerlinB)
is not included in current version.
The current support will work with currently flashed firmware
and config, and bail out if firmware or config aren't flashed yet.
[1] https://github.com/goodix/goodix_ts_berlin
[2] https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Changes in v2:
- Huge cleanups after Jeff's review:
- switch to error instead of ret
- drop dummy vendor/product ids
- drop unused defined/enums
- drop unused ic_info and only keep needes values
- cleanup namings and use goodix_berlin_ everywhere
- fix regulator setup
- fix default variables value when assigned afterwars
- removed indirections
- dropped debugfs
- cleaned input_dev setup
- dropped _remove()
- sync'ed i2c and spi drivers
- fixed yaml bindings
- Link to v1: https://lore.kernel.org/r/20230606-topic-goodix-berlin-upstream-initial-v1-0-4a0741b8aefd@linaro.org
---
Neil Armstrong (4):
dt-bindings: input: document Goodix Berlin Touchscreen IC
input: touchscreen: add core support for Goodix Berlin Touchscreen IC
input: touchscreen: add I2C support for Goodix Berlin Touchscreen IC
input: touchscreen: add SPI support for Goodix Berlin Touchscreen IC
.../bindings/input/touchscreen/goodix,gt9916.yaml | 95 +++
drivers/input/touchscreen/Kconfig | 32 +
drivers/input/touchscreen/Makefile | 3 +
drivers/input/touchscreen/goodix_berlin.h | 178 ++++++
drivers/input/touchscreen/goodix_berlin_core.c | 681 +++++++++++++++++++++
drivers/input/touchscreen/goodix_berlin_i2c.c | 69 +++
drivers/input/touchscreen/goodix_berlin_spi.c | 172 ++++++
7 files changed, 1230 insertions(+)
---
base-commit: 6db29e14f4fb7bce9eb5290288e71b05c2b0d118
change-id: 20230606-topic-goodix-berlin-upstream-initial-ba97e8ec8f4c
Best regards,
--
Neil Armstrong <neil.armstrong@linaro.org>
^ permalink raw reply
* Re: [PATCH RFC 4/4] input: touchscreen: add SPI support for Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2023-06-15 8:20 UTC (permalink / raw)
To: Jeff LaBundy
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg, linux-input,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <ZIdQ723G8/a0tNEZ@nixie71>
On 12/06/2023 19:07, Jeff LaBundy wrote:
> Hi Neil,
>
> [...]
>
>>>> +static const struct input_id goodix_berlin_spi_input_id = {
>>>> + .bustype = BUS_SPI,
>>>> + .vendor = 0x0416,
>>>> + .product = 0x1001,
>>>
>>> After having seen these in the I2C counterpart; consider defining them
>>> in goodix_berlin.h.
>>
>> To be honest, I blindly copied it from goodix.c because the vendor
>> driver puts random values here.
>>
>> input_dev->id.product = 0xDEAD;
>> input_dev->id.vendor = 0xBEEF;
>>
>> So what should I set ?
>
> If there is no explicit guidance from the vendor, I would simply leave
> these unassigned; in theory one would imagine that this controller would
> have a different product ID than other models.
I'll leave those unassigned for now, and perhaps we could find
some firmware info value that could be used here.
Neil
>
> [...]
>
> Kind regards,
> Jeff LaBundy
^ permalink raw reply
* Re: [PATCH] HID: logitech-hidpp: Handle timeout differently from busy
From: Linux regression tracking (Thorsten Leemhuis) @ 2023-06-15 7:24 UTC (permalink / raw)
To: Jiri Kosina, Bastien Nocera, Benjamin Tissoires
Cc: linux-input, linux-kernel, Peter F . Patel-Schneider,
Filipe Laíns, Nestor Lopez Casado, Mark Lord,
Linux regressions mailing list
In-Reply-To: <42b6e582-f642-7521-135a-449140984211@leemhuis.info>
On 06.06.23 20:18, Linux regression tracking (Thorsten Leemhuis) wrote:
> On 06.06.23 15:27, Jiri Kosina wrote:
>> On Mon, 5 Jun 2023, Linux regression tracking (Thorsten Leemhuis) wrote:
>>>>>> If an attempt at contacting a receiver or a device fails because the
>>>>>> receiver or device never responds, don't restart the communication, only
>>>>>> restart it if the receiver or device answers that it's busy, as originally
>>>>>> intended.
>>>>>> Signed-off-by: Bastien Nocera <hadess@hadess.net>
> [...]
>>>> Unfortunately it doesn't seem to cure the reported issue (while reverting
>>>> 586e8fede79 does):
> [...]
>> This should now all be fixed by
>>
>> https://git.kernel.org/linus/7c28afd5512e371773dbb2bf95a31ed5625651d9
>
> Jiri, Benjamin, many many thx for working on this.
FWIW, it seems things work for many people, but something still is not
completely right:
```
https://bugzilla.kernel.org/show_bug.cgi?id=217412
--- Comment #47 from Mark Blakeney ---
@Juha, kernel 6.3.7 adds the 2 patches intended to fix this bug and the
startup delay is now gone. However, I have had 2 cases over the last 5
days in which I have been running 6.3.7 where my mouse fails to be
detected at all after startup. I have to pull the Logitech receiver
out/in to get the mouse working. Never seen this issue before so I
suspect the patches are not right.
```
Ciao, Thorsten
^ permalink raw reply
* [PATCH] HID: intel-ish-hid: ipc: Add Arrow Lake PCI device ID
From: Even Xu @ 2023-06-15 0:26 UTC (permalink / raw)
To: linux-input, jikos, benjamin.tissoires, srinivas.pandruvada; +Cc: Even Xu
Add device ID of Arrow Lake-H into ishtp support list.
Signed-off-by: Even Xu <even.xu@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/hid/intel-ish-hid/ipc/hw-ish.h | 1 +
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
index fc108f1..e99f3a3 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -33,6 +33,7 @@
#define ADL_N_DEVICE_ID 0x54FC
#define RPL_S_DEVICE_ID 0x7A78
#define MTL_P_DEVICE_ID 0x7E45
+#define ARL_H_DEVICE_ID 0x7745
#define REVISION_ID_CHT_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 7120b30..55cb250 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -44,6 +44,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ARL_H_DEVICE_ID)},
{0, }
};
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH RFC 1/4] dt-bindings: input: document Goodix Berlin Touchscreen IC
From: Rob Herring @ 2023-06-14 22:28 UTC (permalink / raw)
To: Neil Armstrong
Cc: Dmitry Torokhov, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg, linux-input,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20230606-topic-goodix-berlin-upstream-initial-v1-1-4a0741b8aefd@linaro.org>
On Tue, Jun 06, 2023 at 04:31:56PM +0200, Neil Armstrong wrote:
> Document the Goodix GT9916 wich is part of the "Berlin" serie
series
> of Touchscreen controllers IC from Goodix.
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> .../bindings/input/touchscreen/goodix-berlin.yaml | 81 ++++++++++++++++++++++
> 1 file changed, 81 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix-berlin.yaml b/Documentation/devicetree/bindings/input/touchscreen/goodix-berlin.yaml
> new file mode 100644
> index 000000000000..4c24a541e919
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix-berlin.yaml
> @@ -0,0 +1,81 @@
> +# SPDX-License-Identifier: GPL-2.0
Dual license
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/touchscreen/goodix-berlin.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Goodix Belin series touchscreen controller
Berlin?
> +
> +maintainers:
> + - Neil Armstrong <neil.armstrong@linaro.org>
Would be nice to have a description which includes that the device has
both I2C and SPI interfaces.
> +
> +allOf:
> + - $ref: touchscreen.yaml#
SPI devices should include spi-peripheral-props.yaml
> +
> +properties:
> + compatible:
> + enum:
> + - goodix,gt9916
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + reset-gpios:
> + maxItems: 1
> +
> + avdd-supply:
> + description: Analog power supply regulator on AVDD pin
> +
> + vddio-supply:
> + description: GPIO power supply regulator on VDDIO pin
> +
> + spi-max-frequency: true
> + touchscreen-inverted-x: true
> + touchscreen-inverted-y: true
> + touchscreen-size-x: true
> + touchscreen-size-y: true
> + touchscreen-swapped-x-y: true
> +
> +additionalProperties: false
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> + #include <dt-bindings/gpio/gpio.h>
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + gt9916@5d {
> + compatible = "goodix,gt9916";
> + reg = <0x5d>;
> + interrupt-parent = <&gpio>;
> + interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
> + reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
> + };
> + };
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> + #include <dt-bindings/gpio/gpio.h>
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + num-cs = <1>;
> + cs-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
> + gt9916@0 {
> + compatible = "goodix,gt9916";
> + reg = <0>;
> + interrupt-parent = <&gpio>;
> + interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
> + reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
> + };
> + };
> +
> +...
>
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v1 7/7] dt-bindings: input: touchscreen: edt-ft5x06: Add 'threshold' property
From: Rob Herring @ 2023-06-14 19:21 UTC (permalink / raw)
To: Oleksij Rempel
Cc: linux-arm-kernel, Michael Turquette, linux-mmc, Abel Vesa,
devicetree, linux-crypto, David S. Miller, Fabio Estevam,
Dmitry Torokhov, Rob Herring, linux-input, Stephen Boyd,
Daniel Lezcano, linux-clk, Anson Huang, Ulf Hansson, Mark Brown,
Conor Dooley, linux-kernel, kernel, Thomas Gleixner,
NXP Linux Team, Shawn Guo, Dario Binacchi, Peng Fan, Herbert Xu,
Krzysztof Kozlowski, Sascha Hauer, Michael Trimarchi, Marek Vasut
In-Reply-To: <20230601101451.357662-8-o.rempel@pengutronix.de>
On Thu, 01 Jun 2023 12:14:51 +0200, Oleksij Rempel wrote:
> Add a new property 'threshold' to the edt-ft5x06 touchscreen binding.
> This property allows setting the "click"-threshold in the range from 0
> to 255. This change addresses the following dtbs_check warning:
> imx6dl-lanmcu.dtb: touchscreen@38: 'threshold' does not match any of the
> regexes: 'pinctrl-[0-9]+'
> From schema:
> Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> .../devicetree/bindings/input/touchscreen/edt-ft5x06.yaml | 6 ++++++
> 1 file changed, 6 insertions(+)
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v1 6/7] dt-bindings: clock: imx6q: Allow single optional clock and add enet_ref_pad
From: Rob Herring @ 2023-06-14 19:18 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Herbert Xu,
David S. Miller, Dmitry Torokhov, Ulf Hansson, kernel, Peng Fan,
Fabio Estevam, NXP Linux Team, Daniel Lezcano, Thomas Gleixner,
Michael Trimarchi, Mark Brown, Dario Binacchi, Anson Huang,
Marek Vasut, linux-clk, devicetree, linux-arm-kernel,
linux-kernel, linux-crypto, linux-input, linux-mmc
In-Reply-To: <20230601101451.357662-7-o.rempel@pengutronix.de>
On Thu, Jun 01, 2023 at 12:14:50PM +0200, Oleksij Rempel wrote:
> All clocks for this driver are optional, so this change allows the
It's not about what the driver supports, but the h/w. You are saying
this SoC can operate with only 1 of any of the clock inputs?
> 'clocks' and 'clock-names' properties to accept a single clock.
> Additionally, 'enet_ref_pad' clock is added. This resolves the following
> dtbs_check warning:
> imx6dl-alti6p.dtb: clock-controller@20c4000: clocks: [[24]] is too short
> From schema: Documentation/devicetree/bindings/clock/imx6q-clock.yaml
>
> imx6dl-alti6p.dtb: clock-controller@20c4000: clock-names:0: 'osc' was
> expected
> From schema: Documentation/devicetree/bindings/clock/imx6q-clock.yaml
>
> imx6dl-alti6p.dtb: clock-controller@20c4000: clock-names:
> ['enet_ref_pad'] is too short
> From schema: Documentation/devicetree/bindings/clock/imx6q-clock.yaml
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> .../devicetree/bindings/clock/imx6q-clock.yaml | 15 +++++++++------
> 1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.yaml b/Documentation/devicetree/bindings/clock/imx6q-clock.yaml
> index bae4fcb3aacc..ed65d19c2e0e 100644
> --- a/Documentation/devicetree/bindings/clock/imx6q-clock.yaml
> +++ b/Documentation/devicetree/bindings/clock/imx6q-clock.yaml
> @@ -28,20 +28,23 @@ properties:
> const: 1
>
> clocks:
> + minItems: 1
> items:
> - description: 24m osc
> - description: 32k osc
> - description: ckih1 clock input
> - description: anaclk1 clock input
> - description: anaclk2 clock input
> + - description: enet_ref_pad
>
> clock-names:
> - items:
> - - const: osc
> - - const: ckil
> - - const: ckih1
> - - const: anaclk1
> - - const: anaclk2
> + enum:
> + - osc
> + - ckil
> + - ckih1
> + - anaclk1
> + - anaclk2
> + - enet_ref_pad
>
> fsl,pmic-stby-poweroff:
> $ref: /schemas/types.yaml#/definitions/flag
> --
> 2.39.2
>
^ permalink raw reply
* Re: [PATCH v1 5/7] dt-bindings: clock: imx6ul: Support optional enet*_ref_pad clocks
From: Rob Herring @ 2023-06-14 19:13 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Herbert Xu,
David S. Miller, Dmitry Torokhov, Ulf Hansson, kernel, Peng Fan,
Fabio Estevam, NXP Linux Team, Daniel Lezcano, Thomas Gleixner,
Michael Trimarchi, Mark Brown, Dario Binacchi, Anson Huang,
Marek Vasut, linux-clk, devicetree, linux-arm-kernel,
linux-kernel, linux-crypto, linux-input, linux-mmc
In-Reply-To: <20230601101451.357662-6-o.rempel@pengutronix.de>
On Thu, Jun 01, 2023 at 12:14:49PM +0200, Oleksij Rempel wrote:
> Extend the 'clocks' and 'clock-names' properties to support optional
> 'enet1_ref_pad' and 'enet2_ref_pad' clocks to resolve the following
> dtbs_check warning:
> imx6ul-prti6g.dtb: clock-controller@20c4000: clocks: [[17], [18], [19],
> [20], [21]] is too long
> From schema: Documentation/devicetree/bindings/clock/imx6ul-clock.yaml
>
> imx6ul-prti6g.dtb: clock-controller@20c4000: clock-names: ['ckil',
> 'osc', 'ipp_di0', 'ipp_di1', 'enet1_ref_pad'] is too long
> From schema: Documentation/devicetree/bindings/clock/imx6ul-clock.yaml
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> Documentation/devicetree/bindings/clock/imx6ul-clock.yaml | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/clock/imx6ul-clock.yaml b/Documentation/devicetree/bindings/clock/imx6ul-clock.yaml
> index be54d4df5afa..d6a36fe575d3 100644
> --- a/Documentation/devicetree/bindings/clock/imx6ul-clock.yaml
> +++ b/Documentation/devicetree/bindings/clock/imx6ul-clock.yaml
> @@ -28,18 +28,24 @@ properties:
> const: 1
>
> clocks:
> + minItems: 4
> items:
> - description: 32k osc
> - description: 24m osc
> - description: ipp_di0 clock input
> - description: ipp_di1 clock input
> + - description: Optional lenet1_ref_pad or enet2_ref_pad clocks
> + - description: Optional lenet1_ref_pad or enet2_ref_pad clocks
>
> clock-names:
> + minItems: 4
> items:
> - const: ckil
> - const: osc
> - const: ipp_di0
> - const: ipp_di1
> + - enum: [enet1_ref_pad, enet2_ref_pad]
> + - enum: [enet1_ref_pad, enet2_ref_pad]
pattern: '^enet[12]_ref_pad$'
Rob
^ permalink raw reply
* Re: [PATCH v1 3/7] dt-bindings: timer: gpt: Support 3rd clock for i.MX6DL
From: Rob Herring @ 2023-06-14 19:03 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Herbert Xu,
David S. Miller, Dmitry Torokhov, Ulf Hansson, kernel, Peng Fan,
Fabio Estevam, NXP Linux Team, Daniel Lezcano, Thomas Gleixner,
Michael Trimarchi, Mark Brown, Dario Binacchi, Anson Huang,
Marek Vasut, linux-clk, devicetree, linux-arm-kernel,
linux-kernel, linux-crypto, linux-input, linux-mmc
In-Reply-To: <20230601101451.357662-4-o.rempel@pengutronix.de>
On Thu, Jun 01, 2023 at 12:14:47PM +0200, Oleksij Rempel wrote:
> Add support for a 3rd clock, 'osc_per', for i.MX6DL to the 'fsl,imxgpt'
> binding to resolve the following dtbs_check warning:
> imx6dl-alti6p.dtb: timer@2098000: clocks: [[2, 119], [2, 120], [2, 237]]
> is too long
> From schema: Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
> imx6dl-alti6p.dtb: timer@2098000: clock-names: ['ipg', 'per', 'osc_per']
> is too long
> From schema: Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> .../devicetree/bindings/timer/fsl,imxgpt.yaml | 22 ++++++++++++++-----
> 1 file changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
> index adf617b8f353..21ff51c3f38f 100644
> --- a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
> +++ b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
> @@ -46,14 +46,24 @@ properties:
> maxItems: 1
>
> clocks:
> - items:
> - - description: SoC GPT ipg clock
> - - description: SoC GPT per clock
> + anyOf:
No need for anyOf. Just add the 3rd entry and 'minItems: 2'.
> + - items:
> + - description: SoC GPT ipg clock
> + - description: SoC GPT per clock
> + - items:
> + - description: SoC GPT ipg clock
> + - description: SoC GPT per clock
> + - description: SoC GPT osc_per clock
>
> clock-names:
> - items:
> - - const: ipg
> - - const: per
> + anyOf:
> + - items:
> + - const: ipg
> + - const: per
> + - items:
> + - const: ipg
> + - const: per
> + - const: osc_per
>
> required:
> - compatible
> --
> 2.39.2
>
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: input: Add bindings for Azoteq IQS7210A/7211A/E
From: Rob Herring @ 2023-06-14 18:52 UTC (permalink / raw)
To: Jeff LaBundy; +Cc: dmitry.torokhov, robh+dt, devicetree, linux-input
In-Reply-To: <ZHVEa0yM1LLUJEfO@nixie71>
On Mon, 29 May 2023 19:33:47 -0500, Jeff LaBundy wrote:
> Add bindings for the Azoteq IQS7210A/7211A/E family of trackpad/
> touchscreen controllers.
>
> Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> ---
> Changes in v2:
> - Renamed 'azoteq,default-comms' to 'azoteq,forced-comms-default' and redefined
> 0, 1 and 2 as unspecified, 0 and 1, respectively
> - Defined ATI upon its first occurrence
> - Redefined 'azoteq,gesture-angle' in units of degrees
> - Declared 'azoteq,rx-enable' to depend upon 'azoteq,tx-enable' within the
> 'trackpad' node
>
> Hi Rob,
>
> I attempted to reference existing properties from a common binding [1] as per
> your feedback in [2], however 'make DT_CHECKER_FLAGS=-m dt_binding_check' fails
> with the message 'Vendor specific properties must have a type and description
> unless they have a defined, common suffix.'
>
> This seems related to the discussion in [3], where you warned that the tooling
> cannot yet deduce that vendor-specific properties have already been typed in an
> externally $ref'd binding. The only other example of a common vendor schema is
> [4], but in that case the common properties are defined under arbitraily named
> pinmux config nodes. As such, they are part of 'additionalProperties' instead of
> 'properties' and hence exempt from this particular validation.
>
> Please let me know if I am mistaken (surprise!), in which case I will continue
> on this path and send a v3. Otherwise, I would like to suggest that the review
> moves forward under the premise that I will happily consolidate these bindings
> once the tooling supports this idea.
>
> Kind regards,
> Jeff LaBundy
>
> [1] https://github.com/jlabundy/linux/tree/azoteq-common (WIP)
> [2] https://patchwork.kernel.org/comment/25003573/
> [3] https://patchwork.kernel.org/comment/23867857/
> [4] Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.yaml
>
> .../input/touchscreen/azoteq,iqs7211.yaml | 769 ++++++++++++++++++
> 1 file changed, 769 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/azoteq,iqs7211.yaml
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: input: Add bindings for Azoteq IQS7210A/7211A/E
From: Rob Herring @ 2023-06-14 18:51 UTC (permalink / raw)
To: Jeff LaBundy
Cc: dmitry.torokhov, linux-input, devicetree, krzysztof.kozlowski+dt,
conor+dt
In-Reply-To: <ZIe/Ti7u+2VHlahA@nixie71>
On Mon, Jun 12, 2023 at 07:58:54PM -0500, Jeff LaBundy wrote:
> Hi Rob,
>
> On Mon, Jun 12, 2023 at 09:29:25AM -0600, Rob Herring wrote:
> > On Sun, Jun 11, 2023 at 08:06:24PM -0500, Jeff LaBundy wrote:
> > > Hi Rob,
> > >
> > > On Fri, Jun 09, 2023 at 08:25:38AM -0600, Rob Herring wrote:
> > > > On Mon, May 29, 2023 at 07:33:47PM -0500, Jeff LaBundy wrote:
> > > > > Add bindings for the Azoteq IQS7210A/7211A/E family of trackpad/
> > > > > touchscreen controllers.
> > > > >
> > > > > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > > > > ---
> > > > > Changes in v2:
> > > > > - Renamed 'azoteq,default-comms' to 'azoteq,forced-comms-default' and redefined
> > > > > 0, 1 and 2 as unspecified, 0 and 1, respectively
> > > > > - Defined ATI upon its first occurrence
> > > > > - Redefined 'azoteq,gesture-angle' in units of degrees
> > > > > - Declared 'azoteq,rx-enable' to depend upon 'azoteq,tx-enable' within the
> > > > > 'trackpad' node
> > > > >
> > > > > Hi Rob,
> > > > >
> > > > > I attempted to reference existing properties from a common binding [1] as per
> > > > > your feedback in [2], however 'make DT_CHECKER_FLAGS=-m dt_binding_check' fails
> > > > > with the message 'Vendor specific properties must have a type and description
> > > > > unless they have a defined, common suffix.'
> > > >
> > > > Is that because you have differing constraints in each case?
> > >
> > > In the failing example [2], I have started with a simple boolean that carries
> > > nothing but a type and description. From the new azoteq,common.yaml:
> > >
> > > properties:
> > > [...]
> > >
> > > azoteq,use-prox:
> > > type: boolean
> > > description: foo
> > >
> > > And from the first consumer:
> > >
> > > patternProperties:
> > > "^hall-switch-(north|south)$":
> > > type: object
> > > allOf:
> > > - $ref: input.yaml#
> > > - $ref: azoteq,common.yaml#
> > > description: bar
> > >
> > > properties:
> > > linux,code: true
> > > azoteq,use-prox: true
> > >
> > > However, the tooling presents the following:
> > >
> > > CHKDT Documentation/devicetree/bindings/processed-schema.json
> > > /home/jlabundy/work/linux/Documentation/devicetree/bindings/input/iqs62x-keys.yaml: patternProperties:^hall-switch-(north|south)$:properties:azoteq,use-prox: True is not of type 'object'
> > > hint: Vendor specific properties must have a type and description unless they have a defined, common suffix.
> > > from schema $id: http://devicetree.org/meta-schemas/vendor-props.yaml#
> > >
> > > [...]
> > >
> > > I am committed to addressing your feedback; to help me do so, can you help me
> > > identify what I've done wrong, and/or point me to an example that successfully
> > > passes dt_binding_check?
> >
> > You're not doing anything wrong. There's 2 options here. The first is we
> > could just relax the check to allow boolean schema for vendor
> > properties. The main issue with that is we then have to look for that
> > improperly used and it doesn't help if you do have additional
> > constraints to add on top of the common definition. The former can
> > mostly be addressed by checking there is a type associated with the
> > property. I'm going to look into adding that.
>
> Thank you for your feedback. I started with a boolean property at first to
> simply test the idea before moving too far forward. In reality however, the
> common binding has many uint32's and uint32-arrays as well, often with
> different constraints among consumers. For this option to be effective, it
> would need to be extended to all types IMO.
>
> >
> > Alternatively, you could drop listing the properties and
> > use 'unevaluatedProperties'. That's not quite equal to what you have.
> > Presumably, you have 'additionalProperties' in this case, so listing
> > them serves the purpose of defining what subset of properties each node
> > uses from the referenced schema. We frequently don't worry if there are
> > common properties not used by a specific schema. This also wouldn't work
> > if you have additional constraints to add.
>
> Because of varying constraints among each consumer, I do not believe this
> option is viable either.
>
> I also think adopting 'unevaluatedProperties' here would be confusing from
> a customer perspective in this case. The new common binding has dozens of
> properties for which some are shared between devices A and B but not C, or
> devices B and C but not A.
>
> Without each device's binding explicitly opting in for supported properties,
> it's difficult for customers to know what is supported for a given device.
> These particular devices are highly configurable yet void of nonvolatile
> memory, so there is simply no way around having so many properties. Most are
> touched in some way throughout various downstream applications.
>
> Therefore I'd like to propose option (3), which is to move forward with patch
> [1/2] as-is and decouple the merging of this driver from future enhancements
> to the tooling. While patch [1/2] is admittedly a big binding with some repeat
> descriptions, none of the duplicate properties introduce a conflicting type.
>
> If in the future option (1) can support all property types and handle varying
> constraints among consumers, I would be happy to be one of the first guinea
> pigs. Does this path seem like a reasonable compromise?
Yes, that's fine.
Rob
^ permalink raw reply
* Re: [PATCH 05/10] dt-bindings: power: reset: Add bindings for twl6030-power
From: Krzysztof Kozlowski @ 2023-06-14 13:30 UTC (permalink / raw)
To: Mithil, robh@kernel.org
Cc: contact@paulk.fr, devicetree@vger.kernel.org,
dmitry.torokhov@gmail.com, krzysztof.kozlowski+dt@linaro.org,
lee@kernel.org, linux-arm-kernel@lists.infradead.org,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-omap@vger.kernel.org, linux-pm@vger.kernel.org,
linux@armlinux.org.uk, sre@kernel.org, tony@atomide.com
In-Reply-To: <CAGzNGR=BkOMtw2PhudUs_b4ffk3B+x==9dtWuA-kcqnePaHVYA@mail.gmail.com>
On 14/06/2023 11:13, Mithil wrote:
> Subject: Re: [PATCH 05/10] dt-bindings: power: reset: Add bindings for
> twl6030-power
>
> On Tue, Aug 23, 2022 at 12:54 AM Rob Herring <robh@kernel.org> wrote:
>>
>> On Sat, Aug 20, 2022 at 12:46:55PM +0530, Mithil Bavishi wrote:
>>> Adds documentation for the twl6030 power driver.
>>>
>>> Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
>>> Signed-off-by: Mithil Bavishi <bavishimithil@gmail.com>
>>> ---
>>> .../bindings/power/reset/twl6030-power.txt | 31 +++++++++++++++++++
>>
>> New bindings must be DT schema format.
>>
>>> 1 file changed, 31 insertions(+)
>>> create mode 100644 Documentation/devicetree/bindings/power/reset/twl6030-power.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/power/reset/twl6030-power.txt b/Documentation/devicetree/bindings/power/reset/twl6030-power.txt
>>> new file mode 100644
>>> index 000000000..946bb3d9f
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/power/reset/twl6030-power.txt
>>> @@ -0,0 +1,31 @@
>>> +Texas Instruments TWL family (twl6030) reset and power management module
>>> +
>>> +For now, the binding only supports the complete shutdown of the system after
>>> +poweroff.
>>> +
>>> +Required properties:
>>> +- compatible : must be
>>> + "ti,twl6030-power"
>>> +
>>> +Optional properties:
>>> +
>>> +- ti,system-power-controller: This indicates that TWL6030 is the
>>
>> We have a generic property for this.
>>
>
> What is property is that? And how would it get implemented here?
Easy to guess...
git grep system-power-controller
>
>>> + power supply master of the system. With this flag, the chip will
>>> + initiate an ACTIVE-to-OFF or SLEEP-to-OFF transition when the
>>> + system poweroffs.
>>> +
>>> +Example:
>>> +&i2c1 {
>>> + clock-frequency = <2600000>;
>>> +
>>> + twl: twl@48 {
>>> + reg = <0x48>;
>>> + interrupts = <7>; /* SYS_NIRQ cascaded to intc */
>>> + interrupt-parent = <&intc>;
>>> +
>>> + twl_power: power {
>>> + compatible = "ti,twl6030-power";
>>> + ti,system-power-controller;
>>
>> Why do you need a child node here? There aren't any resources for the
>> sub-block.
>>
>
> Just an example and how it is used on a device as well, is it fine if
> just the block is as-is?
The question is not about example. Question was why do you need child
node at all. Children without resources are usually useless.
Best regards,
Krzysztof
^ permalink raw reply
* Re: Tree dumb questions from an occasional
From: Benjamin Tissoires @ 2023-06-14 12:11 UTC (permalink / raw)
To: Marco Morandini; +Cc: Jiri Kosina, linux-input
In-Reply-To: <c2c116cf-56e7-12e3-f0e7-f726a0f3f0da@polimi.it>
On Wed, Jun 14, 2023 at 12:18 PM Marco Morandini <marco.morandini@polimi.it> wrote:
>
> > Actually, the one place where it would make sense to have such dynamic
> > quirks is in the hid-core (hid.ko) module itself. It would make sense
> > to have a BUS:VID:PID:QUIRKS parameter.
> > But having such a parameter is not without constraints, because it's
> > not really "dynamic", and we can only set a limited number of quirks.
>
> Ok
>
> >
> > In your particular case, we might as well use an HID-BPF program that
> > tweaks the report descriptor which would force the kernel to "use" the
> > multi-input quirk.
>
> If this means that it could be a nice example (something you would put in
> samples/hid) for HID-BPF, this would be great
> (and I would be curious to understand how to do it).
> But don't waste time for me: the patch is already in your
> for-next and for-6.4/upstream-fixes branches, and for sure I can wait
> and deal with what I have right now.
The program is actually simple: knowing that the kernel splits by
application collection, we can replace the second collection from being
exported as a mouse into a pointer:
See the branch hp_elite_presenter of https://gitlab.freedesktop.org/bentiss/udev-hid-bpf/-/tree/hp_elite_presenter
The program just replaces the byte 79 from 0x02 (mouse) to 0x01
(presenter):
---
SEC("fmod_ret/hid_bpf_rdesc_fixup")
int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
if (!data)
return 0; /* EPERM check */
/* replace application mouse by application pointer on the second collection */
if (data[79] == 0x02)
data[79] = 0x01;
return 0;
}
---
>
> > Would you mind attaching the output of hid-recorder while you do some
> > HID events and where you show the bug?
>
> Attached; I've tried to use all the mouses/buttons. Do you need the same
> kind of recording taken with the patched kernel?
Nope, no need. hid-recorder is what comes from the device, so the kernel
processing depends on my current tree, which explains how I can test the
various quirks :)
>
> You'll notice that the HID descriptor advertises two mouses and
> two consumer controls, each with different Report IDs.
> This is because this device can be used in two different
> configurations: one is a traditional mouse, that you use on your desk.
> If you turn the device, then you access the second one,
> where you are dealing with a virtual pointer:
> two gyroscopes sense the change of attitude of the device,
> and you can control the cursor by waving around the pointer.
> The buttons that you use in the two different configurations
> are different as well.
>
> > Also, FWIW, the number of MULTI_INPUT quirk required in the kernel is
> > probably a sign that we are not using the best default implementation,
> > and I've already been pinged to change that. I couldn't find the time
> > to get back to this, but your device might also help me in having a
> > broader range of use cases so that we can ditch that quirk once and
> > for all.
>
> I was clumsy looking around trying to understand why it's better
> not to have it as a default, but for sure there are good reason
> for the actual behavior. Perhaps this has to do with the fact that
> you don't want to have duplicated OUTPUTs (if there are any)?
> e.g. https://lkml.iu.edu/hypermail/linux/kernel/0701.1/1132.html ?
>
IIRC it was mostly because some devices were having separate
declarations for their input/output and features, and they were not
especially grouped together. The multi_input quirk splits features/input
/output in different devices, making it harder to configure (in case of
the multitouch ones, where to need to set an operating mode), and the
default was just having one input node for the whole HID device.
Cheers,
Benjamin
^ permalink raw reply
* Re: [PATCH v5 1/2] dt-bindings: HID: i2c-hid: ilitek: Introduce bindings for Ilitek ili9882t
From: cong yang @ 2023-06-14 11:02 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, dmitry.torokhov, jikos,
benjamin.tissoires, dianders, hsinyi, linux-input, devicetree,
linux-kernel
In-Reply-To: <949a2d21-eb14-3ef8-a7be-9c12152cd15a@linaro.org>
Hi,Krzysztof
On Sat, Jun 10, 2023 at 12:01 AM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> On 09/06/2023 08:36, Cong Yang wrote:
> > The ili9882t touch screen chip same as Elan eKTH6915 controller
> > has a reset gpio. The difference is that ili9882t needs to use
> > vccio-supply instead of vcc33-supply. Doug's series[1] allows panels
> > and touchscreens to power on/off together, let's add a phandle for this.
> >
> > [1]: https://lore.kernel.org/r/20230607215224.2067679-1-dianders@chromium.org
> >
> > Signed-off-by: Cong Yang <yangcong5@huaqin.corp-partner.google.com>
>
>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>
> If there is going to be new version, then:
> A nit, subject: drop second/last, redundant "bindings for". The
> "dt-bindings" prefix is already stating that these are bindings.
As Doug said,makes sense to land if the panel follower patch series [1] lands.
If Doug's series[1] land, i will update this and commit message link in V6.
Thank you.
>
>
> ---
>
> This is an automated instruction, just in case, because many review tags
> are being ignored. If you do not know the process, here is a short
> explanation:
>
> Please add Acked-by/Reviewed-by/Tested-by tags when posting new
> versions, under or above your Signed-off-by tag. Tools like b4 can help
> here. However, there's no need to repost patches *only* to add the tags.
> The upstream maintainer will do that for acks received on the version
> they apply.
>
> https://elixir.bootlin.com/linux/v5.17/source/Documentation/process/submitting-patches.rst#L540
>
> Best regards,
> Krzysztof
>
^ permalink raw reply
* Re: [PATCH] Input: pwm-beeper - Support volume setting via sysfs
From: Marek Vasut @ 2023-06-14 9:30 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: linux-input, Dmitry Torokhov, Frieder Schrempf, Manuel Traut,
Thierry Reding, linux-pwm
In-Reply-To: <20230614064510.nm3hhokjxe37hrjo@pengutronix.de>
On 6/14/23 08:45, Uwe Kleine-König wrote:
> On Fri, May 12, 2023 at 08:55:51PM +0200, Marek Vasut wrote:
>> The PWM beeper volume can be controlled by adjusting the PWM duty cycle,
>> expose volume setting via sysfs, so users can make the beeper quieter.
>> This patch adds sysfs attribute 'volume' in range 0..50000, i.e. from 0
>> to 50% in 1/1000th of percent steps, this resolution should be sufficient.
>>
>> The reason for 50000 cap on volume or PWM duty cycle is because duty cycle
>> above 50% again reduces the loudness, the PWM wave form is inverted wave
>> form of the one for duty cycle below 50% and the beeper gets quieter the
>> closer the setting is to 100% . Hence, 50% cap where the wave form yields
>> the loudest result.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> ---
>> An alternative option would be to extend the userspace input ABI, e.g. by
>> using SND_TONE top 16bits to encode the duty cycle in 0..50000 range, and
>> bottom 16bit to encode the existing frequency in Hz . Since frequency in
>> Hz is likely to be below some 25 kHz for audible bell, this fits in 16bits
>> just fine. Thoughts ?
>> ---
>> NOTE: This uses approach similar to [1], except it is much simpler.
>> [1] https://patchwork.kernel.org/project/linux-input/cover/20230201152128.614439-1-manuel.traut@mt.com/
>> ---
>> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
>> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>> Cc: Frieder Schrempf <frieder.schrempf@kontron.de>
>> Cc: Manuel Traut <manuel.traut@mt.com>
>> Cc: Marek Vasut <marex@denx.de>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: linux-input@vger.kernel.org
>> Cc: linux-pwm@vger.kernel.org
>> ---
>> drivers/input/misc/pwm-beeper.c | 58 ++++++++++++++++++++++++++++++++-
>> 1 file changed, 57 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
>> index 3cf1812384e6a..f63d0ebbaf573 100644
>> --- a/drivers/input/misc/pwm-beeper.c
>> +++ b/drivers/input/misc/pwm-beeper.c
>> @@ -21,6 +21,7 @@ struct pwm_beeper {
>> struct regulator *amplifier;
>> struct work_struct work;
>> unsigned long period;
>> + unsigned long duty_cycle;
>> unsigned int bell_frequency;
>> bool suspended;
>> bool amplifier_on;
>> @@ -37,7 +38,7 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
>>
>> state.enabled = true;
>> state.period = period;
>> - pwm_set_relative_duty_cycle(&state, 50, 100);
>> + pwm_set_relative_duty_cycle(&state, beeper->duty_cycle, 100000);
>>
>> error = pwm_apply_state(beeper->pwm, &state);
>> if (error)
>> @@ -119,6 +120,53 @@ static void pwm_beeper_close(struct input_dev *input)
>> pwm_beeper_stop(beeper);
>> }
>>
>> +static ssize_t volume_show(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct pwm_beeper *beeper = dev_get_drvdata(dev);
>> +
>> + return sysfs_emit(buf, "%ld\n", beeper->duty_cycle);
>> +}
>> +
>> +static ssize_t volume_store(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct pwm_beeper *beeper = dev_get_drvdata(dev);
>> + unsigned long val;
>> +
>> + if (kstrtoul(buf, 0, &val) < 0)
>> + return -EINVAL;
>> +
>> + /*
>> + * Volume is really PWM duty cycle in pcm (per cent mille, 1/1000th
>> + * of percent). This value therefore ranges from 0 to 50000 . Duty
>> + * cycle of 50% = 50000pcm is the maximum volume .
>> + */
>> + val = clamp(val, 0UL, 50000UL);
>
> I wonder if you want to refuse values here that are not in the specified
> range, that is, something like:
>
> if (val != clamp(val, 0UL, 50000UL))
> return -EINVAL;
>
> I think this is more in line who other sysfs properties work?!
I am still waiting for the more general API design decision here from
input maintainer, i.e. what was designed with Jeff above.
Yes, we can clamp the value, but I won't work on this unless there is
clear answer how to go on with the API first.
^ permalink raw reply
* Re: [PATCH v4 2/4] ARM/mmc: Convert old mmci-omap to GPIO descriptors
From: Linus Walleij @ 2023-06-14 9:24 UTC (permalink / raw)
To: Peter Vasil
Cc: Aaro Koskinen, Janusz Krzysztofik, Tony Lindgren, Russell King,
Daniel Mack, Haojian Zhuang, Robert Jarzmik, Thomas Bogendoerfer,
Dmitry Torokhov, Mark Brown, Bartosz Golaszewski, Andreas Kemnade,
Helge Deller, Ulf Hansson, linux-omap, linux-arm-kernel,
linux-kernel, linux-mips, linux-input, linux-spi, linux-fbdev,
dri-devel, linux-mmc
In-Reply-To: <CAFwpezXJkXRr0Es=owr6fJ8BB_DETYPWdj_EzLbw9+5d7YOxxQ@mail.gmail.com>
On Wed, Jun 14, 2023 at 10:44 AM Peter Vasil <petervasil@gmail.com> wrote:
> On Mon, May 8, 2023 at 11:21 PM Linus Walleij <linus.walleij@linaro.org> wrote:
> > +static struct gpiod_lookup_table nokia810_mmc_gpio_table = {
> > + .dev_id = "mmci-omap",
> > + .table = {
> > + /* Slot index 1, VSD power, GPIO 23 */
> > + GPIO_LOOKUP_IDX("gpio-16-31", 7,
> > + "vsd", 1, GPIO_ACTIVE_HIGH),
>
> Hello everyone,
> not sure if anyone noticed this already, or if I understand it
> wrong... shouldn't the "vsd" name in following lookup descriptor
> actually be "vio"?
>
> > + /* Slot index 1, VIO power, GPIO 9 */
> > + GPIO_LOOKUP_IDX("gpio-0-15", 9,
> > + "vsd", 1, GPIO_ACTIVE_HIGH),
Ooops. Copy/paste bug.
I'll send a fix.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 05/10] dt-bindings: power: reset: Add bindings for twl6030-power
From: Mithil @ 2023-06-14 9:13 UTC (permalink / raw)
To: robh@kernel.org
Cc: bavishimithil@gmail.com, contact@paulk.fr,
devicetree@vger.kernel.org, dmitry.torokhov@gmail.com,
krzysztof.kozlowski+dt@linaro.org, lee@kernel.org,
linux-arm-kernel@lists.infradead.org, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org,
linux-pm@vger.kernel.org, linux@armlinux.org.uk, sre@kernel.org,
tony@atomide.com
Subject: Re: [PATCH 05/10] dt-bindings: power: reset: Add bindings for
twl6030-power
On Tue, Aug 23, 2022 at 12:54 AM Rob Herring <robh@kernel.org> wrote:
>
> On Sat, Aug 20, 2022 at 12:46:55PM +0530, Mithil Bavishi wrote:
> > Adds documentation for the twl6030 power driver.
> >
> > Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
> > Signed-off-by: Mithil Bavishi <bavishimithil@gmail.com>
> > ---
> > .../bindings/power/reset/twl6030-power.txt | 31 +++++++++++++++++++
>
> New bindings must be DT schema format.
>
> > 1 file changed, 31 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/power/reset/twl6030-power.txt
> >
> > diff --git a/Documentation/devicetree/bindings/power/reset/twl6030-power.txt b/Documentation/devicetree/bindings/power/reset/twl6030-power.txt
> > new file mode 100644
> > index 000000000..946bb3d9f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/power/reset/twl6030-power.txt
> > @@ -0,0 +1,31 @@
> > +Texas Instruments TWL family (twl6030) reset and power management module
> > +
> > +For now, the binding only supports the complete shutdown of the system after
> > +poweroff.
> > +
> > +Required properties:
> > +- compatible : must be
> > + "ti,twl6030-power"
> > +
> > +Optional properties:
> > +
> > +- ti,system-power-controller: This indicates that TWL6030 is the
>
> We have a generic property for this.
>
What is property is that? And how would it get implemented here?
> > + power supply master of the system. With this flag, the chip will
> > + initiate an ACTIVE-to-OFF or SLEEP-to-OFF transition when the
> > + system poweroffs.
> > +
> > +Example:
> > +&i2c1 {
> > + clock-frequency = <2600000>;
> > +
> > + twl: twl@48 {
> > + reg = <0x48>;
> > + interrupts = <7>; /* SYS_NIRQ cascaded to intc */
> > + interrupt-parent = <&intc>;
> > +
> > + twl_power: power {
> > + compatible = "ti,twl6030-power";
> > + ti,system-power-controller;
>
> Why do you need a child node here? There aren't any resources for the
> sub-block.
>
Just an example and how it is used on a device as well, is it fine if
just the block is as-is?
Mithil
^ permalink raw reply
* Re: [PATCH v4 2/4] ARM/mmc: Convert old mmci-omap to GPIO descriptors
From: Peter Vasil @ 2023-06-14 8:44 UTC (permalink / raw)
To: Linus Walleij
Cc: Aaro Koskinen, Janusz Krzysztofik, Tony Lindgren, Russell King,
Daniel Mack, Haojian Zhuang, Robert Jarzmik, Thomas Bogendoerfer,
Dmitry Torokhov, Mark Brown, Bartosz Golaszewski, Andreas Kemnade,
Helge Deller, Ulf Hansson, linux-omap, linux-arm-kernel,
linux-kernel, linux-mips, linux-input, linux-spi, linux-fbdev,
dri-devel, linux-mmc
In-Reply-To: <20230430-nokia770-regression-v4-2-9b6dc5536b17@linaro.org>
On Mon, May 8, 2023 at 11:21 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> A recent change to the OMAP driver making it use a dynamic GPIO
> base created problems with some old OMAP1 board files, among
> them Nokia 770, SX1 and also the OMAP2 Nokia n8x0.
>
> Fix up all instances of GPIOs being used for the MMC driver
> by pushing the handling of power, slot selection and MMC
> "cover" into the driver as optional GPIOs.
>
> This is maybe not the most perfect solution as the MMC
> framework have some central handlers for some of the
> stuff, but it at least makes the situtation better and
> solves the immediate issue.
>
> Fixes: 92bf78b33b0b ("gpio: omap: use dynamic allocation of base")
> Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> arch/arm/mach-omap1/board-nokia770.c | 43 ++++++-----------
> arch/arm/mach-omap1/board-sx1-mmc.c | 1 -
> arch/arm/mach-omap2/board-n8x0.c | 85 +++++++++++-----------------------
> drivers/mmc/host/omap.c | 46 +++++++++++++++++-
> include/linux/platform_data/mmc-omap.h | 2 -
> 5 files changed, 83 insertions(+), 94 deletions(-)
>
> diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
> index 8a1f2572deea..218c928f71b3 100644
> --- a/arch/arm/mach-omap1/board-nokia770.c
> +++ b/arch/arm/mach-omap1/board-nokia770.c
> @@ -183,27 +183,23 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
>
> #if IS_ENABLED(CONFIG_MMC_OMAP)
>
> -#define NOKIA770_GPIO_MMC_POWER 41
> -#define NOKIA770_GPIO_MMC_SWITCH 23
> -
> -static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
> - int vdd)
> -{
> - gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on);
> - return 0;
> -}
> -
> -static int nokia770_mmc_get_cover_state(struct device *dev, int slot)
> -{
> - return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH);
> -}
> +static struct gpiod_lookup_table nokia770_mmc_gpio_table = {
> + .dev_id = "mmci-omap",
> + .table = {
> + /* Slot index 0, VSD power, GPIO 41 */
> + GPIO_LOOKUP_IDX("gpio-32-47", 9,
> + "vsd", 0, GPIO_ACTIVE_HIGH),
> + /* Slot index 0, switch, GPIO 23 */
> + GPIO_LOOKUP_IDX("gpio-16-31", 7,
> + "cover", 0, GPIO_ACTIVE_HIGH),
> + { }
> + },
> +};
>
> static struct omap_mmc_platform_data nokia770_mmc2_data = {
> .nr_slots = 1,
> .max_freq = 12000000,
> .slots[0] = {
> - .set_power = nokia770_mmc_set_power,
> - .get_cover_state = nokia770_mmc_get_cover_state,
> .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
> .name = "mmcblk",
> },
> @@ -213,20 +209,7 @@ static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC];
>
> static void __init nokia770_mmc_init(void)
> {
> - int ret;
> -
> - ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power");
> - if (ret < 0)
> - return;
> - gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0);
> -
> - ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover");
> - if (ret < 0) {
> - gpio_free(NOKIA770_GPIO_MMC_POWER);
> - return;
> - }
> - gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH);
> -
> + gpiod_add_lookup_table(&nokia770_mmc_gpio_table);
> /* Only the second MMC controller is used */
> nokia770_mmc_data[1] = &nokia770_mmc2_data;
> omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC);
> diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
> index f1c160924dfe..f183a8448a7b 100644
> --- a/arch/arm/mach-omap1/board-sx1-mmc.c
> +++ b/arch/arm/mach-omap1/board-sx1-mmc.c
> @@ -9,7 +9,6 @@
> * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
> */
>
> -#include <linux/gpio.h>
> #include <linux/platform_device.h>
>
> #include "hardware.h"
> diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
> index 3353b0a923d9..baa2f0341aed 100644
> --- a/arch/arm/mach-omap2/board-n8x0.c
> +++ b/arch/arm/mach-omap2/board-n8x0.c
> @@ -11,6 +11,7 @@
> #include <linux/clk.h>
> #include <linux/delay.h>
> #include <linux/gpio.h>
> +#include <linux/gpio/machine.h>
> #include <linux/init.h>
> #include <linux/io.h>
> #include <linux/irq.h>
> @@ -170,22 +171,32 @@ static struct spi_board_info n800_spi_board_info[] __initdata = {
> * GPIO23 and GPIO9 slot 2 EMMC on N810
> *
> */
> -#define N8X0_SLOT_SWITCH_GPIO 96
> -#define N810_EMMC_VSD_GPIO 23
> -#define N810_EMMC_VIO_GPIO 9
> -
> static int slot1_cover_open;
> static int slot2_cover_open;
> static struct device *mmc_device;
>
> -static int n8x0_mmc_switch_slot(struct device *dev, int slot)
> -{
> -#ifdef CONFIG_MMC_DEBUG
> - dev_dbg(dev, "Choose slot %d\n", slot + 1);
> -#endif
> - gpio_set_value(N8X0_SLOT_SWITCH_GPIO, slot);
> - return 0;
> -}
> +static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
> + .dev_id = "mmci-omap",
> + .table = {
> + /* Slot switch, GPIO 96 */
> + GPIO_LOOKUP("gpio-80-111", 16,
> + "switch", GPIO_ACTIVE_HIGH),
> + { }
> + },
> +};
> +
> +static struct gpiod_lookup_table nokia810_mmc_gpio_table = {
> + .dev_id = "mmci-omap",
> + .table = {
> + /* Slot index 1, VSD power, GPIO 23 */
> + GPIO_LOOKUP_IDX("gpio-16-31", 7,
> + "vsd", 1, GPIO_ACTIVE_HIGH),
Hello everyone,
not sure if anyone noticed this already, or if I understand it
wrong... shouldn't the "vsd" name in following lookup descriptor
actually be "vio"?
> + /* Slot index 1, VIO power, GPIO 9 */
> + GPIO_LOOKUP_IDX("gpio-0-15", 9,
> + "vsd", 1, GPIO_ACTIVE_HIGH),
At least the driver code further down seems to use that name while
n8x0 board file does not define it anywhere.
I've noticed it in the pull request already, so it looks like it has
not been fixed yet (if it's actually wrong?).
Regards,
Peter
> + { }
> + },
> +};
>
> static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot,
> int power_on, int vdd)
> @@ -256,31 +267,13 @@ static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot,
> return 0;
> }
>
> -static void n810_set_power_emmc(struct device *dev,
> - int power_on)
> -{
> - dev_dbg(dev, "Set EMMC power %s\n", power_on ? "on" : "off");
> -
> - if (power_on) {
> - gpio_set_value(N810_EMMC_VSD_GPIO, 1);
> - msleep(1);
> - gpio_set_value(N810_EMMC_VIO_GPIO, 1);
> - msleep(1);
> - } else {
> - gpio_set_value(N810_EMMC_VIO_GPIO, 0);
> - msleep(50);
> - gpio_set_value(N810_EMMC_VSD_GPIO, 0);
> - msleep(50);
> - }
> -}
> -
> static int n8x0_mmc_set_power(struct device *dev, int slot, int power_on,
> int vdd)
> {
> if (board_is_n800() || slot == 0)
> return n8x0_mmc_set_power_menelaus(dev, slot, power_on, vdd);
>
> - n810_set_power_emmc(dev, power_on);
> + /* The n810 power will be handled by GPIO code in the driver */
>
> return 0;
> }
> @@ -418,13 +411,6 @@ static void n8x0_mmc_shutdown(struct device *dev)
> static void n8x0_mmc_cleanup(struct device *dev)
> {
> menelaus_unregister_mmc_callback();
> -
> - gpio_free(N8X0_SLOT_SWITCH_GPIO);
> -
> - if (board_is_n810()) {
> - gpio_free(N810_EMMC_VSD_GPIO);
> - gpio_free(N810_EMMC_VIO_GPIO);
> - }
> }
>
> /*
> @@ -433,7 +419,6 @@ static void n8x0_mmc_cleanup(struct device *dev)
> */
> static struct omap_mmc_platform_data mmc1_data = {
> .nr_slots = 0,
> - .switch_slot = n8x0_mmc_switch_slot,
> .init = n8x0_mmc_late_init,
> .cleanup = n8x0_mmc_cleanup,
> .shutdown = n8x0_mmc_shutdown,
> @@ -463,14 +448,9 @@ static struct omap_mmc_platform_data mmc1_data = {
>
> static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
>
> -static struct gpio n810_emmc_gpios[] __initdata = {
> - { N810_EMMC_VSD_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vddf" },
> - { N810_EMMC_VIO_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vdd" },
> -};
> -
> static void __init n8x0_mmc_init(void)
> {
> - int err;
> + gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table);
>
> if (board_is_n810()) {
> mmc1_data.slots[0].name = "external";
> @@ -483,20 +463,7 @@ static void __init n8x0_mmc_init(void)
> */
> mmc1_data.slots[1].name = "internal";
> mmc1_data.slots[1].ban_openended = 1;
> - }
> -
> - err = gpio_request_one(N8X0_SLOT_SWITCH_GPIO, GPIOF_OUT_INIT_LOW,
> - "MMC slot switch");
> - if (err)
> - return;
> -
> - if (board_is_n810()) {
> - err = gpio_request_array(n810_emmc_gpios,
> - ARRAY_SIZE(n810_emmc_gpios));
> - if (err) {
> - gpio_free(N8X0_SLOT_SWITCH_GPIO);
> - return;
> - }
> + gpiod_add_lookup_table(&nokia810_mmc_gpio_table);
> }
>
> mmc1_data.nr_slots = 2;
> diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
> index ce78edfb402b..a14af21f12da 100644
> --- a/drivers/mmc/host/omap.c
> +++ b/drivers/mmc/host/omap.c
> @@ -26,6 +26,7 @@
> #include <linux/clk.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/platform_data/mmc-omap.h>
>
>
> @@ -111,6 +112,9 @@ struct mmc_omap_slot {
> struct mmc_request *mrq;
> struct mmc_omap_host *host;
> struct mmc_host *mmc;
> + struct gpio_desc *vsd;
> + struct gpio_desc *vio;
> + struct gpio_desc *cover;
> struct omap_mmc_slot_data *pdata;
> };
>
> @@ -133,6 +137,7 @@ struct mmc_omap_host {
> int irq;
> unsigned char bus_mode;
> unsigned int reg_shift;
> + struct gpio_desc *slot_switch;
>
> struct work_struct cmd_abort_work;
> unsigned abort:1;
> @@ -216,8 +221,13 @@ static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)
>
> if (host->current_slot != slot) {
> OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00);
> - if (host->pdata->switch_slot != NULL)
> - host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id);
> + if (host->slot_switch)
> + /*
> + * With two slots and a simple GPIO switch, setting
> + * the GPIO to 0 selects slot ID 0, setting it to 1
> + * selects slot ID 1.
> + */
> + gpiod_set_value(host->slot_switch, slot->id);
> host->current_slot = slot;
> }
>
> @@ -297,6 +307,9 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
> static inline
> int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
> {
> + /* If we have a GPIO then use that */
> + if (slot->cover)
> + return gpiod_get_value(slot->cover);
> if (slot->pdata->get_cover_state)
> return slot->pdata->get_cover_state(mmc_dev(slot->mmc),
> slot->id);
> @@ -1106,6 +1119,11 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
>
> host = slot->host;
>
> + if (slot->vsd)
> + gpiod_set_value(slot->vsd, power_on);
> + if (slot->vio)
> + gpiod_set_value(slot->vio, power_on);
> +
> if (slot->pdata->set_power != NULL)
> slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
> vdd);
> @@ -1240,6 +1258,23 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
> slot->power_mode = MMC_POWER_UNDEFINED;
> slot->pdata = &host->pdata->slots[id];
>
> + /* Check for some optional GPIO controls */
> + slot->vsd = gpiod_get_index_optional(host->dev, "vsd",
> + id, GPIOD_OUT_LOW);
> + if (IS_ERR(slot->vsd))
> + return dev_err_probe(host->dev, PTR_ERR(slot->vsd),
> + "error looking up VSD GPIO\n");
> + slot->vio = gpiod_get_index_optional(host->dev, "vio",
> + id, GPIOD_OUT_LOW);
> + if (IS_ERR(slot->vio))
> + return dev_err_probe(host->dev, PTR_ERR(slot->vio),
> + "error looking up VIO GPIO\n");
> + slot->cover = gpiod_get_index_optional(host->dev, "cover",
> + id, GPIOD_IN);
> + if (IS_ERR(slot->cover))
> + return dev_err_probe(host->dev, PTR_ERR(slot->cover),
> + "error looking up cover switch GPIO\n");
> +
> host->slots[id] = slot;
>
> mmc->caps = 0;
> @@ -1349,6 +1384,13 @@ static int mmc_omap_probe(struct platform_device *pdev)
> if (IS_ERR(host->virt_base))
> return PTR_ERR(host->virt_base);
>
> + host->slot_switch = gpiod_get_optional(host->dev, "switch",
> + GPIOD_OUT_LOW);
> + if (IS_ERR(host->slot_switch))
> + return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
> + "error looking up slot switch GPIO\n");
> +
> +
> INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
> INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
>
> diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
> index 91051e9907f3..054d0c3c5ec5 100644
> --- a/include/linux/platform_data/mmc-omap.h
> +++ b/include/linux/platform_data/mmc-omap.h
> @@ -20,8 +20,6 @@ struct omap_mmc_platform_data {
> * maximum frequency on the MMC bus */
> unsigned int max_freq;
>
> - /* switch the bus to a new slot */
> - int (*switch_slot)(struct device *dev, int slot);
> /* initialize board-specific MMC functionality, can be NULL if
> * not supported */
> int (*init)(struct device *dev);
>
> --
> 2.34.1
>
^ permalink raw reply
* Fotowoltaika- propozycja instalacji
From: Norbert Karecki @ 2023-06-14 8:10 UTC (permalink / raw)
To: linux-input
Dzień dobry,
Czy rozważali Państwo montaż systemu fotowoltaicznego?
Instalacja fotowoltaiczna jest najlepszym sposobem na obniżenie wysokości rachunków za prąd (pozostają tylko opłaty stałe) i zabezpieczenie się przed rosnącymi cenami energii elektrycznej. Jest to w pełni odnawialne i bezemisyjne źródło energii, dzięki czemu przyczyniamy się do ochrony środowiska naturalnego.
Działamy od wielu lat na rynku energetycznym. Przygotujemy projekt, wycenę oraz kompleksowo wykonamy i zgłosimy realizację do zakładu energetycznego.
Czy chcą Państwo poznać naszą propozycję?
Pozdrawiam,
Norbert Karecki
^ permalink raw reply
* Re: [PATCH v2 6/7] docs: update some straggling Documentation/arm references
From: Uwe Kleine-König @ 2023-06-14 7:04 UTC (permalink / raw)
To: Jonathan Corbet
Cc: linux-doc, linux-arch, linux-arm-kernel, Dmitry Torokhov,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Thierry Reding,
Greg Kroah-Hartman, linux-input, linux-sunxi, linux-pwm,
linux-serial
In-Reply-To: <20230529144856.102755-7-corbet@lwn.net>
[-- Attachment #1: Type: text/plain, Size: 1024 bytes --]
Hello,
On Mon, May 29, 2023 at 08:48:55AM -0600, Jonathan Corbet wrote:
> The Arm documentation has moved to Documentation/arch/arm; update the
> last remaining references to match.
>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
> Cc: Samuel Holland <samuel@sholland.org>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-input@vger.kernel.org
> Cc: linux-sunxi@lists.linux.dev
> Cc: linux-pwm@vger.kernel.org
> Cc: linux-serial@vger.kernel.org
> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
If you respin this series, you can add my:
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> # for pwm
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | https://www.pengutronix.de/ |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] Input: pwm-beeper - Support volume setting via sysfs
From: Uwe Kleine-König @ 2023-06-14 6:45 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-input, Dmitry Torokhov, Frieder Schrempf, Manuel Traut,
Thierry Reding, linux-pwm
In-Reply-To: <20230512185551.183049-1-marex@denx.de>
[-- Attachment #1: Type: text/plain, Size: 3909 bytes --]
On Fri, May 12, 2023 at 08:55:51PM +0200, Marek Vasut wrote:
> The PWM beeper volume can be controlled by adjusting the PWM duty cycle,
> expose volume setting via sysfs, so users can make the beeper quieter.
> This patch adds sysfs attribute 'volume' in range 0..50000, i.e. from 0
> to 50% in 1/1000th of percent steps, this resolution should be sufficient.
>
> The reason for 50000 cap on volume or PWM duty cycle is because duty cycle
> above 50% again reduces the loudness, the PWM wave form is inverted wave
> form of the one for duty cycle below 50% and the beeper gets quieter the
> closer the setting is to 100% . Hence, 50% cap where the wave form yields
> the loudest result.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
> An alternative option would be to extend the userspace input ABI, e.g. by
> using SND_TONE top 16bits to encode the duty cycle in 0..50000 range, and
> bottom 16bit to encode the existing frequency in Hz . Since frequency in
> Hz is likely to be below some 25 kHz for audible bell, this fits in 16bits
> just fine. Thoughts ?
> ---
> NOTE: This uses approach similar to [1], except it is much simpler.
> [1] https://patchwork.kernel.org/project/linux-input/cover/20230201152128.614439-1-manuel.traut@mt.com/
> ---
> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Frieder Schrempf <frieder.schrempf@kontron.de>
> Cc: Manuel Traut <manuel.traut@mt.com>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: linux-input@vger.kernel.org
> Cc: linux-pwm@vger.kernel.org
> ---
> drivers/input/misc/pwm-beeper.c | 58 ++++++++++++++++++++++++++++++++-
> 1 file changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
> index 3cf1812384e6a..f63d0ebbaf573 100644
> --- a/drivers/input/misc/pwm-beeper.c
> +++ b/drivers/input/misc/pwm-beeper.c
> @@ -21,6 +21,7 @@ struct pwm_beeper {
> struct regulator *amplifier;
> struct work_struct work;
> unsigned long period;
> + unsigned long duty_cycle;
> unsigned int bell_frequency;
> bool suspended;
> bool amplifier_on;
> @@ -37,7 +38,7 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
>
> state.enabled = true;
> state.period = period;
> - pwm_set_relative_duty_cycle(&state, 50, 100);
> + pwm_set_relative_duty_cycle(&state, beeper->duty_cycle, 100000);
>
> error = pwm_apply_state(beeper->pwm, &state);
> if (error)
> @@ -119,6 +120,53 @@ static void pwm_beeper_close(struct input_dev *input)
> pwm_beeper_stop(beeper);
> }
>
> +static ssize_t volume_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct pwm_beeper *beeper = dev_get_drvdata(dev);
> +
> + return sysfs_emit(buf, "%ld\n", beeper->duty_cycle);
> +}
> +
> +static ssize_t volume_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct pwm_beeper *beeper = dev_get_drvdata(dev);
> + unsigned long val;
> +
> + if (kstrtoul(buf, 0, &val) < 0)
> + return -EINVAL;
> +
> + /*
> + * Volume is really PWM duty cycle in pcm (per cent mille, 1/1000th
> + * of percent). This value therefore ranges from 0 to 50000 . Duty
> + * cycle of 50% = 50000pcm is the maximum volume .
> + */
> + val = clamp(val, 0UL, 50000UL);
I wonder if you want to refuse values here that are not in the specified
range, that is, something like:
if (val != clamp(val, 0UL, 50000UL))
return -EINVAL;
I think this is more in line who other sysfs properties work?!
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | https://www.pengutronix.de/ |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox