From patchwork Wed Oct 28 22:13:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 11864723 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AB6376A2 for ; Thu, 29 Oct 2020 01:02:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 854AC20796 for ; Thu, 29 Oct 2020 01:02:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="A2QmttkI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731049AbgJ2BCE (ORCPT ); Wed, 28 Oct 2020 21:02:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730534AbgJ1WNJ (ORCPT ); Wed, 28 Oct 2020 18:13:09 -0400 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F37EAC0613CF; Wed, 28 Oct 2020 15:13:08 -0700 (PDT) Received: by mail-wr1-x433.google.com with SMTP id g12so669792wrp.10; Wed, 28 Oct 2020 15:13:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cGK0y4DdjN+ht1VXSEDsJItbDCIWKoPEWxNpiJk8/U4=; b=A2QmttkI2fe6dA/2YZGL64pX8xVnqR6evtzrPGT+ldsFPQcVmv1JwRorV+t51DAGQk gGOhIou6GLz7/wQpic/qi0h/5wxwyYmluu2JJQ5DOsbSMm8oTfmOg4Qb8vcZsUFlE7H1 y3Yf26m+/4UUHX2zheGb6YiHC+km8BUKiPxcct3iK04Q5OPp8TJVTcTk+jZyo9e6zdHB MVcMVjkkSRulUgoNbPIU8+pQN7bxJjifv3L5K+DinD0VbLGa45KtADz0NTsaNUKjON2R iMJ3m35zbIyNJL7Rvmuf5G9vM6QPoj4qVCIGM2FkFyYnlD0zVwAJq7qsNbT13hRuFKlM Zr1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cGK0y4DdjN+ht1VXSEDsJItbDCIWKoPEWxNpiJk8/U4=; b=oMn6d5UfWQ1dJTxaaE4ACTXTj5YYglJdfX/ryLSd8W946rnKFlqND1d75mOnV47fpc psS8t991pSOMdQYeWIlR8YGecH28sop5RyuP9OhraoHAyiMonK81Kp+XRLwQyLLtIlvx 1n3GAlJbchsVgygG6sCCBgcnbHILptBqg/BHYLwOk+DF4ueojgG3J2ZRPpLcDBbOVon0 rl6gqSejd6VFsgSbNgPJ+Cna0UnqaW1ya5Rnmu393QNzuhKkvtF1VdQTVpOQVSRsof0w EKEfkXImnzBBa67dOkaJ5/4zOVJ30TeDP3flwK30v50kdyIfGbMfdjSrZ/Xt/mm19P2e 78jg== X-Gm-Message-State: AOAM531TAzAYqC3Rgw8f/P4HtAb0tcoA2Hi08pZtjqFLJsMtNU4yRuED Tte+72mIVZkx/kZrl2j0jn06RINN4sATMyem X-Google-Smtp-Source: ABdhPJxm6cfbG6QjUkuAqgjbUqmYmPAAy0t2sdXju04r3h0/YH3Fuj3gbcmR6HtqNnJfop1leFoS2g== X-Received: by 2002:adf:bd86:: with SMTP id l6mr1665232wrh.205.1603923187610; Wed, 28 Oct 2020 15:13:07 -0700 (PDT) Received: from IcarusMOD.eternityproject.eu ([2.237.20.237]) by smtp.gmail.com with ESMTPSA id x1sm1318928wrl.41.2020.10.28.15.13.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2020 15:13:07 -0700 (PDT) From: kholk11@gmail.com To: dmitry.torokhov@gmail.com Cc: robh+dt@kernel.org, rydberg@bitmath.org, priv.luk@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kholk11@gmail.com, marijns95@gmail.com, konradybcio@gmail.com, martin.botka1@gmail.com, phone-devel@vger.kernel.org, devicetree@vger.kernel.org, krzk@kernel.org, andy.shevchenko@gmail.com Subject: [PATCH v9 1/3] dt-bindings: Add vendor prefix for Novatek Microelectronics Corp. Date: Wed, 28 Oct 2020 23:13:00 +0100 Message-Id: <20201028221302.66583-2-kholk11@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201028221302.66583-1-kholk11@gmail.com> References: <20201028221302.66583-1-kholk11@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: AngeloGioacchino Del Regno Add prefix for Novatek Microelectronics Corp. Signed-off-by: AngeloGioacchino Del Regno --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 66e45112a8d7..f98ea0af487d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -740,6 +740,8 @@ patternProperties: description: Nokia "^nordic,.*": description: Nordic Semiconductor + "^novatek,.*": + description: Novatek Microelectronics Corp. "^novtech,.*": description: NovTech, Inc. "^nutsboard,.*": From patchwork Wed Oct 28 22:13:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 11864719 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 48172697 for ; Thu, 29 Oct 2020 01:02:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0B0AE207BC for ; Thu, 29 Oct 2020 01:02:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Xi8tPFYz" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731089AbgJ1WN1 (ORCPT ); Wed, 28 Oct 2020 18:13:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731018AbgJ1WNK (ORCPT ); Wed, 28 Oct 2020 18:13:10 -0400 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70CA6C0613D2; Wed, 28 Oct 2020 15:13:10 -0700 (PDT) Received: by mail-wm1-x32d.google.com with SMTP id h22so729288wmb.0; Wed, 28 Oct 2020 15:13:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Kzzaw2JLNrKIrkXkBNAUpIJgRcwxBfjeWMF9DAp8eWY=; b=Xi8tPFYzS96V9ieKu2SG0z0Q7sjww6/wS71HzskZ8V36W51+PQLdRJla6Tjwi8xh65 1IFAVmYxg5MrGhrF7hP2/1bxd1rGIrj6X9udUlBRwrPrkBbUBm/1s/tc8uWTT8QzEsVm cc1pw7UiHoBextPTNN+fvMMwEghaURACo6/kjs5oyzftBJL5qFWVKVghyEgrI3PEaUuh KQjSMa1UwGcH/wI4K6Lkqfpvpi/61zWgkA7Fc/kpZ6vcuqQ6nTmpHUHpkI2hFVOnKsRV g4FueR0zthmzTyKFhPPEJEAKy5yuPjP7ztsIvUzvAdAYlHnNpcPUAw1aZEgbEY4zXEVa 2Fhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Kzzaw2JLNrKIrkXkBNAUpIJgRcwxBfjeWMF9DAp8eWY=; b=SvYNztM2iIEXdH6Y/Gl64VFFwCAD+HIXxvez0FYMPk7SvHgNGFW8BWKd5B1sIQhrNV lcjs5lzN4tu6WJ5GXr71qByDdOXpPHBD3JFkbpwToOcYGEaXV8deYfwib+9zf7q4CH6B SCGnIrOETvjhhjLWvJboB07zCgmK7R0J45opt51XvilxgNe9lhVHDzaabqEptE8+dv9N gp+KY/reFqYbX/CjVeLcItCIJ+Tzr7V2hII7XGGIhAwrsAXkMtp9w1jJ0ZvQqsdB/kYD +3/hGDjQc7nyoL6AFDB8nzy909u5+X+n8HRYVrO1VV3SKTfV+2O3Jv/XyEegVaUCeqBA PS6Q== X-Gm-Message-State: AOAM532i+1PBGISrH3FL9J3SjeizekDA6y7dxU5mbBKN8OObDQsT8plj zopxqmAcIMARRpHDGo3PMi4= X-Google-Smtp-Source: ABdhPJzBcQv0h3wE93wFQzBK+w80/vvkzGXlieO6fBxHmF/qK19jq3wbZb6GNyp/60tc03sU2ZaeUA== X-Received: by 2002:a7b:c92c:: with SMTP id h12mr1042555wml.134.1603923188838; Wed, 28 Oct 2020 15:13:08 -0700 (PDT) Received: from IcarusMOD.eternityproject.eu ([2.237.20.237]) by smtp.gmail.com with ESMTPSA id x1sm1318928wrl.41.2020.10.28.15.13.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2020 15:13:08 -0700 (PDT) From: kholk11@gmail.com To: dmitry.torokhov@gmail.com Cc: robh+dt@kernel.org, rydberg@bitmath.org, priv.luk@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kholk11@gmail.com, marijns95@gmail.com, konradybcio@gmail.com, martin.botka1@gmail.com, phone-devel@vger.kernel.org, devicetree@vger.kernel.org, krzk@kernel.org, andy.shevchenko@gmail.com Subject: [PATCH v9 2/3] Input: Add Novatek NT36xxx touchscreen driver Date: Wed, 28 Oct 2020 23:13:01 +0100 Message-Id: <20201028221302.66583-3-kholk11@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201028221302.66583-1-kholk11@gmail.com> References: <20201028221302.66583-1-kholk11@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: AngeloGioacchino Del Regno This is a driver for the Novatek in-cell touch controller and supports various chips from the NT36xxx family, currently including NT36525, NT36672A, NT36676F, NT36772 and NT36870. Functionality like wake gestures and firmware flashing is not included: I am not aware of any of these DrIC+Touch combo chips not including a non-volatile memory and it should be highly unlikely to find one, since the touch firmware is embedded into the DriverIC one, which is obviously necessary to drive the display unit. However, the necessary address for the firmware update procedure was included into the address table in this driver so, in the event that someone finds the need to implement it for a reason or another, it will be pretty straightforward to. This driver is lightly based on the downstream implementation [1]. [1] https://github.com/Rasenkai/caf-tsoft-Novatek-nt36xxx Signed-off-by: AngeloGioacchino Del Regno --- drivers/input/touchscreen/Kconfig | 12 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/nt36xxx.c | 894 ++++++++++++++++++++++++++++ drivers/input/touchscreen/nt36xxx.h | 122 ++++ 4 files changed, 1029 insertions(+) create mode 100644 drivers/input/touchscreen/nt36xxx.c create mode 100644 drivers/input/touchscreen/nt36xxx.h diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 35c867b2d9a7..6d118b967021 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -605,6 +605,18 @@ config TOUCHSCREEN_MTOUCH To compile this driver as a module, choose M here: the module will be called mtouch. +config TOUCHSCREEN_NT36XXX + tristate "Novatek NT36XXX In-Cell I2C touchscreen controller" + depends on I2C + help + Say Y here if you have a Novatek NT36xxx series In-Cell + touchscreen connected to your system over I2C. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called nt36xxx. + config TOUCHSCREEN_IMX6UL_TSC tristate "Freescale i.MX6UL touchscreen controller" depends on (OF && GPIOLIB) || COMPILE_TEST diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 30d1e1b42492..424a555e03d5 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o obj-$(CONFIG_TOUCHSCREEN_MMS114) += mms114.o obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o +obj-$(CONFIG_TOUCHSCREEN_NT36XXX) += nt36xxx.o obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO) += ipaq-micro-ts.o diff --git a/drivers/input/touchscreen/nt36xxx.c b/drivers/input/touchscreen/nt36xxx.c new file mode 100644 index 000000000000..a572d2b87464 --- /dev/null +++ b/drivers/input/touchscreen/nt36xxx.c @@ -0,0 +1,894 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Novatek NT36xxx series touchscreens + * + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2020 AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* FW Param address */ +#define NT36XXX_FW_ADDR 0x01 + +/* Number of bytes for chip identification */ +#define NT36XXX_ID_LEN_MAX 6 + +/* Touch info */ +#define TOUCH_DEFAULT_MAX_WIDTH 1080 +#define TOUCH_DEFAULT_MAX_HEIGHT 2246 +#define TOUCH_MAX_FINGER_NUM 10 +#define TOUCH_MAX_PRESSURE 1000 + +/* Point data length */ +#define POINT_DATA_LEN 65 + +/* Global pages */ +#define NT36XXX_PAGE_CHIP_INFO 0x0001f64e +#define NT36XXX_PAGE_CRC 0x0003f135 + +/* Misc */ +#define NT36XXX_NUM_SUPPLIES 2 +#define NT36XXX_MAX_RETRIES 5 +#define NT36XXX_MAX_FW_RST_RETRY 50 + +struct nt36xxx_abs_object { + u16 x; + u16 y; + u16 z; + u8 tm; +}; + +struct nt36xxx_fw_info { + u8 fw_ver; + u8 x_num; + u8 y_num; + u8 max_buttons; + u16 abs_x_max; + u16 abs_y_max; + u16 nvt_pid; +}; + +struct nt36xxx_mem_map { + u32 evtbuf_addr; + u32 pipe0_addr; + u32 pipe1_addr; + u32 flash_csum_addr; + u32 flash_data_addr; +}; + +struct nt36xxx_i2c { + struct i2c_client *hw_client; + struct i2c_client *fw_client; + struct regmap *regmap; + struct regmap *fw_regmap; + struct input_dev *input; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; + + struct mutex lock; + + struct touchscreen_properties prop; + struct nt36xxx_fw_info fw_info; + struct nt36xxx_abs_object abs_obj; + + const struct nt36xxx_mem_map *mmap; +}; + +enum nt36xxx_chips { + NT36525_IC = 0, + NT36672A_IC, + NT36676F_IC, + NT36772_IC, + NT36870_IC, + NTMAX_IC, +}; + +struct nt36xxx_trim_table { + u8 id[NT36XXX_ID_LEN_MAX]; + u8 mask[NT36XXX_ID_LEN_MAX]; + enum nt36xxx_chips mapid; +}; + +enum nt36xxx_cmds { + NT36XXX_CMD_ENTER_SLEEP = 0x11, + NT36XXX_CMD_ENTER_WKUP_GESTURE = 0x13, + NT36XXX_CMD_UNLOCK = 0x35, + NT36XXX_CMD_BOOTLOADER_RESET = 0x69, + NT36XXX_CMD_SW_RESET = 0xa5, + NT36XXX_CMD_SET_PAGE = 0xff, +}; + +/** + * enum nt36xxx_fw_state - Firmware state + * @NT36XXX_STATE_INIT: IC Reset + * @NT36XXX_STATE_REK: ReK baseline + * @NT36XXX_STATE_REK_FINISH: Baseline is ready + * @NT36XXX_STATE_NORMAL_RUN: Firmware is running + */ +enum nt36xxx_fw_state { + NT36XXX_STATE_INIT = 0xa0, + NT36XXX_STATE_REK, + NT36XXX_STATE_REK_FINISH, + NT36XXX_STATE_NORMAL_RUN, + NT36XXX_STATE_MAX = 0xaf +}; + +enum nt36xxx_i2c_events { + NT36XXX_EVT_REPORT = 0x00, + NT36XXX_EVT_CRC = 0x35, + NT36XXX_EVT_CHIPID = 0x4e, + NT36XXX_EVT_HOST_CMD = 0x50, + NT36XXX_EVT_HS_OR_SUBCMD = 0x51, /* Handshake or subcommand byte */ + NT36XXX_EVT_RESET_COMPLETE = 0x60, + NT36XXX_EVT_FWINFO = 0x78, + NT36XXX_EVT_PROJECTID = 0x9a, +}; + +static const struct nt36xxx_mem_map nt36xxx_memory_maps[] = { + [NT36525_IC] = { 0x11a00, 0x10000, 0x12000, 0x14000, 0x14002 }, + [NT36672A_IC] = { 0x21c00, 0x20000, 0x23000, 0x24000, 0x24002 }, + [NT36676F_IC] = { 0x11a00, 0x10000, 0x12000, 0x14000, 0x14002 }, + [NT36772_IC] = { 0x11e00, 0x10000, 0x12000, 0x14000, 0x14002 }, + [NT36870_IC] = { 0x25000, 0x20000, 0x23000, 0x24000, 0x24002 }, +}; + +static const struct nt36xxx_trim_table trim_id_table[] = { + { + .id = { 0x0A, 0xFF, 0xFF, 0x72, 0x66, 0x03 }, + .mask = { 1, 0, 0, 1, 1, 1 }, + .mapid = NT36672A_IC, + }, + { + .id = { 0x55, 0x00, 0xFF, 0x00, 0x00, 0x00 }, + .mask = { 1, 1, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0x55, 0x72, 0xFF, 0x00, 0x00, 0x00 }, + .mask = { 1, 1, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00 }, + .mask = { 1, 1, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00 }, + .mask = { 1, 1, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x70, 0x68, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36772_IC, + }, + { + .id = { 0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03 }, + .mask = { 0, 0, 0, 1, 1, 1 }, + .mapid = NT36676F_IC, + }, +}; + +/** + * nt36xxx_set_page - Set page number for read/write + * @ts: Main driver structure + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_set_page(struct nt36xxx_i2c *ts, u32 pageaddr) +{ + u32 data = cpu_to_be32(pageaddr) >> 8; + int ret; + + ret = regmap_noinc_write(ts->fw_regmap, NT36XXX_CMD_SET_PAGE, + &data, sizeof(data)); + if (ret) + return ret; + + usleep_range(100, 200); + return ret; +} + +/** + * nt36xxx_sw_reset_idle - Warm restart the firmware + * @ts: Main driver structure + * + * This function restarts the running firmware without rebooting to + * the bootloader (warm restart) + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_sw_reset_idle(struct nt36xxx_i2c *ts) +{ + int ret; + + ret = regmap_write(ts->regmap, ts->hw_client->addr, + NT36XXX_CMD_SW_RESET); + if (ret) + return ret; + + /* Wait until the MCU resets the fw state */ + usleep_range(15000, 16000); + return ret; +} + +/** + * nt36xxx_bootloader_reset - Reset MCU to bootloader + * @ts: Main driver structure + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_bootloader_reset(struct nt36xxx_i2c *ts) +{ + int ret; + + ret = regmap_write(ts->regmap, ts->hw_client->addr, + NT36XXX_CMD_BOOTLOADER_RESET); + if (ret) + return ret; + + /* MCU has to reboot from bootloader: this is the typical boot time */ + msleep(35); + return ret; +} + +/** + * nt36xxx_check_reset_state - Check the boot state during reset + * @ts: Main driver structure + * @fw_state: Enumeration containing firmware states + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_check_reset_state(struct nt36xxx_i2c *ts, + enum nt36xxx_fw_state fw_state) +{ + u8 buf[2] = { 0 }; + int ret, retry = NT36XXX_MAX_FW_RST_RETRY; + + do { + ret = regmap_noinc_read(ts->fw_regmap, + NT36XXX_EVT_RESET_COMPLETE, + buf, sizeof(buf)); + if (likely(ret == 0) && + (buf[0] >= fw_state) && + (buf[0] <= NT36XXX_STATE_MAX)) { + ret = 0; + break; + } + usleep_range(10000, 11000); + } while (--retry); + + if (!retry) { + dev_err(&ts->hw_client->dev, "Firmware reset failed.\n"); + ret = -EBUSY; + } + + return ret; +} + +/** + * nt36xxx_read_pid - Read Novatek Project ID + * @ts: Main driver structure + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_read_pid(struct nt36xxx_i2c *ts) +{ + __be16 pid; + int ret; + + ret = nt36xxx_set_page(ts, ts->mmap->evtbuf_addr); + if (ret) + return ret; + + ret = regmap_noinc_read(ts->fw_regmap, NT36XXX_EVT_PROJECTID, + &pid, sizeof(pid)); + if (ret < 0) + return ret; + + ts->fw_info.nvt_pid = be16_to_cpu(pid); + return 0; +} + +/** + * __nt36xxx_get_fw_info - Get working params from firmware + * @ts: Main driver structure + * + * Return: Always zero for success, negative number for error + */ +static int __nt36xxx_get_fw_info(struct nt36xxx_i2c *ts) +{ + struct nt36xxx_fw_info *fwi = &ts->fw_info; + u8 buf[11] = { 0 }; + int ret = 0; + + ret = nt36xxx_set_page(ts, ts->mmap->evtbuf_addr); + if (ret) + return ret; + + ret = regmap_noinc_read(ts->fw_regmap, NT36XXX_EVT_FWINFO, + buf, sizeof(buf)); + if (ret) + return ret; + + fwi->fw_ver = buf[0]; + fwi->x_num = buf[2]; + fwi->y_num = buf[3]; + fwi->abs_x_max = get_unaligned_be16(&buf[4]); + fwi->abs_y_max = get_unaligned_be16(&buf[6]); + fwi->max_buttons = buf[10]; + + /* Check fw info integrity and clear x_num, y_num if broken */ + if ((buf[0] + buf[1]) != 0xFF) { + dev_err(&ts->hw_client->dev, + "FW info is broken! fw_ver=0x%02X, ~fw_ver=0x%02X\n", + buf[0], buf[1]); + fwi->fw_ver = 0; + fwi->x_num = 18; + fwi->y_num = 32; + fwi->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH; + fwi->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT; + fwi->max_buttons = 0; + return -EINVAL; + } + + /* Get Novatek ProjectID */ + return nt36xxx_read_pid(ts); +} + +static int nt36xxx_get_fw_info(struct nt36xxx_i2c *ts) +{ + struct nt36xxx_fw_info *fwi = &ts->fw_info; + int i, ret = 0; + + for (i = 0; i < NT36XXX_MAX_RETRIES; i++) { + ret = __nt36xxx_get_fw_info(ts); + if (ret == 0) + break; + } + + dev_dbg(&ts->hw_client->dev, + "FW Info: PID=0x%x, ver=0x%x res=%ux%u max=%ux%u buttons=%u", + fwi->nvt_pid, fwi->fw_ver, fwi->x_num, fwi->y_num, + fwi->abs_x_max, fwi->abs_y_max, fwi->max_buttons); + + return ret; +} + +/** + * nt36xxx_report - Report touch events + * @ts: Main driver structure + * + * Return: Always zero for success, negative number for error + */ +static void nt36xxx_report(struct nt36xxx_i2c *ts) +{ + struct nt36xxx_abs_object *obj = &ts->abs_obj; + struct input_dev *input = ts->input; + u8 input_id = 0; + u8 point[POINT_DATA_LEN + 1] = { 0 }; + unsigned int ppos = 0; + int i, ret, finger_cnt = 0; + + mutex_lock(&ts->lock); + + ret = regmap_noinc_read(ts->fw_regmap, NT36XXX_EVT_REPORT, + point, sizeof(point)); + if (ret < 0) { + dev_err(&ts->hw_client->dev, + "Cannot read touch point data: %d\n", ret); + goto xfer_error; + } + + for (i = 0; i < TOUCH_MAX_FINGER_NUM; i++) { + ppos = 6 * i; + input_id = point[ppos + 0] >> 3; + if ((input_id == 0) || (input_id > TOUCH_MAX_FINGER_NUM)) + continue; + + if (((point[ppos] & 0x07) == 0x01) || + ((point[ppos] & 0x07) == 0x02)) { + obj->x = (point[ppos + 1] << 4) + + (point[ppos + 3] >> 4); + obj->y = (point[ppos + 2] << 4) + + (point[ppos + 3] & 0xf); + if ((obj->x > ts->prop.max_x) || + (obj->y > ts->prop.max_y)) + continue; + + obj->tm = point[ppos + 4]; + if (obj->tm == 0) + obj->tm = 1; + + obj->z = point[ppos + 5]; + if (i < 2) { + obj->z += point[i + 63] << 8; + if (obj->z > TOUCH_MAX_PRESSURE) + obj->z = TOUCH_MAX_PRESSURE; + } + + if (obj->z == 0) + obj->z = 1; + + input_mt_slot(input, input_id - 1); + input_mt_report_slot_state(input, + MT_TOOL_FINGER, true); + touchscreen_report_pos(input, &ts->prop, obj->x, + obj->y, true); + + input_report_abs(input, ABS_MT_TOUCH_MAJOR, obj->tm); + input_report_abs(input, ABS_MT_PRESSURE, obj->z); + + finger_cnt++; + } + } + input_mt_sync_frame(input); + input_sync(input); + +xfer_error: + enable_irq(ts->hw_client->irq); + + mutex_unlock(&ts->lock); +} + +static irqreturn_t nt36xxx_i2c_irq_handler(int irq, void *dev_id) +{ + struct nt36xxx_i2c *ts = dev_id; + + disable_irq_nosync(ts->hw_client->irq); + nt36xxx_report(ts); + + return IRQ_HANDLED; +} + +static bool nt36xxx_in_crc_reboot_loop(u8 *buf) +{ + return ((buf[0] == 0xFC) && (buf[1] == 0xFC) && (buf[2] == 0xFC)) || + ((buf[0] == 0xFF) && (buf[1] == 0xFF) && (buf[2] == 0xFF)); +} + +/** + * nt36xxx_stop_crc_reboot - Stop CRC reboot loop and warm-reboot the firmware + * @ts: Main driver structure + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_stop_crc_reboot(struct nt36xxx_i2c *ts) +{ + u8 buf[3] = { 0 }; + u8 val; + int ret, retry = NT36XXX_MAX_RETRIES; + + /* Read dummy buffer to check CRC fail reboot is happening or not */ + + /* Change I2C index to prevent getting 0xFF, but not 0xFC */ + ret = nt36xxx_set_page(ts, NT36XXX_PAGE_CHIP_INFO); + if (ret) { + dev_dbg(&ts->hw_client->dev, + "CRC reset failed: Cannot select page.\n"); + return ret; + } + + /* If ChipID command returns 0xFC or 0xFF, the MCU is in CRC reboot */ + ret = regmap_noinc_read(ts->fw_regmap, NT36XXX_EVT_CHIPID, + buf, sizeof(buf)); + if (ret) + return ret; + + if (!nt36xxx_in_crc_reboot_loop(buf)) + return 0; + + /* IC is in CRC fail reboot loop, needs to be stopped! */ + do { + /* Special reset-idle sequence for CRC failure */ + ret = regmap_write(ts->regmap, ts->hw_client->addr, + NT36XXX_CMD_SW_RESET); + if (ret) + dev_dbg(&ts->hw_client->dev, + "SW Reset 1 failed: may not recover\n"); + + ret = regmap_write(ts->regmap, ts->hw_client->addr, + NT36XXX_CMD_SW_RESET); + if (ret) + dev_dbg(&ts->hw_client->dev, + "SW Reset 2 failed: may not recover\n"); + usleep_range(1000, 1100); + + /* Clear CRC_ERR_FLAG */ + ret = nt36xxx_set_page(ts, NT36XXX_PAGE_CRC); + if (ret) + continue; + + val = 0xA5; + ret = regmap_raw_write(ts->fw_regmap, NT36XXX_EVT_CRC, + &val, sizeof(val)); + if (ret) + continue; + + /* Check CRC_ERR_FLAG */ + ret = nt36xxx_set_page(ts, NT36XXX_PAGE_CRC); + if (ret) + continue; + + ret = regmap_noinc_read(ts->fw_regmap, NT36XXX_EVT_CRC, + &buf, sizeof(buf)); + if (ret) + continue; + + if (buf[0] == 0xA5) + break; + } while (--retry); + + if (retry == 0) { + dev_err(&ts->hw_client->dev, + "CRC reset failed: buf=0x%2ph\n", buf); + } + + return ret; +} + +/** + * nt36xxx_i2c_chip_version_init - Detect Novatek NT36xxx family IC + * @ts: Main driver structure + * + * This function reads the ChipID from the IC and sets the right + * memory map for the detected chip. + * + * Return: Always zero for success, negative number for error + */ +static int nt36xxx_i2c_chip_version_init(struct nt36xxx_i2c *ts) +{ + u8 buf[7] = { 0 }; + int retry = NT36XXX_MAX_RETRIES; + int sz = sizeof(trim_id_table) / sizeof(struct nt36xxx_trim_table); + int i, list, mapid, ret; + + ret = nt36xxx_bootloader_reset(ts); + if (ret) { + dev_err(&ts->hw_client->dev, "Can't reset the nvt IC\n"); + return ret; + } + + do { + ret = nt36xxx_sw_reset_idle(ts); + if (ret) + continue; + + ret = regmap_write(ts->regmap, ts->hw_client->addr, NT36XXX_CMD_UNLOCK); + if (ret) + continue; + usleep_range(10000, 11000); + + ret = nt36xxx_set_page(ts, NT36XXX_PAGE_CHIP_INFO); + if (ret) + continue; + + memset(buf, 0, ARRAY_SIZE(buf)); + ret = regmap_noinc_read(ts->fw_regmap, NT36XXX_EVT_CHIPID, + buf, sizeof(buf)); + if (ret) + continue; + + /* Compare read chip id with trim list */ + for (list = 0; list < sz; list++) { + /* Compare each not masked byte */ + for (i = 0; i < NT36XXX_ID_LEN_MAX; i++) { + if (trim_id_table[list].mask[i] && + buf[i] != trim_id_table[list].id[i]) + break; + } + + if (i == NT36XXX_ID_LEN_MAX) { + mapid = trim_id_table[list].mapid; + ts->mmap = &nt36xxx_memory_maps[mapid]; + return 0; + } + + ts->mmap = NULL; + ret = -ENOENT; + } + + /* Stop CRC check to prevent IC auto reboot */ + if (nt36xxx_in_crc_reboot_loop(buf)) { + ret = nt36xxx_stop_crc_reboot(ts); + if (ret) + continue; + } + + usleep_range(10000, 11000); + } while (--retry); + + return ret; +} + +static const struct regmap_config nt36xxx_i2c_regmap_hw_config = { + .name = "nt36xxx_i2c_hw", + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_NONE, +}; + +static const struct regmap_config nt36xxx_i2c_regmap_fw_config = { + .name = "nt36xxx_i2c_fw", + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_NONE, +}; + +static void nt36xxx_disable_regulators(void *data) +{ + struct nt36xxx_i2c *ts = data; + + regulator_bulk_disable(NT36XXX_NUM_SUPPLIES, ts->supplies); +} + +static int nt36xxx_i2c_probe(struct i2c_client *hw_client, + const struct i2c_device_id *id) +{ + struct nt36xxx_i2c *ts; + struct input_dev *input; + int ret; + + if (!i2c_check_functionality(hw_client->adapter, I2C_FUNC_I2C)) { + dev_err(&hw_client->dev, "i2c_check_functionality error\n"); + return -EIO; + } + + if (!hw_client->irq) { + dev_err(&hw_client->dev, "No irq specified\n"); + return -EINVAL; + } + + ts = devm_kzalloc(&hw_client->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + ts->supplies = devm_kcalloc(&hw_client->dev, + NT36XXX_NUM_SUPPLIES, + sizeof(*ts->supplies), + GFP_KERNEL); + if (!ts->supplies) + return -ENOMEM; + + input = devm_input_allocate_device(&hw_client->dev); + if (!input) + return -ENOMEM; + + ts->fw_client = i2c_new_dummy_device(hw_client->adapter, + NT36XXX_FW_ADDR); + if (IS_ERR(ts->fw_client)) { + dev_err(&hw_client->dev, "Cannot add FW I2C device\n"); + return PTR_ERR(ts->fw_client); + } + + ts->hw_client = hw_client; + ts->input = input; + i2c_set_clientdata(ts->hw_client, ts); + i2c_set_clientdata(ts->fw_client, ts); + + ts->reset_gpio = devm_gpiod_get_optional(&hw_client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) + return PTR_ERR(ts->reset_gpio); + gpiod_set_consumer_name(ts->reset_gpio, "nt36xxx reset"); + + /* These supplies are optional */ + ts->supplies[0].supply = "vdd"; + ts->supplies[1].supply = "vio"; + ret = devm_regulator_bulk_get(&hw_client->dev, + NT36XXX_NUM_SUPPLIES, + ts->supplies); + if (ret) + return dev_err_probe(&hw_client->dev, ret, + "Cannot get supplies: %d\n", ret); + + ts->regmap = devm_regmap_init_i2c(ts->hw_client, + &nt36xxx_i2c_regmap_hw_config); + if (IS_ERR(ts->regmap)) { + dev_err(&hw_client->dev, "regmap (hw-addr) init failed\n"); + return PTR_ERR(ts->regmap); + } + + ts->fw_regmap = devm_regmap_init_i2c(ts->fw_client, + &nt36xxx_i2c_regmap_fw_config); + if (IS_ERR(ts->fw_regmap)) { + dev_err(&hw_client->dev, "regmap (fw-addr) init failed\n"); + return PTR_ERR(ts->fw_regmap); + } + + ret = regulator_bulk_enable(NT36XXX_NUM_SUPPLIES, ts->supplies); + if (ret) + return ret; + + usleep_range(10000, 11000); + + ret = devm_add_action_or_reset(&hw_client->dev, + nt36xxx_disable_regulators, ts); + if (ret) + return ret; + + mutex_init(&ts->lock); + + /* Set memory maps for the specific chip version */ + ret = nt36xxx_i2c_chip_version_init(ts); + if (ret) { + dev_err(&hw_client->dev, "Failed to check chip version\n"); + return ret; + } + + /* Reset the MCU */ + ret = nt36xxx_bootloader_reset(ts); + if (ret < 0) + return ret; + + /* Check and eventually wait until the MCU goes in reset state */ + ret = nt36xxx_check_reset_state(ts, NT36XXX_STATE_INIT); + if (ret < 0) + return ret; + + /* Get informations from the TS firmware */ + ret = nt36xxx_get_fw_info(ts); + if (ret < 0) + return ret; + + input->phys = devm_kasprintf(&hw_client->dev, GFP_KERNEL, + "%s/input0", dev_name(&hw_client->dev)); + if (!input->phys) + return -ENOMEM; + + input->name = "Novatek NT36XXX Touchscreen"; + input->id.bustype = BUS_I2C; + input->dev.parent = &hw_client->dev; + + __set_bit(EV_KEY, input->evbit); + __set_bit(EV_ABS, input->evbit); + input_set_capability(input, EV_KEY, BTN_TOUCH); + + ret = input_mt_init_slots(input, TOUCH_MAX_FINGER_NUM, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (ret) { + dev_err(&hw_client->dev, "Cannot init MT slots (%d)\n", ret); + return ret; + } + + input_set_abs_params(input, ABS_MT_PRESSURE, 0, + TOUCH_MAX_PRESSURE, 0, 0); + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + + input_set_abs_params(input, ABS_MT_POSITION_X, 0, + ts->fw_info.abs_x_max - 1, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, + ts->fw_info.abs_y_max - 1, 0, 0); + + /* Override the firmware defaults, if needed */ + touchscreen_parse_properties(input, true, &ts->prop); + + input_set_drvdata(input, ts); + + ret = input_register_device(ts->input); + if (ret) { + dev_err(&hw_client->dev, "Failed to register input device: %d\n", + ret); + return ret; + } + + ret = devm_request_threaded_irq(&hw_client->dev, hw_client->irq, NULL, + nt36xxx_i2c_irq_handler, IRQF_ONESHOT, + hw_client->name, ts); + if (ret) { + dev_err(&hw_client->dev, "request irq failed: %d\n", ret); + return ret; + } + + return ret; +} + +static int __maybe_unused nt36xxx_i2c_suspend(struct device *dev) +{ + struct nt36xxx_i2c *ts = i2c_get_clientdata(to_i2c_client(dev)); + int ret; + + disable_irq(ts->hw_client->irq); + + ret = regmap_write(ts->fw_regmap, NT36XXX_EVT_HOST_CMD, + NT36XXX_CMD_ENTER_SLEEP); + if (ret) { + dev_err(&ts->hw_client->dev, "Cannot enter suspend!!\n"); + return ret; + } + + gpiod_set_value(ts->reset_gpio, 1); + + return 0; +} + +static int __maybe_unused nt36xxx_i2c_resume(struct device *dev) +{ + struct nt36xxx_i2c *ts = i2c_get_clientdata(to_i2c_client(dev)); + int ret; + + mutex_lock(&ts->lock); + + gpiod_set_value(ts->reset_gpio, 0); + + /* Reboot the MCU (also recalibrates the TS) */ + ret = nt36xxx_bootloader_reset(ts); + if (ret < 0) + goto end; + + ret = nt36xxx_check_reset_state(ts, NT36XXX_STATE_REK); + if (ret < 0) + goto end; + + enable_irq(ts->hw_client->irq); +end: + mutex_unlock(&ts->lock); + return ret; +} + +static SIMPLE_DEV_PM_OPS(nt36xxx_i2c_pm, + nt36xxx_i2c_suspend, nt36xxx_i2c_resume); + +static const struct of_device_id nt36xxx_of_match[] = { + { .compatible = "novatek,nt36525" }, + { } +}; +MODULE_DEVICE_TABLE(of, nt36xxx_of_match); + +static const struct i2c_device_id nt36xxx_i2c_ts_id[] = { + { "NVT-ts", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nt36xxx_i2c_ts_id); + +static struct i2c_driver nt36xxx_i2c_ts_driver = { + .driver = { + .name = "nt36xxx_ts", + .pm = &nt36xxx_i2c_pm, + .of_match_table = nt36xxx_of_match, + }, + .id_table = nt36xxx_i2c_ts_id, + .probe = nt36xxx_i2c_probe, +}; +module_i2c_driver(nt36xxx_i2c_ts_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Novatek NT36XXX Touchscreen Driver"); +MODULE_AUTHOR("AngeloGioacchino Del Regno "); diff --git a/drivers/input/touchscreen/nt36xxx.h b/drivers/input/touchscreen/nt36xxx.h new file mode 100644 index 000000000000..6f03dfb45656 --- /dev/null +++ b/drivers/input/touchscreen/nt36xxx.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2020 AngeloGioacchino Del Regno + */ + +#ifndef NT36XXX_H +#define NT36XXX_H + +#define NT36XXX_INPUT_DEVICE_NAME "Novatek NT36XXX Touch Sensor" + +/* These chips have this fixed address when in bootloader :( */ +#define NT36XXX_BLDR_ADDR 0x01 + +/* Input device info */ +#define NVT_TS_NAME "NVTCapacitiveTouchScreen" + +/* Number of bytes for chip identification */ +#define NT36XXX_ID_LEN_MAX 6 + +/* Touch info */ +#define TOUCH_DEFAULT_MAX_WIDTH 1080 +#define TOUCH_DEFAULT_MAX_HEIGHT 2246 +#define TOUCH_MAX_FINGER_NUM 10 +#define TOUCH_MAX_PRESSURE 1000 + +/* Point data length */ +#define POINT_DATA_LEN 65 + +/* Global pages */ +#define NT36XXX_PAGE_CHIP_INFO 0x0001f64e +#define NT36XXX_PAGE_CRC 0x0003f135 + +/* Misc */ +#define NT36XXX_NUM_SUPPLIES 2 +#define NT36XXX_MAX_RETRIES 5 +#define NT36XXX_MAX_FW_RST_RETRY 50 + +struct nt36xxx_abs_object { + u16 x; + u16 y; + u16 z; + u8 tm; +}; + +struct nt36xxx_fw_info { + u8 fw_ver; + u8 x_num; + u8 y_num; + u8 max_buttons; + u16 abs_x_max; + u16 abs_y_max; + u16 nvt_pid; +}; + +struct nt36xxx_mem_map { + u32 evtbuf_addr; + u32 pipe0_addr; + u32 pipe1_addr; + u32 flash_csum_addr; + u32 flash_data_addr; +}; + +struct nt36xxx_i2c { + struct i2c_client *client; + struct input_dev *input; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; + + struct work_struct ts_work; + struct workqueue_struct *ts_workq; + struct mutex lock; + + struct nt36xxx_fw_info fw_info; + struct nt36xxx_abs_object abs_obj; + + const struct nt36xxx_mem_map *mmap; + u8 max_fingers; +}; + +enum nt36xxx_chips { + NT36525_IC = 0, + NT36672A_IC, + NT36676F_IC, + NT36772_IC, + NT36870_IC, + NTMAX_IC, +}; + +struct nt36xxx_trim_table { + u8 id[NT36XXX_ID_LEN_MAX]; + u8 mask[NT36XXX_ID_LEN_MAX]; + enum nt36xxx_chips mapid; +}; + +enum nt36xxx_cmds { + NT36XXX_CMD_ENTER_SLEEP = 0x11, + NT36XXX_CMD_ENTER_WKUP_GESTURE = 0x13, + NT36XXX_CMD_UNLOCK = 0x35, + NT36XXX_CMD_BOOTLOADER_RESET = 0x69, + NT36XXX_CMD_SW_RESET = 0xa5, + NT36XXX_CMD_SET_PAGE = 0xff, +}; + +enum nt36xxx_fw_state { + NT36XXX_STATE_INIT = 0xa0, /* IC reset */ + NT36XXX_STATE_REK, /* ReK baseline */ + NT36XXX_STATE_REK_FINISH, /* Baseline is ready */ + NT36XXX_STATE_NORMAL_RUN, /* Normal run */ + NT36XXX_STATE_MAX = 0xaf +}; + +enum nt36xxx_i2c_events { + NT36XXX_EVT_CHIPID = 0x4e, + NT36XXX_EVT_HOST_CMD = 0x50, + NT36XXX_EVT_HS_OR_SUBCMD = 0x51, /* Handshake or subcommand byte */ + NT36XXX_EVT_RESET_COMPLETE = 0x60, + NT36XXX_EVT_FWINFO = 0x78, + NT36XXX_EVT_PROJECTID = 0x9a, +}; + +#endif From patchwork Wed Oct 28 22:13:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 11863509 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8D2E214B2 for ; Wed, 28 Oct 2020 22:13:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 664C22473C for ; Wed, 28 Oct 2020 22:13:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DlatPnFt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731009AbgJ1WNO (ORCPT ); Wed, 28 Oct 2020 18:13:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731022AbgJ1WNM (ORCPT ); Wed, 28 Oct 2020 18:13:12 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B9AEC0613D3; Wed, 28 Oct 2020 15:13:11 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id t3so696048wmi.3; Wed, 28 Oct 2020 15:13:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UQeIb9S6fRyX5SRt2bDKlf1jyr9GKEnfhYagOSnTM3M=; b=DlatPnFtHJrfJ07LWvkl9+nsvhNwx+orArQF7h6O2RJSm7XI44ONw8VlqpEbhEMT0M 6Wq+lpKTWAVNnf7Bj6QMm1J/33sTXoUaLeLhmbMqoNRmXrXlGS8iS62Zhr8V0yGDz2lQ w5VsN4sMlVmScHmpj1XKy7YYFiOT3e34th+9xIPx6uCF0PnG8p1xHTmebu8w7m/KJ4CV 2O9N57kTqJSw4K8GnZWP9cl42YR+TfjNF9TBsKK/FUdBMcRZr6dm4yKRE+kDUTnTryHI 9odrtv/iBcPWIsh3jxWrbNifLAJaS7QnsvFjNkQ1bC2vGLjTbmyiWlQCBlG30xLIe/Ym Ti6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UQeIb9S6fRyX5SRt2bDKlf1jyr9GKEnfhYagOSnTM3M=; b=F6pmHbrM6IpkHC2rMjuecC+Iw8R1+s/Eg/y74iNIhgYxM6PADIvrus+ABecjiQxUvo RrtfmhoMCuAJ+dbemEgf3DiSl4wc9+QqZF4vRoP1i+PGtjv5y+OTnS4M/rx6ppnRppje J0Ei+DA0ZGl2/zigQ9PiPuR1JPymQ3pY/KKm+bLtjPYw+FF4B0zRNb2A2coQxU3wqPON 1Nj0H/KvqA5trTk4i3qzIa6lS5LfVoNLot3kJ9HTVDJEQW0w+p4lc7VlTQENw9n/1UiH YoDnb8Fe3PAFWqj7P3tO4QAAXNPpuV2g+9/hF2iqzW/7VnqQvXOqqVuohtoyOe1Y0nQQ DpVQ== X-Gm-Message-State: AOAM533Y1WwtY+VENDz66MrlvUt5uxQ4QG5piKvtnI6nrap7OCKfRVWA KKlzgTC8OW0eSDtwyt1R2Pqt3HzM63OiR6s/ X-Google-Smtp-Source: ABdhPJxdhm6P6d9+9M90lpfBiEoEfY8zosAdgCLm46HLBQ5WD9A+r5LCSE+7/tfvSXPlOzLo2ml11g== X-Received: by 2002:a1c:740e:: with SMTP id p14mr1044002wmc.34.1603923190036; Wed, 28 Oct 2020 15:13:10 -0700 (PDT) Received: from IcarusMOD.eternityproject.eu ([2.237.20.237]) by smtp.gmail.com with ESMTPSA id x1sm1318928wrl.41.2020.10.28.15.13.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2020 15:13:09 -0700 (PDT) From: kholk11@gmail.com To: dmitry.torokhov@gmail.com Cc: robh+dt@kernel.org, rydberg@bitmath.org, priv.luk@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kholk11@gmail.com, marijns95@gmail.com, konradybcio@gmail.com, martin.botka1@gmail.com, phone-devel@vger.kernel.org, devicetree@vger.kernel.org, krzk@kernel.org, andy.shevchenko@gmail.com, Rob Herring Subject: [PATCH v9 3/3] dt-bindings: touchscreen: Add binding for Novatek NT36xxx series driver Date: Wed, 28 Oct 2020 23:13:02 +0100 Message-Id: <20201028221302.66583-4-kholk11@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201028221302.66583-1-kholk11@gmail.com> References: <20201028221302.66583-1-kholk11@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: AngeloGioacchino Del Regno Add binding for the Novatek NT36xxx series touchscreen driver. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Krzysztof Kozlowski Reviewed-by: Rob Herring --- .../bindings/input/touchscreen/nt36xxx.yaml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/nt36xxx.yaml diff --git a/Documentation/devicetree/bindings/input/touchscreen/nt36xxx.yaml b/Documentation/devicetree/bindings/input/touchscreen/nt36xxx.yaml new file mode 100644 index 000000000000..a360a9f5d43b --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/nt36xxx.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/touchscreen/nt36xxx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Novatek NT36xxx series touchscreen controller Bindings + +maintainers: + - AngeloGioacchino Del Regno + +allOf: + - $ref: touchscreen.yaml# + +properties: + compatible: + const: novatek,nt36525 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + reset-gpios: + maxItems: 1 + + vdd-supply: + description: Power supply regulator for VDD pin + + vio-supply: + description: Power supply regulator on VDD-IO pin + +unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + touchscreen@62 { + compatible = "novatek,nt36525"; + reg = <0x62>; + interrupt-parent = <&tlmm>; + interrupts = <45 IRQ_TYPE_EDGE_RISING>; + reset-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>; + }; + }; + +...