^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2012-2017 Hideep, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/input/touchscreen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define HIDEEP_TS_NAME "HiDeep Touchscreen"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define HIDEEP_I2C_NAME "hideep_ts"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define HIDEEP_MT_MAX 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define HIDEEP_KEY_MAX 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* count(2) + touch data(100) + key data(6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define HIDEEP_MAX_EVENT 108UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define HIDEEP_TOUCH_EVENT_INDEX 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define HIDEEP_KEY_EVENT_INDEX 102
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Touch & key event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define HIDEEP_EVENT_ADDR 0x240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* command list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define HIDEEP_RESET_CMD 0x9800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* event bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define HIDEEP_MT_RELEASED BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define HIDEEP_KEY_PRESSED BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define HIDEEP_KEY_FIRST_PRESSED BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define HIDEEP_KEY_PRESSED_MASK (HIDEEP_KEY_PRESSED | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) HIDEEP_KEY_FIRST_PRESSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define HIDEEP_KEY_IDX_MASK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* For NVM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define HIDEEP_YRAM_BASE 0x40000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define HIDEEP_PERIPHERAL_BASE 0x50000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define HIDEEP_ESI_BASE (HIDEEP_PERIPHERAL_BASE + 0x00000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define HIDEEP_FLASH_BASE (HIDEEP_PERIPHERAL_BASE + 0x01000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define HIDEEP_SYSCON_BASE (HIDEEP_PERIPHERAL_BASE + 0x02000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define HIDEEP_SYSCON_MOD_CON (HIDEEP_SYSCON_BASE + 0x0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define HIDEEP_SYSCON_SPC_CON (HIDEEP_SYSCON_BASE + 0x0004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define HIDEEP_SYSCON_CLK_CON (HIDEEP_SYSCON_BASE + 0x0008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define HIDEEP_SYSCON_CLK_ENA (HIDEEP_SYSCON_BASE + 0x000C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define HIDEEP_SYSCON_RST_CON (HIDEEP_SYSCON_BASE + 0x0010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define HIDEEP_SYSCON_WDT_CON (HIDEEP_SYSCON_BASE + 0x0014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define HIDEEP_SYSCON_WDT_CNT (HIDEEP_SYSCON_BASE + 0x0018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define HIDEEP_SYSCON_PWR_CON (HIDEEP_SYSCON_BASE + 0x0020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define HIDEEP_SYSCON_PGM_ID (HIDEEP_SYSCON_BASE + 0x00F4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define HIDEEP_FLASH_CON (HIDEEP_FLASH_BASE + 0x0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define HIDEEP_FLASH_STA (HIDEEP_FLASH_BASE + 0x0004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define HIDEEP_FLASH_CFG (HIDEEP_FLASH_BASE + 0x0008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define HIDEEP_FLASH_TIM (HIDEEP_FLASH_BASE + 0x000C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define HIDEEP_FLASH_CACHE_CFG (HIDEEP_FLASH_BASE + 0x0010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define HIDEEP_FLASH_PIO_SIG (HIDEEP_FLASH_BASE + 0x400000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define HIDEEP_ESI_TX_INVALID (HIDEEP_ESI_BASE + 0x0008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define HIDEEP_PERASE 0x00040000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define HIDEEP_WRONLY 0x00100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define HIDEEP_NVM_MASK_OFS 0x0000000C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define HIDEEP_NVM_DEFAULT_PAGE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define HIDEEP_NVM_SFR_WPAGE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define HIDEEP_NVM_SFR_RPAGE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define HIDEEP_PIO_SIG 0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define HIDEEP_PROT_MODE 0x03400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define HIDEEP_NVM_PAGE_SIZE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define HIDEEP_DWZ_INFO 0x000002C0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct hideep_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) __le16 x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) __le16 y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __le16 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u8 w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u8 flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct dwz_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) __be32 code_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 code_crc[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) __be32 c_code_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __be16 gen_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __be16 c_code_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __be32 vr_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) __be16 rsv0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) __be16 vr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __be32 ft_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) __be16 vr_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) __be16 ft_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) __be16 core_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __be16 boot_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) __be16 release_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) __be16 custom_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u8 factory_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u8 panel_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u8 model_name[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) __be16 extra_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) __be16 product_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) __be16 vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) __be16 product_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct pgm_packet {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u8 unused[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) __be32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) __be32 payload[HIDEEP_NVM_PAGE_SIZE / sizeof(__be32)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define HIDEEP_XFER_BUF_SIZE sizeof(struct pgm_packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct hideep_ts {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct regmap *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct touchscreen_properties prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct regulator *vcc_vdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct regulator *vcc_vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct mutex dev_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u32 tch_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u32 lpm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Data buffer to read packet from the device (contacts and key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * states). We align it on double-word boundary to keep word-sized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * fields in contact data and double-word-sized fields in program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * packet aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u8 xfer_buf[HIDEEP_XFER_BUF_SIZE] __aligned(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int key_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u32 key_codes[HIDEEP_KEY_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct dwz_info dwz_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned int fw_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u32 nvm_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int hideep_pgm_w_mem(struct hideep_ts *ts, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) const __be32 *data, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct pgm_packet *packet = (void *)ts->xfer_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) size_t len = count * sizeof(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .addr = ts->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .len = len + sizeof(packet->header.len) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) sizeof(packet->header.addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .buf = &packet->header.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (len > HIDEEP_NVM_PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) packet->header.len = 0x80 | (count - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) packet->header.addr = cpu_to_be32(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) memcpy(packet->payload, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) ret = i2c_transfer(ts->client->adapter, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return ret < 0 ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int hideep_pgm_r_mem(struct hideep_ts *ts, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) __be32 *data, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct pgm_packet *packet = (void *)ts->xfer_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) size_t len = count * sizeof(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .addr = ts->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .len = sizeof(packet->header.len) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sizeof(packet->header.addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .buf = &packet->header.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .addr = ts->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .len = len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .buf = (u8 *)data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (len > HIDEEP_NVM_PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) packet->header.len = count - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) packet->header.addr = cpu_to_be32(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret != ARRAY_SIZE(msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return ret < 0 ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static int hideep_pgm_r_reg(struct hideep_ts *ts, u32 addr, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) __be32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) error = hideep_pgm_r_mem(ts, addr, &data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) "read of register %#08x failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) addr, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *val = be32_to_cpu(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static int hideep_pgm_w_reg(struct hideep_ts *ts, u32 addr, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) __be32 data = cpu_to_be32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) error = hideep_pgm_w_mem(ts, addr, &data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) "write to register %#08x (%#08x) failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) addr, val, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define SW_RESET_IN_PGM(clk) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CNT, (clk)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, 0x03); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, 0x01); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #define SET_FLASH_PIO(ce) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CON, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 0x01 | ((ce) << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #define SET_PIO_SIG(x, y) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) hideep_pgm_w_reg(ts, HIDEEP_FLASH_PIO_SIG + (x), (y))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define SET_FLASH_HWCONTROL() \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CON, 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #define NVM_W_SFR(x, y) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) SET_FLASH_PIO(1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) SET_PIO_SIG(x, y); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) SET_FLASH_PIO(0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static void hideep_pgm_set(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_SPC_CON, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_CLK_ENA, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_CLK_CON, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) hideep_pgm_w_reg(ts, HIDEEP_SYSCON_PWR_CON, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) hideep_pgm_w_reg(ts, HIDEEP_FLASH_TIM, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CACHE_CFG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static int hideep_pgm_get_pattern(struct hideep_ts *ts, u32 *pattern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u16 p1 = 0xAF39;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) u16 p2 = 0xDF9D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) error = regmap_bulk_write(ts->reg, p1, &p2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) "%s: regmap_bulk_write() failed with %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) __func__, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) usleep_range(1000, 1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* flush invalid Tx load register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) error = hideep_pgm_w_reg(ts, HIDEEP_ESI_TX_INVALID, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) error = hideep_pgm_r_reg(ts, HIDEEP_SYSCON_PGM_ID, pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int hideep_enter_pgm(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int retry_count = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) u32 pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) while (retry_count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) error = hideep_pgm_get_pattern(ts, &pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "hideep_pgm_get_pattern failed: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) } else if (pattern != 0x39AF9DDF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dev_err(&ts->client->dev, "%s: bad pattern: %#08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) __func__, pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_dbg(&ts->client->dev, "found magic code");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) hideep_pgm_set(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) usleep_range(1000, 1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) dev_err(&ts->client->dev, "failed to enter pgm mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) SW_RESET_IN_PGM(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int hideep_nvm_unlock(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) u32 unmask_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* make it unprotected code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) unmask_code &= ~HIDEEP_PROT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* compare unmask code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (unmask_code != ts->nvm_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) dev_warn(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) "read mask code different %#08x vs %#08x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) unmask_code, ts->nvm_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_WPAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) SET_FLASH_PIO(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) SET_FLASH_HWCONTROL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int hideep_check_status(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int time_out = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) while (time_out--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) error = hideep_pgm_r_reg(ts, HIDEEP_FLASH_STA, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!error && status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) usleep_range(1000, 1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int hideep_program_page(struct hideep_ts *ts, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) const __be32 *ucode, size_t xfer_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) error = hideep_check_status(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) addr &= ~(HIDEEP_NVM_PAGE_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) SET_FLASH_PIO(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) SET_FLASH_PIO(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* erase page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) SET_PIO_SIG(HIDEEP_PERASE | addr, 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) SET_FLASH_PIO(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) error = hideep_check_status(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* write page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) SET_FLASH_PIO(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) val = be32_to_cpu(ucode[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) SET_PIO_SIG(HIDEEP_WRONLY | addr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) hideep_pgm_w_mem(ts, HIDEEP_FLASH_PIO_SIG | HIDEEP_WRONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ucode, xfer_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) val = be32_to_cpu(ucode[xfer_count - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) SET_PIO_SIG(124, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) SET_FLASH_PIO(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) usleep_range(1000, 1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) error = hideep_check_status(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) SET_FLASH_HWCONTROL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int hideep_program_nvm(struct hideep_ts *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) const __be32 *ucode, size_t ucode_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct pgm_packet *packet_r = (void *)ts->xfer_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) __be32 *current_ucode = packet_r->payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) size_t xfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) size_t xfer_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) u32 addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) error = hideep_nvm_unlock(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) while (ucode_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) xfer_count = xfer_len / sizeof(*ucode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) error = hideep_pgm_r_mem(ts, 0x00000000 + addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) current_ucode, xfer_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) "%s: failed to read page at offset %#08x: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) __func__, addr, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* See if the page needs updating */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (memcmp(ucode, current_ucode, xfer_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) error = hideep_program_page(ts, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ucode, xfer_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) "%s: iwrite failure @%#08x: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) __func__, addr, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) usleep_range(1000, 1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ucode += xfer_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) addr += xfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ucode_len -= xfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static int hideep_verify_nvm(struct hideep_ts *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) const __be32 *ucode, size_t ucode_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct pgm_packet *packet_r = (void *)ts->xfer_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) __be32 *current_ucode = packet_r->payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) size_t xfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) size_t xfer_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) u32 addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) while (ucode_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) xfer_count = xfer_len / sizeof(*ucode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) error = hideep_pgm_r_mem(ts, 0x00000000 + addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) current_ucode, xfer_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) "%s: failed to read page at offset %#08x: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) __func__, addr, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (memcmp(ucode, current_ucode, xfer_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) const u8 *ucode_bytes = (const u8 *)ucode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) const u8 *current_bytes = (const u8 *)current_ucode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) for (i = 0; i < xfer_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (ucode_bytes[i] != current_bytes[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) "%s: mismatch @%#08x: (%#02x vs %#02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) __func__, addr + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ucode_bytes[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) current_bytes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ucode += xfer_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) addr += xfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ucode_len -= xfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static int hideep_load_dwz(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) u16 product_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) error = hideep_enter_pgm(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) error = hideep_pgm_r_mem(ts, HIDEEP_DWZ_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) (void *)&ts->dwz_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) sizeof(ts->dwz_info) / sizeof(__be32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) SW_RESET_IN_PGM(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) "failed to fetch DWZ data: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) product_code = be16_to_cpu(ts->dwz_info.product_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) switch (product_code & 0xF0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case 0x40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) dev_dbg(&ts->client->dev, "used crimson IC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ts->fw_size = 1024 * 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ts->nvm_mask = 0x00310000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) case 0x60:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) dev_dbg(&ts->client->dev, "used lime IC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) ts->fw_size = 1024 * 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) ts->nvm_mask = 0x0030027B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dev_err(&ts->client->dev, "product code is wrong: %#04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) product_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) dev_dbg(&ts->client->dev, "firmware release version: %#04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) be16_to_cpu(ts->dwz_info.release_ver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int hideep_flash_firmware(struct hideep_ts *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) const __be32 *ucode, size_t ucode_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int retry_cnt = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) while (retry_cnt--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) error = hideep_program_nvm(ts, ucode, ucode_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (!error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) error = hideep_verify_nvm(ts, ucode, ucode_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static int hideep_update_firmware(struct hideep_ts *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) const __be32 *ucode, size_t ucode_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int error, error2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) dev_dbg(&ts->client->dev, "starting firmware update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* enter program mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) error = hideep_enter_pgm(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) error = hideep_flash_firmware(ts, ucode, ucode_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) "firmware update failed: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dev_dbg(&ts->client->dev, "firmware updated successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) SW_RESET_IN_PGM(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) error2 = hideep_load_dwz(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (error2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) "failed to load dwz after firmware update: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) error2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return error ?: error2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static int hideep_power_on(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) error = regulator_enable(ts->vcc_vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) "failed to enable 'vdd' regulator: %d", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) usleep_range(999, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) error = regulator_enable(ts->vcc_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) "failed to enable 'vcc_vid' regulator: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) msleep(30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (ts->reset_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) gpiod_set_value_cansleep(ts->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) error = regmap_write(ts->reg, HIDEEP_RESET_CMD, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dev_err(&ts->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) "failed to send 'reset' command: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static void hideep_power_off(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct hideep_ts *ts = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (ts->reset_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) gpiod_set_value(ts->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) regulator_disable(ts->vcc_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) regulator_disable(ts->vcc_vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) #define __GET_MT_TOOL_TYPE(type) ((type) == 0x01 ? MT_TOOL_FINGER : MT_TOOL_PEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static void hideep_report_slot(struct input_dev *input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) const struct hideep_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) input_mt_slot(input, event->index & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) input_mt_report_slot_state(input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) __GET_MT_TOOL_TYPE(event->type),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) !(event->flag & HIDEEP_MT_RELEASED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!(event->flag & HIDEEP_MT_RELEASED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) input_report_abs(input, ABS_MT_POSITION_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) le16_to_cpup(&event->x));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) input_report_abs(input, ABS_MT_POSITION_Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) le16_to_cpup(&event->y));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) input_report_abs(input, ABS_MT_PRESSURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) le16_to_cpup(&event->z));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) input_report_abs(input, ABS_MT_TOUCH_MAJOR, event->w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static void hideep_parse_and_report(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) const struct hideep_event *events =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) (void *)&ts->xfer_buf[HIDEEP_TOUCH_EVENT_INDEX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) const u8 *keys = &ts->xfer_buf[HIDEEP_KEY_EVENT_INDEX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int touch_count = ts->xfer_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int key_count = ts->xfer_buf[1] & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) int lpm_count = ts->xfer_buf[1] & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* get touch event count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) dev_dbg(&ts->client->dev, "mt = %d, key = %d, lpm = %02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) touch_count, key_count, lpm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) touch_count = min(touch_count, HIDEEP_MT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) for (i = 0; i < touch_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) hideep_report_slot(ts->input_dev, events + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) key_count = min(key_count, HIDEEP_KEY_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) for (i = 0; i < key_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) u8 key_data = keys[i * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) input_report_key(ts->input_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) ts->key_codes[key_data & HIDEEP_KEY_IDX_MASK],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) key_data & HIDEEP_KEY_PRESSED_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) input_mt_sync_frame(ts->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) input_sync(ts->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static irqreturn_t hideep_irq(int irq, void *handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct hideep_ts *ts = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) BUILD_BUG_ON(HIDEEP_MAX_EVENT > HIDEEP_XFER_BUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) error = regmap_bulk_read(ts->reg, HIDEEP_EVENT_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ts->xfer_buf, HIDEEP_MAX_EVENT / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dev_err(&ts->client->dev, "failed to read events: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) hideep_parse_and_report(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int hideep_get_axis_info(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) __le16 val[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) error = regmap_bulk_read(ts->reg, 0x28, val, ARRAY_SIZE(val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ts->prop.max_x = le16_to_cpup(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) ts->prop.max_y = le16_to_cpup(val + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) dev_dbg(&ts->client->dev, "X: %d, Y: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) ts->prop.max_x, ts->prop.max_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int hideep_init_input(struct hideep_ts *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct device *dev = &ts->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) ts->input_dev = devm_input_allocate_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (!ts->input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) dev_err(dev, "failed to allocate input device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) ts->input_dev->name = HIDEEP_TS_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) ts->input_dev->id.bustype = BUS_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) input_set_drvdata(ts->input_dev, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 65535, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) input_set_abs_params(ts->input_dev, ABS_MT_TOOL_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 0, MT_TOOL_MAX, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) touchscreen_parse_properties(ts->input_dev, true, &ts->prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (ts->prop.max_x == 0 || ts->prop.max_y == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) error = hideep_get_axis_info(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) error = input_mt_init_slots(ts->input_dev, HIDEEP_MT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) INPUT_MT_DIRECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ts->key_num = device_property_count_u32(dev, "linux,keycodes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (ts->key_num > HIDEEP_KEY_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dev_err(dev, "too many keys defined: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ts->key_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (ts->key_num <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) dev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) "missing or malformed 'linux,keycodes' property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) error = device_property_read_u32_array(dev, "linux,keycodes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ts->key_codes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) ts->key_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dev_dbg(dev, "failed to read keymap: %d", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (ts->key_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) ts->input_dev->keycode = ts->key_codes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ts->input_dev->keycodesize = sizeof(ts->key_codes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ts->input_dev->keycodemax = ts->key_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) for (i = 0; i < ts->key_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) input_set_capability(ts->input_dev, EV_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) ts->key_codes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) error = input_register_device(ts->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) dev_err(dev, "failed to register input device: %d", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static ssize_t hideep_update_fw(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct hideep_ts *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) const struct firmware *fw_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) char *fw_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) error = kstrtoint(buf, 0, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) fw_name = kasprintf(GFP_KERNEL, "hideep_ts_%04x.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) be16_to_cpu(ts->dwz_info.product_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (!fw_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) error = request_firmware(&fw_entry, fw_name, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) dev_err(dev, "failed to request firmware %s: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) fw_name, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) goto out_free_fw_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (fw_entry->size % sizeof(__be32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dev_err(dev, "invalid firmware size %zu\n", fw_entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) goto out_release_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (fw_entry->size > ts->fw_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev_err(dev, "fw size (%zu) is too big (memory size %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) fw_entry->size, ts->fw_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) error = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) goto out_release_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mutex_lock(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) disable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) error = hideep_update_firmware(ts, (const __be32 *)fw_entry->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) fw_entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) enable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) mutex_unlock(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) out_release_fw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) release_firmware(fw_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) out_free_fw_name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) kfree(fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return error ?: count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static ssize_t hideep_fw_version_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct hideep_ts *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) mutex_lock(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) len = scnprintf(buf, PAGE_SIZE, "%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) be16_to_cpu(ts->dwz_info.release_ver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) mutex_unlock(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static ssize_t hideep_product_id_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct hideep_ts *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) mutex_lock(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) len = scnprintf(buf, PAGE_SIZE, "%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) be16_to_cpu(ts->dwz_info.product_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) mutex_unlock(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static DEVICE_ATTR(version, 0664, hideep_fw_version_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static DEVICE_ATTR(product_id, 0664, hideep_product_id_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static DEVICE_ATTR(update_fw, 0664, NULL, hideep_update_fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static struct attribute *hideep_ts_sysfs_entries[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) &dev_attr_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) &dev_attr_product_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) &dev_attr_update_fw.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static const struct attribute_group hideep_ts_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .attrs = hideep_ts_sysfs_entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) static int __maybe_unused hideep_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct hideep_ts *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) disable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) hideep_power_off(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static int __maybe_unused hideep_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct hideep_ts *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) error = hideep_power_on(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) dev_err(&client->dev, "power on failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) enable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) static SIMPLE_DEV_PM_OPS(hideep_pm_ops, hideep_suspend, hideep_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) static const struct regmap_config hideep_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .reg_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .reg_format_endian = REGMAP_ENDIAN_LITTLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .val_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .val_format_endian = REGMAP_ENDIAN_LITTLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) .max_register = 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static int hideep_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct hideep_ts *ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* check i2c bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) dev_err(&client->dev, "check i2c device error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (client->irq <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) dev_err(&client->dev, "missing irq: %d\n", client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (!ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ts->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) i2c_set_clientdata(client, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) mutex_init(&ts->dev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ts->reg = devm_regmap_init_i2c(client, &hideep_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (IS_ERR(ts->reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) error = PTR_ERR(ts->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) "failed to initialize regmap: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) ts->vcc_vdd = devm_regulator_get(&client->dev, "vdd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (IS_ERR(ts->vcc_vdd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return PTR_ERR(ts->vcc_vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ts->vcc_vid = devm_regulator_get(&client->dev, "vid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (IS_ERR(ts->vcc_vid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return PTR_ERR(ts->vcc_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) "reset", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (IS_ERR(ts->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return PTR_ERR(ts->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) error = hideep_power_on(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) dev_err(&client->dev, "power on failed: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) error = devm_add_action_or_reset(&client->dev, hideep_power_off, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) error = hideep_load_dwz(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) dev_err(&client->dev, "failed to load dwz: %d", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) error = hideep_init_input(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) error = devm_request_threaded_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) NULL, hideep_irq, IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) client->name, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) dev_err(&client->dev, "failed to request irq %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) client->irq, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) error = devm_device_add_group(&client->dev, &hideep_ts_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) "failed to add sysfs attributes: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) static const struct i2c_device_id hideep_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) { HIDEEP_I2C_NAME, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) MODULE_DEVICE_TABLE(i2c, hideep_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) #ifdef CONFIG_ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) static const struct acpi_device_id hideep_acpi_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) { "HIDP0001", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) MODULE_DEVICE_TABLE(acpi, hideep_acpi_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) static const struct of_device_id hideep_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) { .compatible = "hideep,hideep-ts" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) MODULE_DEVICE_TABLE(of, hideep_match_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static struct i2c_driver hideep_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) .name = HIDEEP_I2C_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) .of_match_table = of_match_ptr(hideep_match_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) .acpi_match_table = ACPI_PTR(hideep_acpi_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) .pm = &hideep_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) .id_table = hideep_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) .probe = hideep_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) module_i2c_driver(hideep_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) MODULE_DESCRIPTION("Driver for HiDeep Touchscreen Controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) MODULE_AUTHOR("anthony.kim@hideep.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) MODULE_LICENSE("GPL v2");