* [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
[not found] <20231227053509.894642-1-allencl_lin@hotmail.com>
@ 2023-12-27 5:35 ` Allen_Lin
2023-12-28 8:30 ` kernel test robot
2023-12-28 10:36 ` Krzysztof Kozlowski
2023-12-27 5:35 ` [PATCH v3 2/2] Input: Add Himax HX83102J touchscreen driver Allen_Lin
1 sibling, 2 replies; 8+ messages in thread
From: Allen_Lin @ 2023-12-27 5:35 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt, jikos,
benjamin.tissoires, linux-input, devicetree, linux-kernel
Cc: Allen_Lin
Add the HX83102j touchscreen device tree bindings documents.
Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
---
.../bindings/input/himax,hx83102j.yaml | 65 +++++++++++++++++++
MAINTAINERS | 6 ++
2 files changed, 71 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/himax,hx83102j.yaml
diff --git a/Documentation/devicetree/bindings/input/himax,hx83102j.yaml b/Documentation/devicetree/bindings/input/himax,hx83102j.yaml
new file mode 100644
index 000000000000..872b478c5753
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/himax,hx83102j.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/himax,hx83102j.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Himax hx83102j touchscreen
+
+maintainers:
+ - Allen Lin <allencl_lin@hotmail.com>
+
+description:
+ This Himax hx83102j touchscreen uses the spi-hid protocol.
+
+allOf:
+ - $ref: /schemas/input/touchscreen/touchscreen.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - himax,hx83102j
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ spi-cpha: true
+
+ spi-cpol: true
+
+ spi-max-frequency: true
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ hid-himax-spi@0 {
+ compatible = "himax,hx83102j";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_int0 &touch_reset>;
+ reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+ spi-cpha;
+ spi-cpol;
+ interrupt-parent = <&gpio1>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 012df8ccf34e..6a92e40d126d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9502,6 +9502,12 @@ L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/misc/hisi_hikey_usb.c
+HIMAX HID HX83102J TOUCHSCREEN
+M: Allen Lin <allencl_lin@hotmail.com>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/himax,hx83102j.yaml
+
HIMAX HX83112B TOUCHSCREEN SUPPORT
M: Job Noorman <job@noorman.info>
L: linux-input@vger.kernel.org
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/2] Input: Add Himax HX83102J touchscreen driver
[not found] <20231227053509.894642-1-allencl_lin@hotmail.com>
2023-12-27 5:35 ` [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen Allen_Lin
@ 2023-12-27 5:35 ` Allen_Lin
1 sibling, 0 replies; 8+ messages in thread
From: Allen_Lin @ 2023-12-27 5:35 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt, jikos,
benjamin.tissoires, linux-input, devicetree, linux-kernel
Cc: Allen_Lin
Add a new driver for Himax touchscreen series touchscreen controllers.
This driver supports Himax IC using the SPI interface to
acquire HID packets.
Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
---
MAINTAINERS | 1 +
drivers/hid/Kconfig | 8 +
drivers/hid/Makefile | 2 +
drivers/hid/hid-himax-83102j.c | 1096 ++++++++++++++++++++++++++++++++
drivers/hid/hid-himax-83102j.h | 202 ++++++
5 files changed, 1309 insertions(+)
create mode 100644 drivers/hid/hid-himax-83102j.c
create mode 100644 drivers/hid/hid-himax-83102j.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6a92e40d126d..e9553edf0bf0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9507,6 +9507,7 @@ M: Allen Lin <allencl_lin@hotmail.com>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/himax,hx83102j.yaml
+F: drivers/hid/hid-himax-83102j.*
HIMAX HX83112B TOUCHSCREEN SUPPORT
M: Job Noorman <job@noorman.info>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 4ce74af79657..e9bb95c288ec 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1325,6 +1325,14 @@ config HID_KUNIT_TEST
If in doubt, say "N".
+config HID_HIMAX_HX83102J
+ tristate "Himax hx83102j touchpanel CHIPSET"
+ depends on HID
+ help
+ Say Y here if you have a Himax CHIPSET touchscreen.
+ HIMAX controllers are multi touch controllers which can
+ report 10 touches at a time.
+ If unsure, say N.
endmenu
source "drivers/hid/bpf/Kconfig"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 8a06d0f840bc..3474a9d8c43d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -169,3 +169,5 @@ obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/
obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/
obj-$(CONFIG_SURFACE_HID_CORE) += surface-hid/
+
+obj-$(CONFIG_HID_HIMAX_HX83102J) += hid-himax-83102j.o
diff --git a/drivers/hid/hid-himax-83102j.c b/drivers/hid/hid-himax-83102j.c
new file mode 100644
index 000000000000..414c5fb99885
--- /dev/null
+++ b/drivers/hid/hid-himax-83102j.c
@@ -0,0 +1,1096 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Himax hx83102j Driver Code for Common IC to simulate HID
+ *
+ * Copyright (C) 2023 Himax Corporation.
+ */
+
+#include "hid-himax-83102j.h"
+
+static void hx83102j_pin_reset(struct himax_ts_data *ts);
+static void himax_ts_work(struct himax_ts_data *ts);
+static int himax_resume(struct device *dev);
+static int himax_suspend(struct device *dev);
+static int himax_chip_init(struct himax_ts_data *ts);
+static bool hx83102j_sense_off(struct himax_ts_data *ts, bool check_en);
+
+static int himax_spi_read(struct himax_ts_data *ts, u8 *cmd,
+ u8 cmd_len, u8 *buf, u32 len)
+{
+ struct spi_message m;
+ int result = 0;
+ int retry;
+ int error;
+ struct spi_transfer t = {
+ .len = cmd_len + len,
+ };
+
+ t.tx_buf = ts->xfer_data;
+ t.rx_buf = ts->xfer_data;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ for (retry = 0; retry < HIMAX_BUS_RETRY_TIMES; retry++) {
+ error = spi_sync(ts->spi, &m);
+ if (!unlikely(error))
+ break;
+ }
+
+ if (retry == HIMAX_BUS_RETRY_TIMES) {
+ dev_err(ts->dev, "SPI read error retry over %d", HIMAX_BUS_RETRY_TIMES);
+ result = -EIO;
+ goto err_retry_over;
+ } else {
+ memcpy(buf, ts->xfer_data + cmd_len, len);
+ }
+
+err_retry_over:
+ return result;
+}
+
+static int himax_spi_write(struct himax_ts_data *ts, u8 *buf,
+ u32 length)
+{
+ int status;
+ struct spi_message m;
+ struct spi_transfer t = {
+ .tx_buf = buf,
+ .len = length,
+ };
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ status = spi_sync(ts->spi, &m);
+
+ if (status == 0) {
+ status = m.status;
+ if (status == 0)
+ status = m.actual_length;
+ }
+
+ return status;
+}
+
+static int himax_bus_read(struct himax_ts_data *ts, u8 cmd,
+ u8 *buf, u32 len)
+{
+ int result = -1;
+ u8 hw_addr = 0x00;
+
+ if (len > HIMAX_BUS_R_DLEN) {
+ dev_err(ts->dev, "len[%d] is over %d", len, HIMAX_BUS_R_DLEN);
+ return result;
+ }
+
+ mutex_lock(&ts->rw_lock);
+
+ hw_addr = 0xF3;
+
+ memset(ts->xfer_data, 0, HIMAX_BUS_R_HLEN + len);
+ ts->xfer_data[0] = hw_addr;
+ ts->xfer_data[1] = cmd;
+ ts->xfer_data[2] = 0x00;
+ result = himax_spi_read(ts, ts->xfer_data, HIMAX_BUS_R_HLEN, buf, len);
+
+ mutex_unlock(&ts->rw_lock);
+
+ return result;
+}
+
+static int himax_bus_write(struct himax_ts_data *ts, u8 cmd,
+ u8 *addr, u8 *data, u32 len)
+{
+ int result = -1;
+ u8 offset = 0;
+ u32 tmp_len = len;
+ u8 hw_addr = 0x00;
+
+ if (len > HIMAX_BUS_W_DLEN) {
+ dev_err(ts->dev, "len[%d] is over %d", len, HIMAX_BUS_W_DLEN);
+ return -EFAULT;
+ }
+
+ mutex_lock(&ts->rw_lock);
+
+ hw_addr = 0xF2;
+
+ ts->xfer_data[0] = hw_addr;
+ ts->xfer_data[1] = cmd;
+ offset = HIMAX_BUS_W_HLEN;
+
+ if (addr) {
+ memcpy(ts->xfer_data + offset, addr, 4);
+ offset += 4;
+ tmp_len -= 4;
+ }
+
+ if (data)
+ memcpy(ts->xfer_data + offset, data, tmp_len);
+
+ result = himax_spi_write(ts, ts->xfer_data, len + HIMAX_BUS_W_HLEN);
+
+ mutex_unlock(&ts->rw_lock);
+
+ return (result == len + HIMAX_BUS_W_HLEN) ? 0 : -EIO;
+}
+
+static void himax_int_enable(struct himax_ts_data *ts, int enable)
+{
+ unsigned long irqflags = 0;
+ int irqnum = ts->himax_irq;
+
+ spin_lock_irqsave(&ts->irq_lock, irqflags);
+ if (enable == 1 && atomic_read(&ts->irq_state) == 0) {
+ atomic_set(&ts->irq_state, 1);
+ enable_irq(irqnum);
+ ts->irq_enabled = 1;
+ } else if (enable == 0 && atomic_read(&ts->irq_state) == 1) {
+ atomic_set(&ts->irq_state, 0);
+ disable_irq_nosync(irqnum);
+ ts->irq_enabled = 0;
+ }
+
+ spin_unlock_irqrestore(&ts->irq_lock, irqflags);
+}
+
+static void himax_ts_isr_func(struct himax_ts_data *ts)
+{
+ himax_ts_work(ts);
+}
+
+static irqreturn_t himax_ts_thread(int irq, void *ptr)
+{
+ himax_ts_isr_func((struct himax_ts_data *)ptr);
+
+ return IRQ_HANDLED;
+}
+
+static int himax_int_register_trigger(struct himax_ts_data *ts)
+{
+ int ret = 0;
+
+ if (ts->ic_data->HX_INT_IS_EDGE) {
+ ret = devm_request_threaded_irq(ts->dev, ts->himax_irq, NULL,
+ himax_ts_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ ts->dev->driver->name, ts);
+ } else {
+ ret = devm_request_threaded_irq(ts->dev, ts->himax_irq, NULL,
+ himax_ts_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ ts->dev->driver->name, ts);
+ }
+
+ return ret;
+}
+
+static int himax_ts_register_interrupt(struct himax_ts_data *ts)
+{
+ int ret = 0;
+
+ ts->irq_enabled = 0;
+
+ if (ts->himax_irq) {
+
+ ret = himax_int_register_trigger(ts);
+
+ if (ret == 0) {
+ ts->irq_enabled = 1;
+ atomic_set(&ts->irq_state, 1);
+ } else {
+
+ dev_err(ts->dev, "request_irq failed");
+ }
+ }
+
+ return ret;
+}
+
+static void himax_mcu_burst_enable(struct himax_ts_data *ts,
+ u8 auto_add_4_byte)
+{
+ u8 tmp_data[HIMAX_REG_DATA_LEN];
+ int ret;
+
+ tmp_data[0] = HIMAX_IC_CMD_CONTI;
+
+ ret = himax_bus_write(ts, HIMAX_IC_ADR_CONTI, NULL, tmp_data, 1);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ return;
+ }
+
+ tmp_data[0] = (HIMAX_IC_CMD_INCR4 | auto_add_4_byte);
+
+ ret = himax_bus_write(ts, HIMAX_IC_ADR_INCR4, NULL, tmp_data, 1);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ return;
+ }
+}
+static int himax_mcu_register_read(struct himax_ts_data *ts, u32 addr,
+ u8 *buf, u32 len)
+{
+ int ret = 0;
+ union {
+ u8 byte[4];
+ u32 word;
+ } target_addr = { .word = cpu_to_le32(addr) };
+ u8 direction_switch = HIMAX_IC_CMD_AHB_ACCESS_DIRECTION_READ;
+
+ mutex_lock(&ts->reg_lock);
+
+ if (addr == HIMAX_FLASH_ADDR_SPI200_DATA)
+ himax_mcu_burst_enable(ts, 0);
+ else if (len > HIMAX_REG_DATA_LEN)
+ himax_mcu_burst_enable(ts, 1);
+ else
+ himax_mcu_burst_enable(ts, 0);
+
+ ret = himax_bus_write(ts, HIMAX_IC_ADR_AHB_ADDR_BYTE_0, target_addr.byte, NULL, 4);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ goto read_end;
+ }
+
+ ret = himax_bus_write(ts, HIMAX_IC_ADR_AHB_ACCESS_DIRECTION, NULL,
+ &direction_switch, 1);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ goto read_end;
+ }
+
+ ret = himax_bus_read(ts, HIMAX_IC_ADR_AHB_RDATA_BYTE_0, buf, len);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ goto read_end;
+ }
+
+read_end:
+ mutex_unlock(&ts->reg_lock);
+
+ return ret;
+}
+
+static int himax_mcu_register_write(struct himax_ts_data *ts, u32 addr,
+ u8 *val, u32 len)
+{
+ int ret = 0;
+ const u32 max_trans_sz = 4 * 1024;
+ int i = 0;
+ union {
+ u8 byte[4];
+ u16 half[2];
+ u32 word;
+ } target_addr;
+ u32 temp_len = 0;
+
+ mutex_lock(&ts->reg_lock);
+ if (addr == HIMAX_FLASH_ADDR_SPI200_DATA)
+ himax_mcu_burst_enable(ts, 0);
+ else if (len > HIMAX_REG_DATA_LEN)
+ himax_mcu_burst_enable(ts, 1);
+ else
+ himax_mcu_burst_enable(ts, 0);
+
+ if (len > max_trans_sz) {
+ for (i = 0; i < len; i += max_trans_sz) {
+ if ((len - i) > max_trans_sz)
+ temp_len = max_trans_sz;
+ else
+ temp_len = len % max_trans_sz;
+
+ target_addr.word = cpu_to_le32(addr + i);
+ ret = himax_bus_write(ts, HIMAX_IC_ADR_AHB_ADDR_BYTE_0,
+ target_addr.byte, val + i, temp_len + HIMAX_REG_ADDR_LEN);
+ if (ret < 0) {
+ dev_err(ts->dev, "xfer fail!");
+ goto write_end;
+ }
+ }
+ } else {
+ target_addr.word = cpu_to_le32(addr);
+ ret = himax_bus_write(ts, HIMAX_IC_ADR_AHB_ADDR_BYTE_0, target_addr.byte, val,
+ len + HIMAX_REG_ADDR_LEN);
+ if (ret < 0) {
+ dev_err(ts->dev, "xfer fail!");
+ goto write_end;
+ }
+ }
+write_end:
+ mutex_unlock(&ts->reg_lock);
+
+ return ret;
+}
+
+
+static void himax_ap_notify_fw_sus(struct himax_ts_data *ts, int suspend)
+{
+ int retry = 0;
+ int read_sts = 0;
+ union {
+ u8 byte[4];
+ u16 half[2];
+ u32 word;
+ } rdata, data;
+
+ if (suspend)
+ data.word = HIMAX_FW_DATA_AP_NOTIFY_FW_SUS_EN;
+ else
+ data.word = HIMAX_FW_DATA_AP_NOTIFY_FW_SUS_DIS;
+
+ data.word = cpu_to_le32(data.word);
+ do {
+ himax_mcu_register_write(ts, HIMAX_FW_ADDR_AP_NOTIFY_FW_SUS, data.byte,
+ 4);
+ usleep_range(1000, 1001);
+ read_sts = himax_mcu_register_read(ts, HIMAX_FW_ADDR_AP_NOTIFY_FW_SUS, rdata.byte,
+ 4);
+ } while ((retry++ < 10) && (read_sts != 0) &&
+ (rdata.word != data.word));
+}
+
+static void himax_resume_proc(struct himax_ts_data *ts, bool suspended)
+{
+ himax_ap_notify_fw_sus(ts, 0);
+}
+
+static void himax_mcu_ic_reset(struct himax_ts_data *ts, u8 loadconfig,
+ u8 int_off)
+{
+
+ if (ts->gpiod_rst) {
+ if (int_off)
+ himax_int_enable(ts, 0);
+
+ hx83102j_pin_reset(ts);
+
+ if (int_off)
+ himax_int_enable(ts, 1);
+ }
+}
+static void himax_mcu_touch_information(struct himax_ts_data *ts)
+{
+ if (ts->ic_data->HX_RX_NUM == 0xFFFFFFFF)
+ ts->ic_data->HX_RX_NUM = 48;
+
+ if (ts->ic_data->HX_TX_NUM == 0xFFFFFFFF)
+ ts->ic_data->HX_TX_NUM = 32;
+
+ if (ts->ic_data->HX_BT_NUM == 0xFFFFFFFF)
+ ts->ic_data->HX_BT_NUM = 0;
+
+ if (ts->ic_data->HX_MAX_PT == 0xFFFFFFFF)
+ ts->ic_data->HX_MAX_PT = 10;
+
+ if (ts->ic_data->HX_INT_IS_EDGE == 0xFF)
+ ts->ic_data->HX_INT_IS_EDGE = false;
+
+ if (ts->ic_data->HX_STYLUS_FUNC == 0xFF)
+ ts->ic_data->HX_STYLUS_FUNC = 1;
+
+ if (ts->ic_data->HX_STYLUS_ID_V2 == 0xFF)
+ ts->ic_data->HX_STYLUS_ID_V2 = 0;
+
+ if (ts->ic_data->HX_STYLUS_RATIO == 0xFF)
+ ts->ic_data->HX_STYLUS_RATIO = 1;
+
+}
+static bool hx83102j_chip_detect(struct himax_ts_data *ts)
+{
+ union {
+ u8 byte[4];
+ u16 half[2];
+ u32 word;
+ } data;
+ bool ret_data = false;
+ int ret = 0;
+ int i = 0;
+ bool check_flash;
+
+ hx83102j_pin_reset(ts);
+ ret = himax_bus_read(ts, 0x13, data.byte, 1);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ return false;
+ }
+
+ check_flash = false;
+
+ if (hx83102j_sense_off(ts, check_flash) == false) {
+ ret_data = false;
+ dev_err(ts->dev, "hx83102_sense_off Fail!");
+ return ret_data;
+ }
+
+ for (i = 0; i < 5; i++) {
+ ret = himax_mcu_register_read(ts, HIMAX_HX83102J_ICID_ADDR, data.byte, 4);
+ if (ret != 0) {
+ ret_data = false;
+ dev_err(ts->dev, "read ic id Fail");
+ return ret_data;
+ }
+
+ if ((data.word & 0xFFFFFF00) == HIMAX_HX83102J_ICID_DATA) {
+ strscpy(ts->chip_name,
+ HIMAX_HX83102J_ID, 30);
+ ts->ic_data->icid = data.word;
+ ret_data = true;
+ break;
+ }
+ dev_err(ts->dev, "Read driver IC ID = %X,%X,%X",
+ data.byte[3], data.byte[2], data.byte[1]);
+ ret_data = false;
+ dev_err(ts->dev, "Read driver ID register Fail!");
+ dev_err(ts->dev, "Could NOT find Himax Chipset");
+ dev_err(ts->dev, "Please check:\n1.VCCD,VCCA,VSP,VSN");
+ dev_err(ts->dev, "2. LCM_RST,TP_RST");
+ dev_err(ts->dev, "3. Power On Sequence");
+ }
+
+ return ret_data;
+}
+static bool hx83102j_sense_off(struct himax_ts_data *ts, bool check_en)
+{
+ u32 cnt = 0;
+ union {
+ u8 byte[4];
+ u16 half[2];
+ u32 word;
+ } data;
+ int ret = 0;
+
+ do {
+ data.word = cpu_to_le32(HIMAX_FW_DATA_FW_STOP);
+ if (cnt == 0 ||
+ (data.byte[0] != 0xA5 &&
+ data.byte[0] != 0x00 &&
+ data.byte[0] != 0x87))
+ himax_mcu_register_write(ts, HIMAX_FW_ADDR_CTRL_FW,
+ data.byte, 4);
+ usleep_range(10000, 10001);
+
+ himax_mcu_register_read(ts, HIMAX_IC_ADR_CS_CENTRAL_STATE,
+ data.byte, 4);
+
+ if (data.byte[0] != 0x05)
+ break;
+
+ himax_mcu_register_read(ts, HIMAX_FW_ADDR_CTRL_FW,
+ data.byte, 4);
+ } while (data.byte[0] != 0x87 && ++cnt < 35 && check_en);
+
+ cnt = 0;
+
+ do {
+ /**
+ * set Enter safe mode : 0x31 ==> 0x9527
+ */
+ data.half[0] = cpu_to_le16(HIMAX_HX83102J_SAFE_MODE_PASSWORD);
+ ret = himax_bus_write(ts, 0x31, NULL, data.byte, 2);
+ if (ret < 0) {
+ dev_err(ts->dev, "bus access fail!");
+ return false;
+ }
+
+ /**
+ *Check enter_save_mode
+ */
+ himax_mcu_register_read(ts, HIMAX_IC_ADR_CS_CENTRAL_STATE, data.byte, 4);
+
+ if (data.byte[0] == 0x0C) {
+ /**
+ *Reset TCON
+ */
+ data.word = 0;
+ himax_mcu_register_write(ts, HIMAX_HX83102J_IC_ADR_TCON_RST, data.byte, 4);
+ usleep_range(1000, 1001);
+ return true;
+ }
+ usleep_range(5000, 5001);
+ hx83102j_pin_reset(ts);
+ } while (cnt++ < 5);
+
+ return false;
+}
+
+static bool hx83102j_read_event_stack(struct himax_ts_data *ts,
+ u8 *buf, u32 length)
+{
+ int ret = 0;
+
+ ret = himax_bus_read(ts, HIMAX_FW_ADDR_EVENT_ADDR, buf, length);
+
+ return (ret == 0) ? true : false;
+}
+
+static void hx83102j_pin_reset(struct himax_ts_data *ts)
+{
+ if (ts->gpiod_rst) {
+ gpiod_set_value(ts->gpiod_rst, 1);
+ usleep_range(100 * 100, 101 * 100);
+ gpiod_set_value(ts->gpiod_rst, 0);
+ usleep_range(200 * 100, 201 * 100);
+ }
+}
+
+static int himax_touch_get(struct himax_ts_data *ts, u8 *buf, int ts_path)
+{
+ u32 read_size = 0;
+ int ts_status = 0;
+
+ switch (ts_path) {
+ case HIMAX_REPORT_COORD:
+ read_size = ts->touch_all_size;
+ break;
+ default:
+ break;
+ }
+
+ if (read_size == 0) {
+ dev_err(ts->dev, "Read size fault!");
+ ts_status = HIMAX_TS_GET_DATA_FAIL;
+ } else {
+ if (!hx83102j_read_event_stack(ts, buf, read_size)) {
+ dev_err(ts->dev, "can't read data from chip!");
+ ts_status = HIMAX_TS_GET_DATA_FAIL;
+ }
+ }
+
+ return ts_status;
+}
+
+static int himax_hid_parse(struct hid_device *hid)
+{
+ struct himax_ts_data *ts = NULL;
+ int ret;
+
+ if (!hid) {
+ dev_err(ts->dev, "hid is NULL");
+ return -EINVAL;
+ }
+
+ ts = hid->driver_data;
+ if (!ts) {
+ dev_err(ts->dev, "hid->driver_data is NULL");
+ return -EINVAL;
+ }
+
+ ret = hid_parse_report(hid, ts->hid_rd_data.rd_data,
+ ts->hid_rd_data.rd_length);
+ if (ret) {
+ dev_err(ts->dev, "failed parse report");
+ return ret;
+ }
+ return 0;
+}
+
+static int himax_hid_start(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void himax_hid_stop(struct hid_device *hid)
+{
+}
+
+static int himax_hid_open(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void himax_hid_close(struct hid_device *hid)
+{
+}
+
+static int himax_hid_get_raw_report(const struct hid_device *hid, unsigned char reportnum,
+ __u8 *buf, size_t len, unsigned char report_type)
+{
+ struct himax_ts_data *ts = NULL;
+ int ret = 0;
+
+ ts = hid->driver_data;
+ if (!ts) {
+ dev_err(ts->dev, "hid->driver_data is NULL");
+ return -EINVAL;
+ }
+
+
+ switch (reportnum) {
+ case ID_CONTACT_COUNT:
+ if (!ts->ic_data) {
+ dev_err(ts->dev, "ts->ic_data is NULL");
+ return -EINVAL;
+ }
+ buf[1] = ts->ic_data->HX_MAX_PT;
+ ret = len;
+ break;
+ default:
+ ret = -EINVAL;
+ };
+ return ret;
+}
+
+static int himax_raw_request(struct hid_device *hid, unsigned char reportnum,
+ __u8 *buf, size_t len, unsigned char rtype, int reqtype)
+{
+ switch (reqtype) {
+ case HID_REQ_GET_REPORT:
+ return himax_hid_get_raw_report(hid, reportnum, buf, len, rtype);
+ default:
+ return -EIO;
+ }
+
+ return -EINVAL;
+}
+
+static struct hid_ll_driver himax_hid_ll_driver = {
+ .parse = himax_hid_parse,
+ .start = himax_hid_start,
+ .stop = himax_hid_stop,
+ .open = himax_hid_open,
+ .close = himax_hid_close,
+ .raw_request = himax_raw_request
+};
+
+static int himax_hid_report(const struct himax_ts_data *ts, u8 *data, s32 len)
+{
+ int ret = 0;
+
+ if (ts->hid)
+ ret = hid_input_report(ts->hid, HID_INPUT_REPORT, data, len, 1);
+
+ return ret;
+}
+static int himax_hid_probe(struct himax_ts_data *ts)
+{
+ int ret;
+ struct hid_device *hid = NULL;
+
+ if (!ts) {
+ dev_err(ts->dev, "ts is NULL");
+ return -EINVAL;
+ }
+ hid = ts->hid;
+ if (hid) {
+ hid_destroy_device(hid);
+ hid = NULL;
+ }
+
+ hid = hid_allocate_device();
+ if (IS_ERR(hid)) {
+ ret = PTR_ERR(hid);
+ return ret;
+ }
+
+ hid->driver_data = ts;
+ hid->ll_driver = &himax_hid_ll_driver;
+ hid->bus = BUS_SPI;
+ hid->dev.parent = &ts->spi->dev;
+
+ hid->version = ts->hid_desc.bcd_version;
+ hid->vendor = ts->hid_desc.vendor_id;
+ hid->product = ts->hid_desc.product_id;
+ snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-hxtp",
+ hid->vendor, hid->product);
+
+ ret = hid_add_device(hid);
+ if (ret) {
+ dev_err(ts->dev, "failed add hid device");
+ goto err_hid_data;
+ }
+ ts->hid = hid;
+ mutex_unlock(&ts->hid_ioctl_lock);
+ return 0;
+
+err_hid_data:
+ hid_destroy_device(hid);
+ return ret;
+}
+
+static void himax_hid_remove(struct himax_ts_data *ts)
+{
+ mutex_lock(&ts->hid_ioctl_lock);
+ if (ts && ts->hid)
+ hid_destroy_device(ts->hid);
+ else
+ goto out;
+ ts->hid = NULL;
+out:
+ mutex_unlock(&ts->hid_ioctl_lock);
+}
+
+
+static int himax_ts_operation(struct himax_ts_data *ts,
+ int ts_path)
+{
+ int ts_status = HIMAX_TS_NORMAL_END;
+ int ret = 0;
+ u32 offset = 0;
+
+ memset(ts->xfer_buff,
+ 0x00,
+ ts->touch_all_size * sizeof(u8));
+ ts_status = himax_touch_get(ts, ts->xfer_buff, ts_path);
+ if (ts_status == HIMAX_TS_GET_DATA_FAIL)
+ goto end_function;
+ if (ts->hid_probe) {
+ offset += ts->hid_desc.max_input_length;
+ if (ts->ic_data->HX_STYLUS_FUNC) {
+ ret += himax_hid_report(ts,
+ ts->xfer_buff + offset + HIMAX_HID_REPORT_HDR_SZ,
+ ts->hid_desc.max_input_length - HIMAX_HID_REPORT_HDR_SZ);
+ offset += ts->hid_desc.max_input_length;
+ }
+ }
+
+ if (ret != 0)
+ ts_status = HIMAX_TS_GET_DATA_FAIL;
+
+end_function:
+ return ts_status;
+}
+static void himax_ts_work(struct himax_ts_data *ts)
+{
+ int ts_status = HIMAX_TS_NORMAL_END;
+ int ts_path = 0;
+
+
+ ts_path = HIMAX_REPORT_COORD;
+ ts_status = himax_ts_operation(ts, ts_path);
+ if (ts_status == HIMAX_TS_GET_DATA_FAIL)
+ himax_mcu_ic_reset(ts, false, true);
+
+}
+
+static int himax_hid_rd_init(struct himax_ts_data *ts)
+{
+ int ret = 0;
+ u32 rd_sz = 0;
+
+ rd_sz = ts->hid_desc.report_desc_length;
+ if (ts->flash_ver_info.addr_hid_rd_desc != 0) {
+ if (ts->hid_rd_data.rd_data &&
+ rd_sz != ts->hid_rd_data.rd_length) {
+ kfree(ts->hid_rd_data.rd_data);
+ ts->hid_rd_data.rd_data = NULL;
+ }
+
+ if (!ts->hid_rd_data.rd_data)
+ ts->hid_rd_data.rd_data = kzalloc(rd_sz, GFP_KERNEL);
+
+ if (ts->hid_rd_data.rd_data) {
+ } else {
+ dev_err(ts->dev, "hid rd data alloc fail");
+ ret = -ENOMEM;
+ }
+ }
+
+ return ret;
+}
+
+static void himax_hid_register(struct himax_ts_data *ts)
+{
+ if (ts->hid_probe) {
+ hid_destroy_device(ts->hid);
+ ts->hid = NULL;
+ ts->hid_probe = false;
+ }
+
+ if (himax_hid_probe(ts) != 0) {
+ dev_err(ts->dev, "hid probe fail");
+ ts->hid_probe = false;
+ } else {
+ ts->hid_probe = true;
+ }
+}
+
+static int himax_hid_report_data_init(struct himax_ts_data *ts)
+{
+ int ret = 0;
+
+ ts->touch_info_size = ts->hid_desc.max_input_length;
+ if (ts->ic_data->HX_STYLUS_FUNC)
+ ts->touch_info_size += ts->hid_desc.max_input_length;
+
+ ts->touch_all_size = ts->touch_info_size;
+ return ret;
+}
+
+static void himax_hid_update(struct work_struct *work)
+{
+ struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
+ work_hid_update.work);
+
+ himax_int_enable(ts, false);
+ if (himax_hid_rd_init(ts) == 0) {
+ himax_hid_register(ts);
+ if (ts->hid_probe)
+ himax_hid_report_data_init(ts);
+ }
+ himax_int_enable(ts, true);
+}
+
+static int himax_chip_suspend(struct himax_ts_data *ts)
+{
+ int ret = 0;
+
+ ts->suspended = true;
+ himax_int_enable(ts, false);
+ if (ts->gpiod_rst)
+ gpiod_set_value(ts->gpiod_rst, 1);
+ himax_hid_remove(ts);
+ return ret;
+}
+
+static int himax_chip_resume(struct himax_ts_data *ts)
+{
+ int ret = 0;
+
+ ts->suspended = false;
+ if (ts->gpiod_rst)
+ gpiod_set_value(ts->gpiod_rst, 0);
+ himax_resume_proc(ts, ts->suspended);
+ himax_hid_probe(ts);
+ himax_int_enable(ts, true);
+ return ret;
+}
+
+static int himax_suspend(struct device *dev)
+{
+ struct himax_ts_data *ts = dev_get_drvdata(dev);
+
+ if (!ts->initialized) {
+ dev_err(ts->dev, "init not ready, skip!");
+ return -ECANCELED;
+ }
+ himax_chip_suspend(ts);
+ return 0;
+}
+
+static void himax_shutdown(struct spi_device *spi)
+{
+ struct himax_ts_data *ts = spi_get_drvdata(spi);
+
+ if (!ts->initialized) {
+ dev_err(ts->dev, "init not ready, skip!");
+ return;
+ }
+
+ himax_int_enable(ts, false);
+ himax_hid_remove(ts);
+}
+
+static int himax_resume(struct device *dev)
+{
+ int ret = 0;
+ struct himax_ts_data *ts = dev_get_drvdata(dev);
+
+ if (!ts->initialized) {
+ if (himax_chip_init(ts))
+ return -ECANCELED;
+ }
+ ret = himax_chip_resume(ts);
+ if (ret < 0)
+ dev_err(ts->dev, "resume failed!");
+ return ret;
+}
+static const struct dev_pm_ops himax_hid_pm = {
+ .suspend = himax_suspend,
+ .resume = himax_resume,
+ .restore = himax_resume,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id himax_table[] = {
+ { .compatible = "himax,hx83102j" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, himax_table);
+#endif
+
+static int himax_chip_init(struct himax_ts_data *ts)
+{
+ himax_mcu_touch_information(ts);
+ spin_lock_init(&ts->irq_lock);
+ if (himax_ts_register_interrupt(ts)) {
+ dev_err(ts->dev, "register interrupt failed");
+ return -EIO;
+ }
+ himax_int_enable(ts, false);
+ INIT_DELAYED_WORK(&ts->work_hid_update, himax_hid_update);
+ ts->suspended = false;
+ ts->initialized = true;
+ return 0;
+
+}
+static bool himax_platform_init(struct himax_ts_data *ts,
+ struct himax_platform_data *local_pdata)
+{
+ struct himax_platform_data *pdata;
+
+ ts->xfer_buff = devm_kzalloc(ts->dev, HIMAX_FULL_STACK_SIZE, GFP_KERNEL);
+ if (!ts->xfer_buff)
+ return false;
+
+ pdata = devm_kzalloc(ts->dev, sizeof(struct himax_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return false;
+
+
+ ts->ic_data = devm_kzalloc(ts->dev, sizeof(struct himax_ic_data), GFP_KERNEL);
+ if (!ts->ic_data)
+ return false;
+
+ memset(ts->ic_data, 0xFF, sizeof(struct himax_ic_data));
+ memcpy(pdata, local_pdata, sizeof(struct himax_platform_data));
+ ts->pdata = pdata;
+ pdata->ts = ts;
+ ts->gpiod_rst = pdata->gpiod_rst;
+ if (pdata->gpiod_rst)
+ gpiod_set_value(pdata->gpiod_rst, 1);
+ if (pdata->gpiod_rst)
+ gpiod_set_value(pdata->gpiod_rst, 0);
+
+ return true;
+}
+
+static int himax_spi_drv_probe(struct spi_device *spi)
+{
+ struct himax_ts_data *ts = NULL;
+ int ret = 0;
+ bool bret = false;
+ static struct himax_platform_data pdata = {0};
+
+ ts = devm_kzalloc(&spi->dev, sizeof(struct himax_ts_data), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->dev = &spi->dev;
+ if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) {
+ dev_err(ts->dev, "Full duplex not supported by host");
+ return -EIO;
+ }
+ pdata.ts = ts;
+ ts->dev = &spi->dev;
+ if (!spi->irq) {
+ dev_dbg(ts->dev, "no IRQ?\n");
+ return -EINVAL;
+ }
+ ts->himax_irq = spi->irq;
+ pdata.gpiod_rst = devm_gpiod_get(ts->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(pdata.gpiod_rst)) {
+ dev_err(ts->dev, "gpio-rst value is not valid");
+ return -EIO;
+ }
+
+
+ ts->xfer_data = devm_kzalloc(ts->dev, HIMAX_BUS_RW_MAX_LEN, GFP_KERNEL);
+ if (!ts->xfer_data)
+ return -ENOMEM;
+
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_3;
+ spi->chip_select = 0;
+
+ ts->spi = spi;
+ mutex_init(&ts->rw_lock);
+ mutex_init(&ts->reg_lock);
+ mutex_init(&ts->hid_ioctl_lock);
+ dev_set_drvdata(&spi->dev, ts);
+ spi_set_drvdata(spi, ts);
+
+ ts->probe_finish = false;
+ ts->initialized = false;
+ ts->ic_boot_done = false;
+ bret = himax_platform_init(ts, &pdata);
+ if (!bret) {
+ dev_err(ts->dev, "platform init failed");
+ return -ENODEV;
+ }
+
+ bret = hx83102j_chip_detect(ts);
+ if (!bret) {
+ dev_err(ts->dev, "IC detect failed");
+ return -ENODEV;
+ }
+
+ ret = himax_chip_init(ts);
+ if (ret < 0)
+ return ret;
+ ts->probe_finish = true;
+ return ret;
+
+}
+
+
+static void himax_spi_drv_remove(struct spi_device *spi)
+{
+ struct himax_ts_data *ts = spi_get_drvdata(spi);
+
+ if (ts->probe_finish) {
+ if (ts->ic_boot_done) {
+ himax_int_enable(ts, false);
+
+ if (ts->hid_probe) {
+ himax_hid_remove(ts);
+ ts->hid_probe = false;
+ }
+
+ kfree(ts->hid_rd_data.rd_data);
+ ts->hid_rd_data.rd_data = NULL;
+
+ ts->ic_boot_done = false;
+ }
+ }
+ spi_set_drvdata(spi, NULL);
+
+}
+static struct spi_driver himax_hid_over_spi_driver = {
+ .driver = {
+ .name = "hx83102j",
+ .owner = THIS_MODULE,
+ .pm = &himax_hid_pm,
+#if defined(CONFIG_OF)
+ .of_match_table = of_match_ptr(himax_table),
+#endif
+ },
+ .probe = himax_spi_drv_probe,
+ .remove = himax_spi_drv_remove,
+ .shutdown = himax_shutdown,
+};
+static void himax_spi_drv_exit(void)
+{
+ spi_unregister_driver(&himax_hid_over_spi_driver);
+}
+
+static int himax_spi_drv_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&himax_hid_over_spi_driver);
+ return ret;
+}
+
+static int __init himax_ic_init(void)
+{
+ int ret = 0;
+
+ ret = himax_spi_drv_init();
+ return ret;
+}
+
+static void __exit himax_ic_exit(void)
+{
+ himax_spi_drv_exit();
+}
+
+#if !defined(CONFIG_HID_HIMAX)
+module_init(himax_ic_init);
+#else
+late_initcall(himax_ic_init);
+#endif
+module_exit(himax_ic_exit);
+
+MODULE_DESCRIPTION("Himax SPI driver for HID simulator for " HIMAX_HX83102J_ID);
+MODULE_AUTHOR("Himax, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-himax-83102j.h b/drivers/hid/hid-himax-83102j.h
new file mode 100644
index 000000000000..61e9d006f9be
--- /dev/null
+++ b/drivers/hid/hid-himax-83102j.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __HX_IC_83102J_H__
+#define __HX_IC_83102J_H__
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/acpi.h>
+#include <linux/spi/spi.h>
+#include <linux/hid.h>
+#include <linux/sizes.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/proc_fs.h>
+#include <linux/version.h>
+#include <linux/firmware.h>
+#include <linux/stddef.h>
+#include <linux/power_supply.h>
+
+#define HIMAX_BUS_RETRY_TIMES 3
+// SPI bus read/write max length
+#define HIMAX_BUS_RW_MAX_LEN 0x20006
+// SPI bus read header length
+#define HIMAX_BUS_R_HLEN 3
+// SPI bus read data length, must be multiple of 4 and smaller than BUS_RW_MAX_LEN - BUS_R_HLEN
+#define HIMAX_BUS_R_DLEN ((HIMAX_BUS_RW_MAX_LEN - HIMAX_BUS_R_HLEN) - ((HIMAX_BUS_RW_MAX_LEN - HIMAX_BUS_R_HLEN) % 4))
+// SPI bus write header length
+#define HIMAX_BUS_W_HLEN 2
+// SPI bus write data length, must be multiple of 4 and smaller than BUS_RW_MAX_LEN - BUS_W_HLEN
+#define HIMAX_BUS_W_DLEN ((HIMAX_BUS_RW_MAX_LEN - HIMAX_BUS_W_HLEN) - ((HIMAX_BUS_RW_MAX_LEN - HIMAX_BUS_W_HLEN) % 4))
+
+enum HID_ID_FUNCT {
+ ID_CONTACT_COUNT = 0x03,
+};
+
+enum HID_FW_UPDATE_STATUS_CODE {
+ FWUP_ERROR_NO_ERROR = 0x77,
+ FWUP_ERROR_NO_MAIN = 0xC2,
+ FWUP_ERROR_BL_COMPLETE = 0xB1,
+ FWUP_ERROR_BL = 0xB2,
+ FWUP_ERROR_FLASH_PROGRAMMING = 0xB5,
+};
+
+
+// Register setting
+#define HIMAX_REG_DATA_LEN 4
+#define HIMAX_REG_ADDR_LEN 4
+#define HIMAX_MAX_TRANS_SZ 128
+#define HIMAX_MAX_RETRY_TIMES 5
+
+#define HIMAX_HX83102J_STACK_SIZE 128
+#define HIMAX_HX83102J_IC_ADR_TCON_RST 0x80020004
+#define HIMAX_HX83102J_SAFE_MODE_PASSWORD 0x9527
+#define HIMAX_HX83102J_ICID_ADDR 0x900000D0
+#define HIMAX_HX83102J_ICID_DATA 0x83102900
+#define HIMAX_HX83102J_MAX_RX_NUM 48
+#define HIMAX_HX83102J_MAX_TX_NUM 32
+
+#define HIMAX_IC_ADR_AHB_ADDR_BYTE_0 0x00
+#define HIMAX_IC_ADR_AHB_RDATA_BYTE_0 0x08
+#define HIMAX_IC_ADR_AHB_ACCESS_DIRECTION 0x0c
+#define HIMAX_IC_ADR_CONTI 0x13
+#define HIMAX_IC_ADR_INCR4 0x0D
+#define HIMAX_IC_CMD_AHB_ACCESS_DIRECTION_READ 0x00
+#define HIMAX_IC_CMD_CONTI 0x31
+#define HIMAX_IC_CMD_INCR4 0x10
+#define HIMAX_IC_ADR_CS_CENTRAL_STATE 0x900000A8
+
+#define HIMAX_FW_ADDR_CTRL_FW 0x9000005c
+#define HIMAX_FW_USB_DETECT_ADDR 0x10007F38
+#define HIMAX_FW_DATA_SAFE_MODE_RELEASE_PW_RESET 0x00000000
+#define HIMAX_FW_DATA_FW_STOP 0x000000A5
+#define HIMAX_FW_ADDR_AP_NOTIFY_FW_SUS 0x10007FD0
+#define HIMAX_FW_DATA_AP_NOTIFY_FW_SUS_EN 0xA55AA55A
+#define HIMAX_FW_DATA_AP_NOTIFY_FW_SUS_DIS 0x00000000
+#define HIMAX_FW_ADDR_EVENT_ADDR 0x30
+#define HIMAX_FW_FUNC_HANDSHAKING_PWD 0xA55AA55A
+
+#define HIMAX_FLASH_ADDR_CTRL_BASE 0x80000000
+#define HIMAX_FLASH_ADDR_SPI200_DATA (HIMAX_FLASH_ADDR_CTRL_BASE + 0x2c)
+
+#define HIMAX_HID_REPORT_HDR_SZ (2)
+#define HIMAX_HX83102J_ID "HX83102J"
+
+
+struct flash_version_info {
+ u32 addr_hid_rd_desc;
+};
+
+struct himax_hid_rd_data_t {
+ u8 *rd_data;
+ u32 rd_length;
+};
+union himax_dword_data_t {
+ u32 dword;
+ u8 byte[4];
+};
+
+enum hid_reg_action {
+ REG_READ = 0,
+ REG_WRITE = 1
+};
+
+enum hid_reg_types {
+ REG_TYPE_EXT_AHB,
+ REG_TYPE_EXT_SRAM,
+ REG_TYPE_EXT_TYPE = 0xFFFFFFFF
+};
+struct himax_hid_req_cfg_t {
+ u32 data_type;
+ u32 input_RD_de;
+};
+
+#define HIMAX_FULL_STACK_SIZE \
+ (HIMAX_HX83102J_STACK_SIZE +\
+ (2 + HIMAX_HX83102J_MAX_RX_NUM * HIMAX_HX83102J_MAX_TX_NUM + HIMAX_HX83102J_MAX_TX_NUM + HIMAX_HX83102J_MAX_RX_NUM)\
+ * 2)
+
+struct himax_ic_data {
+ u32 HX_RX_NUM;
+ u32 HX_TX_NUM;
+ u32 HX_BT_NUM;
+ u32 HX_MAX_PT;
+ u8 HX_INT_IS_EDGE;
+ u8 HX_STYLUS_FUNC;
+ u8 HX_STYLUS_ID_V2;
+ u8 HX_STYLUS_RATIO;
+ u32 icid;
+};
+
+enum HX_TS_PATH {
+ HIMAX_REPORT_COORD = 1,
+};
+
+enum HX_TS_STATUS {
+ HIMAX_TS_GET_DATA_FAIL = -4,
+ HIMAX_TS_NORMAL_END = 0,
+};
+
+struct himax_hid_desc_t {
+ u16 desc_length;
+ u16 bcd_version;
+ u16 report_desc_length;
+ u16 max_input_length;
+ u16 max_output_length;
+ u16 max_fragment_length;
+ u16 vendor_id;
+ u16 product_id;
+ u16 version_id;
+ u16 flags;
+ u32 reserved;
+} __packed;
+
+struct himax_ts_data {
+ bool initialized;
+ bool probe_finish;
+ bool suspended;
+ char chip_name[30];
+ bool ic_boot_done;
+ u8 *xfer_data;
+ struct himax_ic_data *ic_data;
+ int touch_all_size;
+ int touch_info_size;
+ struct flash_version_info flash_ver_info;
+ u8 irq_enabled;
+ struct gpio_desc *gpiod_rst;
+ s32 (*power)(s32 on);
+ struct device *dev;
+ struct himax_platform_data *pdata;
+ /* mutex lock for reg access */
+ struct mutex reg_lock;
+ /* mutex lock for read/write action */
+ struct mutex rw_lock;
+ /* mutex lock for hid ioctl action */
+ struct mutex hid_ioctl_lock;
+ atomic_t irq_state;
+ /* spin lock for irq */
+ spinlock_t irq_lock;
+ struct spi_device *spi;
+ s32 himax_irq;
+ u8 *xfer_buff;
+ struct hid_device *hid;
+ struct himax_hid_desc_t hid_desc;
+ struct himax_hid_rd_data_t hid_rd_data;
+ bool hid_probe;
+ struct delayed_work work_hid_update;
+};
+
+struct himax_platform_data {
+ struct himax_ts_data *ts;
+ struct gpio_desc *gpiod_rst;
+};
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
2023-12-27 5:35 ` [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen Allen_Lin
@ 2023-12-28 8:30 ` kernel test robot
2023-12-28 10:36 ` Krzysztof Kozlowski
1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2023-12-28 8:30 UTC (permalink / raw)
To: Allen_Lin, dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt,
conor+dt, jikos, benjamin.tissoires, linux-input, devicetree,
linux-kernel
Cc: oe-kbuild-all, Allen_Lin
Hi Allen_Lin,
kernel test robot noticed the following build warnings:
[auto build test WARNING on hid/for-next]
[also build test WARNING on dtor-input/next dtor-input/for-linus robh/for-next linus/master v6.7-rc7 next-20231222]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Allen_Lin/Input-Add-Himax-HX83102J-touchscreen-driver/20231227-133817
base: https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link: https://lore.kernel.org/r/SEZPR06MB56080820EE51CBAE9C6B6B3E9E9FA%40SEZPR06MB5608.apcprd06.prod.outlook.com
patch subject: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
:::::: branch date: 19 hours ago
:::::: commit date: 19 hours ago
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20231228/202312280837.b2PFmd9W-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/r/202312280837.b2PFmd9W-lkp@intel.com/
dtcheck warnings: (new ones prefixed by >>)
>> Documentation/devicetree/bindings/input/himax,hx83102j.yaml:1:58: [error] wrong new line character: expected \n (new-lines)
vim +1 Documentation/devicetree/bindings/input/himax,hx83102j.yaml
b6f7a8833439cc Allen_Lin 2023-12-27 @1 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
2023-12-27 5:35 ` [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen Allen_Lin
2023-12-28 8:30 ` kernel test robot
@ 2023-12-28 10:36 ` Krzysztof Kozlowski
2023-12-29 9:08 ` Allen Lin
[not found] ` <TY0PR06MB561188EBD127F8ECF4A7052B9E9DA@TY0PR06MB5611.apcprd06.prod.outlook.com>
1 sibling, 2 replies; 8+ messages in thread
From: Krzysztof Kozlowski @ 2023-12-28 10:36 UTC (permalink / raw)
To: Allen_Lin, dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt,
conor+dt, jikos, benjamin.tissoires, linux-input, devicetree,
linux-kernel
On 27/12/2023 06:35, Allen_Lin wrote:
> Add the HX83102j touchscreen device tree bindings documents.
>
> Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
> ---
Where is the changelog? There is no cover letter attached, so changelog
is supposed to be here. There were several comments, so does it mean you
ignored them?
> .../bindings/input/himax,hx83102j.yaml | 65 +++++++++++++++++++
> MAINTAINERS | 6 ++
> 2 files changed, 71 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/himax,hx83102j.yaml
>
> diff --git a/Documentation/devicetree/bindings/input/himax,hx83102j.yaml b/Documentation/devicetree/bindings/input/himax,hx83102j.yaml
> new file mode 100644
> index 000000000000..872b478c5753
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/himax,hx83102j.yaml
> @@ -0,0 +1,65 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/himax,hx83102j.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Himax hx83102j touchscreen
> +
...
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + hid-himax-spi@0 {
Still not the name I asked - it should be generic, like touchscreen.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
2023-12-28 10:36 ` Krzysztof Kozlowski
@ 2023-12-29 9:08 ` Allen Lin
[not found] ` <TY0PR06MB561188EBD127F8ECF4A7052B9E9DA@TY0PR06MB5611.apcprd06.prod.outlook.com>
1 sibling, 0 replies; 8+ messages in thread
From: Allen Lin @ 2023-12-29 9:08 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt, jikos,
benjamin.tissoires, linux-input, devicetree, linux-kernel
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 於 2023年12月28日 週四 下午6:36寫道:
>
> On 27/12/2023 06:35, Allen_Lin wrote:
> > Add the HX83102j touchscreen device tree bindings documents.
> >
> > Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
> > ---
>
> Where is the changelog? There is no cover letter attached, so changelog
> is supposed to be here. There were several comments, so does it mean you
> ignored them?
>
Cover letter is not in this mail but in the mail with this title
"[PATCH v3 0/2] Add HX83102j driver for HIMAX HID touchscreen"
Hi,
This driver implements for Himax HID touchscreen HX83102j.
Using SPI interface to receive/send HID packets.
Patchs notes as below
1. Add the Maintainer and devicetree bindings document for driver
2. Add the driver code and modify Kconfig/Makefile to support the driver
change in v2 :
- Fix kernel test robot build warnings.
change in v3 :
- Modify code according to review suggesions.
Thanks.
Allen_Lin (2):
dt-bindings: input: Add Himax HX83102J touchscreen
Input: Add Himax HX83102J touchscreen driver
.../bindings/input/himax,hx83102j.yaml | 65 +
MAINTAINERS | 7 +
drivers/hid/Kconfig | 8 +
drivers/hid/Makefile | 2 +
drivers/hid/hid-himax-83102j.c | 1096 +++++++++++++++++
drivers/hid/hid-himax-83102j.h | 202 +++
6 files changed, 1380 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/himax,hx83102j.yaml
create mode 100644 drivers/hid/hid-himax-83102j.c
create mode 100644 drivers/hid/hid-himax-83102j.h
--
2.34.1
>
> > .../bindings/input/himax,hx83102j.yaml | 65 +++++++++++++++++++
> > MAINTAINERS | 6 ++
> > 2 files changed, 71 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/input/himax,hx83102j.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/input/himax,hx83102j.yaml b/Documentation/devicetree/bindings/input/himax,hx83102j.yaml
> > new file mode 100644
> > index 000000000000..872b478c5753
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/input/himax,hx83102j.yaml
> > @@ -0,0 +1,65 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/input/himax,hx83102j.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Himax hx83102j touchscreen
> > +
>
> ...
>
> > +examples:
> > + - |
> > + #include <dt-bindings/gpio/gpio.h>
> > + #include <dt-bindings/interrupt-controller/irq.h>
> > + spi {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + hid-himax-spi@0 {
>
> Still not the name I asked - it should be generic, like touchscreen.
>
I will fix it, thanks for your review. if driver code needs to be
modified, i will fix it together.
> Best regards,
> Krzysztof
>
Best regards
Allen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
[not found] ` <TY0PR06MB561188EBD127F8ECF4A7052B9E9DA@TY0PR06MB5611.apcprd06.prod.outlook.com>
@ 2023-12-30 14:19 ` Krzysztof Kozlowski
2024-01-02 2:36 ` Allen Lin
2024-01-04 1:14 ` Allen Lin
0 siblings, 2 replies; 8+ messages in thread
From: Krzysztof Kozlowski @ 2023-12-30 14:19 UTC (permalink / raw)
To: Allen Lin
Cc: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt, jikos,
benjamin.tissoires, linux-input, devicetree, linux-kernel
On 29/12/2023 10:08, Allen Lin wrote:
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 於 2023年12月28日 週四 下午6:36寫道:
>>
>> On 27/12/2023 06:35, Allen_Lin wrote:
>>> Add the HX83102j touchscreen device tree bindings documents.
>>>
>>> Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
>>> ---
>>
>> Where is the changelog? There is no cover letter attached, so changelog
>> is supposed to be here. There were several comments, so does it mean you
>> ignored them?
>>
> Cover letter is not in this mail but in the mail with this title
> "[PATCH v3 0/2] Add HX83102j driver for HIMAX HID touchscreen"
There was no cover letter attached to this thread. Don't send cover
letters in separate threads.
>
> Hi,
> This driver implements for Himax HID touchscreen HX83102j.
>
> Using SPI interface to receive/send HID packets.
>
> Patchs notes as below
> 1. Add the Maintainer and devicetree bindings document for driver
> 2. Add the driver code and modify Kconfig/Makefile to support the driver
>
> change in v2 :
> - Fix kernel test robot build warnings.
> change in v3 :
> - Modify code according to review suggesions.
Not detailed enough. What did you change exactly?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
2023-12-30 14:19 ` Krzysztof Kozlowski
@ 2024-01-02 2:36 ` Allen Lin
2024-01-04 1:14 ` Allen Lin
1 sibling, 0 replies; 8+ messages in thread
From: Allen Lin @ 2024-01-02 2:36 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Allen Lin, dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt,
conor+dt, jikos, benjamin.tissoires, linux-input, devicetree,
linux-kernel
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 於 2023年12月30日 週六 下午10:19寫道:
>
> On 29/12/2023 10:08, Allen Lin wrote:
> > Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 於 2023年12月28日 週四 下午6:36寫道:
> >>
> >> On 27/12/2023 06:35, Allen_Lin wrote:
> >>> Add the HX83102j touchscreen device tree bindings documents.
> >>>
> >>> Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
> >>> ---
> >>
> >> Where is the changelog? There is no cover letter attached, so changelog
> >> is supposed to be here. There were several comments, so does it mean you
> >> ignored them?
> >>
> > Cover letter is not in this mail but in the mail with this title
> > "[PATCH v3 0/2] Add HX83102j driver for HIMAX HID touchscreen"
>
> There was no cover letter attached to this thread. Don't send cover
> letters in separate threads.
>
> >
> > Hi,
> > This driver implements for Himax HID touchscreen HX83102j.
> >
> > Using SPI interface to receive/send HID packets.
> >
> > Patchs notes as below
> > 1. Add the Maintainer and devicetree bindings document for driver
> > 2. Add the driver code and modify Kconfig/Makefile to support the driver
> >
> > change in v2 :
> > - Fix kernel test robot build warnings.
> > change in v3 :
> > - Modify code according to review suggesions.
>
> Not detailed enough. What did you change exactly?
>
1. Remove function pointer coding style
2. Remove unused code/variable/structure
3. Use devm_kzalloc() to allocate memory
4. Use gpio descriptors to control gpio
5. All functions are changed to static
6. Drop all global variables.
>
> Best regards,
> Krzysztof
>
Best regards
Allen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen
2023-12-30 14:19 ` Krzysztof Kozlowski
2024-01-02 2:36 ` Allen Lin
@ 2024-01-04 1:14 ` Allen Lin
1 sibling, 0 replies; 8+ messages in thread
From: Allen Lin @ 2024-01-04 1:14 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Allen Lin, dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt,
conor+dt, jikos, benjamin.tissoires, linux-input, devicetree,
linux-kernel
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 於 2023年12月30日 週六 下午10:19寫道:
>
> On 29/12/2023 10:08, Allen Lin wrote:
> > Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 於 2023年12月28日 週四 下午6:36寫道:
> >>
> >> On 27/12/2023 06:35, Allen_Lin wrote:
> >>> Add the HX83102j touchscreen device tree bindings documents.
> >>>
> >>> Signed-off-by: Allen_Lin <allencl_lin@hotmail.com>
> >>> ---
> >>
> >> Where is the changelog? There is no cover letter attached, so changelog
> >> is supposed to be here. There were several comments, so does it mean you
> >> ignored them?
> >>
> > Cover letter is not in this mail but in the mail with this title
> > "[PATCH v3 0/2] Add HX83102j driver for HIMAX HID touchscreen"
>
> There was no cover letter attached to this thread. Don't send cover
> letters in separate threads.
>
> >
> > Hi,
> > This driver implements for Himax HID touchscreen HX83102j.
> >
> > Using SPI interface to receive/send HID packets.
> >
> > Patchs notes as below
> > 1. Add the Maintainer and devicetree bindings document for driver
> > 2. Add the driver code and modify Kconfig/Makefile to support the driver
> >
> > change in v2 :
> > - Fix kernel test robot build warnings.
> > change in v3 :
> > - Modify code according to review suggesions.
>
> Not detailed enough. What did you change exactly?
>
1. Remove function pointer coding style
2. Remove unused code/variable/structure
3. Use devm_kzalloc() to allocate memory
4. Use gpio descriptors to control gpio
5. All functions are changed to static
6. Drop all global variables.
>
> Best regards,
> Krzysztof
>
Best regards
Allen
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-01-04 1:20 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20231227053509.894642-1-allencl_lin@hotmail.com>
2023-12-27 5:35 ` [PATCH v3 1/2] dt-bindings: input: Add Himax HX83102J touchscreen Allen_Lin
2023-12-28 8:30 ` kernel test robot
2023-12-28 10:36 ` Krzysztof Kozlowski
2023-12-29 9:08 ` Allen Lin
[not found] ` <TY0PR06MB561188EBD127F8ECF4A7052B9E9DA@TY0PR06MB5611.apcprd06.prod.outlook.com>
2023-12-30 14:19 ` Krzysztof Kozlowski
2024-01-02 2:36 ` Allen Lin
2024-01-04 1:14 ` Allen Lin
2023-12-27 5:35 ` [PATCH v3 2/2] Input: Add Himax HX83102J touchscreen driver Allen_Lin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).