Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Goodix "Berlin" Touchscreen IC driver
  4 * Copyright (C) 2020 - 2021 Goodix, Inc.
  5 * Copyright (C) 2023 Linaro Ltd.
  6 *
  7 * Based on goodix_ts_berlin driver.
  8 *
  9 * This driver is distinct from goodix.c since hardware interface
 10 * is different enough to require a new driver.
 11 * None of the register address or data structure are close enough
 12 * to the previous generations.
 13 *
 14 * Currently the driver only handles Multitouch events with already
 15 * programmed firmware and "config" for "Revision D" Berlin IC.
 16 *
 17 * Support is missing for:
 18 * - ESD Management
 19 * - Firmware update/flashing
 20 * - "Config" update/flashing
 21 * - Stylus Events
 22 * - Gesture Events
 23 * - Support for older revisions (A & B)
 24 */
 25
 26#include <linux/bitfield.h>
 27#include <linux/gpio/consumer.h>
 28#include <linux/input.h>
 29#include <linux/input/mt.h>
 30#include <linux/input/touchscreen.h>
 31#include <linux/regmap.h>
 32#include <linux/regulator/consumer.h>
 33#include <linux/sizes.h>
 34#include <linux/unaligned.h>
 35
 36#include "goodix_berlin.h"
 37
 38#define GOODIX_BERLIN_MAX_TOUCH			10
 39
 40#define GOODIX_BERLIN_NORMAL_RESET_DELAY_MS	100
 41
 42#define GOODIX_BERLIN_TOUCH_EVENT		BIT(7)
 43#define GOODIX_BERLIN_REQUEST_EVENT		BIT(6)
 44#define GOODIX_BERLIN_TOUCH_COUNT_MASK		GENMASK(3, 0)
 45
 46#define GOODIX_BERLIN_REQUEST_CODE_RESET	3
 47
 48#define GOODIX_BERLIN_POINT_TYPE_MASK		GENMASK(3, 0)
 49#define GOODIX_BERLIN_POINT_TYPE_STYLUS_HOVER	1
 50#define GOODIX_BERLIN_POINT_TYPE_STYLUS		3
 51
 52#define GOODIX_BERLIN_TOUCH_ID_MASK		GENMASK(7, 4)
 53
 54#define GOODIX_BERLIN_DEV_CONFIRM_VAL		0xAA
 55#define GOODIX_BERLIN_BOOTOPTION_ADDR		0x10000
 56#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR	0x10014
 57
 58#define GOODIX_BERLIN_IC_INFO_MAX_LEN		SZ_1K
 59#define GOODIX_BERLIN_IC_INFO_ADDR		0x10070
 60
 61#define GOODIX_BERLIN_CHECKSUM_SIZE		sizeof(u16)
 62
 63struct goodix_berlin_fw_version {
 64	u8 rom_pid[6];
 65	u8 rom_vid[3];
 66	u8 rom_vid_reserved;
 67	u8 patch_pid[8];
 68	u8 patch_vid[4];
 69	u8 patch_vid_reserved;
 70	u8 sensor_id;
 71	u8 reserved[2];
 72	__le16 checksum;
 73};
 74
 75struct goodix_berlin_ic_info_version {
 76	u8 info_customer_id;
 77	u8 info_version_id;
 78	u8 ic_die_id;
 79	u8 ic_version_id;
 80	__le32 config_id;
 81	u8 config_version;
 82	u8 frame_data_customer_id;
 83	u8 frame_data_version_id;
 84	u8 touch_data_customer_id;
 85	u8 touch_data_version_id;
 86	u8 reserved[3];
 87} __packed;
 88
 89struct goodix_berlin_ic_info_feature {
 90	__le16 freqhop_feature;
 91	__le16 calibration_feature;
 92	__le16 gesture_feature;
 93	__le16 side_touch_feature;
 94	__le16 stylus_feature;
 95} __packed;
 96
 97struct goodix_berlin_ic_info_misc {
 98	__le32 cmd_addr;
 99	__le16 cmd_max_len;
100	__le32 cmd_reply_addr;
101	__le16 cmd_reply_len;
102	__le32 fw_state_addr;
103	__le16 fw_state_len;
104	__le32 fw_buffer_addr;
105	__le16 fw_buffer_max_len;
106	__le32 frame_data_addr;
107	__le16 frame_data_head_len;
108	__le16 fw_attr_len;
109	__le16 fw_log_len;
110	u8 pack_max_num;
111	u8 pack_compress_version;
112	__le16 stylus_struct_len;
113	__le16 mutual_struct_len;
114	__le16 self_struct_len;
115	__le16 noise_struct_len;
116	__le32 touch_data_addr;
117	__le16 touch_data_head_len;
118	__le16 point_struct_len;
119	__le16 reserved1;
120	__le16 reserved2;
121	__le32 mutual_rawdata_addr;
122	__le32 mutual_diffdata_addr;
123	__le32 mutual_refdata_addr;
124	__le32 self_rawdata_addr;
125	__le32 self_diffdata_addr;
126	__le32 self_refdata_addr;
127	__le32 iq_rawdata_addr;
128	__le32 iq_refdata_addr;
129	__le32 im_rawdata_addr;
130	__le16 im_readata_len;
131	__le32 noise_rawdata_addr;
132	__le16 noise_rawdata_len;
133	__le32 stylus_rawdata_addr;
134	__le16 stylus_rawdata_len;
135	__le32 noise_data_addr;
136	__le32 esd_addr;
137} __packed;
138
139struct goodix_berlin_touch {
140	u8 status;
141	u8 reserved;
142	__le16 x;
143	__le16 y;
144	__le16 w;
145};
146#define GOODIX_BERLIN_TOUCH_SIZE	sizeof(struct goodix_berlin_touch)
147
148struct goodix_berlin_header {
149	u8 status;
150	u8 reserved1;
151	u8 request_type;
152	u8 reserved2[3];
153	__le16 checksum;
154};
155#define GOODIX_BERLIN_HEADER_SIZE	sizeof(struct goodix_berlin_header)
156
157struct goodix_berlin_event {
158	struct goodix_berlin_header hdr;
159	/* The data below is u16/__le16 aligned */
160	u8 data[GOODIX_BERLIN_TOUCH_SIZE * GOODIX_BERLIN_MAX_TOUCH +
161		GOODIX_BERLIN_CHECKSUM_SIZE];
162};
163
164struct goodix_berlin_core {
165	struct device *dev;
166	struct regmap *regmap;
167	struct regulator *avdd;
168	struct regulator *iovdd;
169	struct gpio_desc *reset_gpio;
170	struct touchscreen_properties props;
171	struct goodix_berlin_fw_version fw_version;
172	struct input_dev *input_dev;
173	int irq;
174
175	/* Runtime parameters extracted from IC_INFO buffer  */
176	u32 touch_data_addr;
177
178	struct goodix_berlin_event event;
179};
180
181static bool goodix_berlin_checksum_valid(const u8 *data, int size)
182{
183	u32 cal_checksum = 0;
184	u16 r_checksum;
185	int i;
186
187	if (size < GOODIX_BERLIN_CHECKSUM_SIZE)
188		return false;
189
190	for (i = 0; i < size - GOODIX_BERLIN_CHECKSUM_SIZE; i++)
191		cal_checksum += data[i];
192
193	r_checksum = get_unaligned_le16(&data[i]);
194
195	return (u16)cal_checksum == r_checksum;
196}
197
198static bool goodix_berlin_is_dummy_data(struct goodix_berlin_core *cd,
199					const u8 *data, int size)
200{
201	int i;
202
203	/*
204	 * If the device is missing or doesn't respond the buffer
205	 * could be filled with bus default line state, 0x00 or 0xff,
206	 * so declare success the first time we encounter neither.
207	 */
208	for (i = 0; i < size; i++)
209		if (data[i] > 0 && data[i] < 0xff)
210			return false;
211
212	return true;
213}
214
215static int goodix_berlin_dev_confirm(struct goodix_berlin_core *cd)
216{
217	u8 tx_buf[8], rx_buf[8];
218	int retry = 3;
219	int error;
220
221	memset(tx_buf, GOODIX_BERLIN_DEV_CONFIRM_VAL, sizeof(tx_buf));
222	while (retry--) {
223		error = regmap_raw_write(cd->regmap,
224					 GOODIX_BERLIN_BOOTOPTION_ADDR,
225					 tx_buf, sizeof(tx_buf));
226		if (error)
227			return error;
228
229		error = regmap_raw_read(cd->regmap,
230					GOODIX_BERLIN_BOOTOPTION_ADDR,
231					rx_buf, sizeof(rx_buf));
232		if (error)
233			return error;
234
235		if (!memcmp(tx_buf, rx_buf, sizeof(tx_buf)))
236			return 0;
237
238		usleep_range(5000, 5100);
239	}
240
241	dev_err(cd->dev, "device confirm failed, rx_buf: %*ph\n",
242		(int)sizeof(rx_buf), rx_buf);
243
244	return -EINVAL;
245}
246
247static int goodix_berlin_power_on(struct goodix_berlin_core *cd)
248{
249	int error;
250
251	error = regulator_enable(cd->iovdd);
252	if (error) {
253		dev_err(cd->dev, "Failed to enable iovdd: %d\n", error);
254		return error;
255	}
256
257	/* Vendor waits 3ms for IOVDD to settle */
258	usleep_range(3000, 3100);
259
260	error = regulator_enable(cd->avdd);
261	if (error) {
262		dev_err(cd->dev, "Failed to enable avdd: %d\n", error);
263		goto err_iovdd_disable;
264	}
265
266	/* Vendor waits 15ms for IOVDD to settle */
267	usleep_range(15000, 15100);
268
269	gpiod_set_value_cansleep(cd->reset_gpio, 0);
270
271	/* Vendor waits 4ms for Firmware to initialize */
272	usleep_range(4000, 4100);
273
274	error = goodix_berlin_dev_confirm(cd);
275	if (error)
276		goto err_dev_reset;
277
278	/* Vendor waits 100ms for Firmware to fully boot */
279	msleep(GOODIX_BERLIN_NORMAL_RESET_DELAY_MS);
280
281	return 0;
282
283err_dev_reset:
284	gpiod_set_value_cansleep(cd->reset_gpio, 1);
285	regulator_disable(cd->avdd);
286err_iovdd_disable:
287	regulator_disable(cd->iovdd);
288	return error;
289}
290
291static void goodix_berlin_power_off(struct goodix_berlin_core *cd)
292{
293	gpiod_set_value_cansleep(cd->reset_gpio, 1);
294	regulator_disable(cd->avdd);
295	regulator_disable(cd->iovdd);
296}
297
298static int goodix_berlin_read_version(struct goodix_berlin_core *cd)
299{
300	int error;
301
302	error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR,
303				&cd->fw_version, sizeof(cd->fw_version));
304	if (error) {
305		dev_err(cd->dev, "error reading fw version, %d\n", error);
306		return error;
307	}
308
309	if (!goodix_berlin_checksum_valid((u8 *)&cd->fw_version,
310					  sizeof(cd->fw_version))) {
311		dev_err(cd->dev, "invalid fw version: checksum error\n");
312		return -EINVAL;
313	}
314
315	return 0;
316}
317
318/* Only extract necessary data for runtime */
319static int goodix_berlin_parse_ic_info(struct goodix_berlin_core *cd,
320				       const u8 *data, u16 length)
321{
322	struct goodix_berlin_ic_info_misc *misc;
323	unsigned int offset = 0;
324
325	offset += sizeof(__le16); /* length */
326	offset += sizeof(struct goodix_berlin_ic_info_version);
327	offset += sizeof(struct goodix_berlin_ic_info_feature);
328
329	/* IC_INFO Parameters, variable width structure */
330	offset += 4 * sizeof(u8); /* drv_num, sen_num, button_num, force_num */
331	if (offset >= length)
332		goto invalid_offset;
333
334#define ADVANCE_LE16_PARAMS()				\
335	do {						\
336		u8 param_num = data[offset++];		\
337		offset += param_num * sizeof(__le16);	\
338		if (offset >= length)			\
339			goto invalid_offset;		\
340	} while (0)
341	ADVANCE_LE16_PARAMS(); /* active_scan_rate_num */
342	ADVANCE_LE16_PARAMS(); /* mutual_freq_num*/
343	ADVANCE_LE16_PARAMS(); /* self_tx_freq_num */
344	ADVANCE_LE16_PARAMS(); /* self_rx_freq_num */
345	ADVANCE_LE16_PARAMS(); /* stylus_freq_num */
346#undef ADVANCE_LE16_PARAMS
347
348	misc = (struct goodix_berlin_ic_info_misc *)&data[offset];
349	cd->touch_data_addr = le32_to_cpu(misc->touch_data_addr);
350
351	return 0;
352
353invalid_offset:
354	dev_err(cd->dev, "ic_info length is invalid (offset %d length %d)\n",
355		offset, length);
356	return -EINVAL;
357}
358
359static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
360{
361	u8 *afe_data __free(kfree) = NULL;
362	__le16 length_raw;
363	u16 length;
364	int error;
365
366	afe_data = kzalloc(GOODIX_BERLIN_IC_INFO_MAX_LEN, GFP_KERNEL);
367	if (!afe_data)
368		return -ENOMEM;
369
370	error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
371				&length_raw, sizeof(length_raw));
372	if (error) {
373		dev_err(cd->dev, "failed get ic info length, %d\n", error);
374		return error;
375	}
376
377	length = le16_to_cpu(length_raw);
378	if (length >= GOODIX_BERLIN_IC_INFO_MAX_LEN) {
379		dev_err(cd->dev, "invalid ic info length %d\n", length);
380		return -EINVAL;
381	}
382
383	error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
384				afe_data, length);
385	if (error) {
386		dev_err(cd->dev, "failed get ic info data, %d\n", error);
387		return error;
388	}
389
390	/* check whether the data is valid (ex. bus default values) */
391	if (goodix_berlin_is_dummy_data(cd, afe_data, length)) {
392		dev_err(cd->dev, "fw info data invalid\n");
393		return -EINVAL;
394	}
395
396	if (!goodix_berlin_checksum_valid(afe_data, length)) {
397		dev_err(cd->dev, "fw info checksum error\n");
398		return -EINVAL;
399	}
400
401	error = goodix_berlin_parse_ic_info(cd, afe_data, length);
402	if (error)
403		return error;
404
405	/* check some key info */
406	if (!cd->touch_data_addr) {
407		dev_err(cd->dev, "touch_data_addr is null\n");
408		return -EINVAL;
409	}
410
411	return 0;
412}
413
414static int goodix_berlin_get_remaining_contacts(struct goodix_berlin_core *cd,
415						int n)
416{
417	size_t offset = 2 * GOODIX_BERLIN_TOUCH_SIZE +
418				GOODIX_BERLIN_CHECKSUM_SIZE;
419	u32 addr = cd->touch_data_addr + GOODIX_BERLIN_HEADER_SIZE + offset;
420	int error;
421
422	error = regmap_raw_read(cd->regmap, addr,
423				&cd->event.data[offset],
424				(n - 2) * GOODIX_BERLIN_TOUCH_SIZE);
425	if (error) {
426		dev_err_ratelimited(cd->dev, "failed to get touch data, %d\n",
427				    error);
428		return error;
429	}
430
431	return 0;
432}
433
434static void goodix_berlin_report_state(struct goodix_berlin_core *cd, int n)
435{
436	struct goodix_berlin_touch *touch_data =
437			(struct goodix_berlin_touch *)cd->event.data;
438	struct goodix_berlin_touch *t;
439	int i;
440	u8 type, id;
441
442	for (i = 0; i < n; i++) {
443		t = &touch_data[i];
444
445		type = FIELD_GET(GOODIX_BERLIN_POINT_TYPE_MASK, t->status);
446		if (type == GOODIX_BERLIN_POINT_TYPE_STYLUS ||
447		    type == GOODIX_BERLIN_POINT_TYPE_STYLUS_HOVER) {
448			dev_warn_once(cd->dev, "Stylus event type not handled\n");
449			continue;
450		}
451
452		id = FIELD_GET(GOODIX_BERLIN_TOUCH_ID_MASK, t->status);
453		if (id >= GOODIX_BERLIN_MAX_TOUCH) {
454			dev_warn_ratelimited(cd->dev, "invalid finger id %d\n", id);
455			continue;
456		}
457
458		input_mt_slot(cd->input_dev, id);
459		input_mt_report_slot_state(cd->input_dev, MT_TOOL_FINGER, true);
460
461		touchscreen_report_pos(cd->input_dev, &cd->props,
462				       __le16_to_cpu(t->x), __le16_to_cpu(t->y),
463				       true);
464		input_report_abs(cd->input_dev, ABS_MT_TOUCH_MAJOR,
465				 __le16_to_cpu(t->w));
466	}
467
468	input_mt_sync_frame(cd->input_dev);
469	input_sync(cd->input_dev);
470}
471
472static void goodix_berlin_touch_handler(struct goodix_berlin_core *cd)
473{
474	u8 touch_num;
475	int error;
476
477	touch_num = FIELD_GET(GOODIX_BERLIN_TOUCH_COUNT_MASK,
478			      cd->event.hdr.request_type);
479	if (touch_num > GOODIX_BERLIN_MAX_TOUCH) {
480		dev_warn(cd->dev, "invalid touch num %d\n", touch_num);
481		return;
482	}
483
484	if (touch_num > 2) {
485		/* read additional contact data if more than 2 touch events */
486		error = goodix_berlin_get_remaining_contacts(cd, touch_num);
487		if (error)
488			return;
489	}
490
491	if (touch_num) {
492		int len = touch_num * GOODIX_BERLIN_TOUCH_SIZE +
493			  GOODIX_BERLIN_CHECKSUM_SIZE;
494		if (!goodix_berlin_checksum_valid(cd->event.data, len)) {
495			dev_err(cd->dev, "touch data checksum error: %*ph\n",
496				len, cd->event.data);
497			return;
498		}
499	}
500
501	goodix_berlin_report_state(cd, touch_num);
502}
503
504static int goodix_berlin_request_handle_reset(struct goodix_berlin_core *cd)
505{
506	gpiod_set_value_cansleep(cd->reset_gpio, 1);
507	usleep_range(2000, 2100);
508	gpiod_set_value_cansleep(cd->reset_gpio, 0);
509
510	msleep(GOODIX_BERLIN_NORMAL_RESET_DELAY_MS);
511
512	return 0;
513}
514
515static irqreturn_t goodix_berlin_irq(int irq, void *data)
516{
517	struct goodix_berlin_core *cd = data;
518	int error;
519
520	/*
521	 * First, read buffer with space for 2 touch events:
522	 * - GOODIX_BERLIN_HEADER_SIZE = 8 bytes
523	 * - GOODIX_BERLIN_TOUCH_SIZE * 2 = 16 bytes
524	 * - GOODIX_BERLIN_CHECKLSUM_SIZE = 2 bytes
525	 * For a total of 26 bytes.
526	 *
527	 * If only a single finger is reported, we will read 8 bytes more than
528	 * needed:
529	 * - bytes 0-7:   Header (GOODIX_BERLIN_HEADER_SIZE)
530	 * - bytes 8-15:  Finger 0 Data
531	 * - bytes 24-25: Checksum
532	 * - bytes 18-25: Unused 8 bytes
533	 *
534	 * If 2 fingers are reported, we would have read the exact needed
535	 * amount of data and checksum would be at the end of the buffer:
536	 * - bytes 0-7:   Header (GOODIX_BERLIN_HEADER_SIZE)
537	 * - bytes 8-15:  Finger 0 Bytes 0-7
538	 * - bytes 16-23: Finger 1 Bytes 0-7
539	 * - bytes 24-25: Checksum
540	 *
541	 * If more than 2 fingers were reported, the "Checksum" bytes would
542	 * in fact contain part of the next finger data, and then
543	 * goodix_berlin_get_remaining_contacts() would complete the buffer
544	 * with the missing bytes, including the trailing checksum.
545	 * For example, if 3 fingers are reported, then we would do:
546	 * Read 1:
547	 * - bytes 0-7:   Header (GOODIX_BERLIN_HEADER_SIZE)
548	 * - bytes 8-15:  Finger 0 Bytes 0-7
549	 * - bytes 16-23: Finger 1 Bytes 0-7
550	 * - bytes 24-25: Finger 2 Bytes 0-1
551	 * Read 2 (with length of (3 - 2) * 8 = 8 bytes):
552	 * - bytes 26-31: Finger 2 Bytes 2-7
553	 * - bytes 32-33: Checksum
554	 */
555	error = regmap_raw_read(cd->regmap, cd->touch_data_addr,
556				&cd->event,
557				GOODIX_BERLIN_HEADER_SIZE +
558					2 * GOODIX_BERLIN_TOUCH_SIZE +
559					GOODIX_BERLIN_CHECKSUM_SIZE);
560	if (error) {
561		dev_warn_ratelimited(cd->dev,
562				     "failed get event head data: %d\n", error);
563		goto out;
564	}
565
566	if (cd->event.hdr.status == 0)
567		goto out;
568
569	if (!goodix_berlin_checksum_valid((u8 *)&cd->event.hdr,
570					  GOODIX_BERLIN_HEADER_SIZE)) {
571		dev_warn_ratelimited(cd->dev,
572				     "touch head checksum error: %*ph\n",
573				     (int)GOODIX_BERLIN_HEADER_SIZE,
574				     &cd->event.hdr);
575		goto out_clear;
576	}
577
578	if (cd->event.hdr.status & GOODIX_BERLIN_TOUCH_EVENT)
579		goodix_berlin_touch_handler(cd);
580
581	if (cd->event.hdr.status & GOODIX_BERLIN_REQUEST_EVENT) {
582		switch (cd->event.hdr.request_type) {
583		case GOODIX_BERLIN_REQUEST_CODE_RESET:
584			if (cd->reset_gpio)
585				goodix_berlin_request_handle_reset(cd);
586			break;
587
588		default:
589			dev_warn(cd->dev, "unsupported request code 0x%x\n",
590				 cd->event.hdr.request_type);
591		}
592	}
593
594
595out_clear:
596	/* Clear up status field */
597	regmap_write(cd->regmap, cd->touch_data_addr, 0);
598
599out:
600	return IRQ_HANDLED;
601}
602
603static int goodix_berlin_input_dev_config(struct goodix_berlin_core *cd,
604					  const struct input_id *id)
605{
606	struct input_dev *input_dev;
607	int error;
608
609	input_dev = devm_input_allocate_device(cd->dev);
610	if (!input_dev)
611		return -ENOMEM;
612
613	cd->input_dev = input_dev;
614	input_set_drvdata(input_dev, cd);
615
616	input_dev->name = "Goodix Berlin Capacitive TouchScreen";
617	input_dev->phys = "input/ts";
618
619	input_dev->id = *id;
620
621	input_set_abs_params(cd->input_dev, ABS_MT_POSITION_X,
622			     0, SZ_64K - 1, 0, 0);
623	input_set_abs_params(cd->input_dev, ABS_MT_POSITION_Y,
624			     0, SZ_64K - 1, 0, 0);
625	input_set_abs_params(cd->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
626
627	touchscreen_parse_properties(cd->input_dev, true, &cd->props);
628
629	error = input_mt_init_slots(cd->input_dev, GOODIX_BERLIN_MAX_TOUCH,
630				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
631	if (error)
632		return error;
633
634	error = input_register_device(cd->input_dev);
635	if (error)
636		return error;
637
638	return 0;
639}
640
641static int goodix_berlin_suspend(struct device *dev)
642{
643	struct goodix_berlin_core *cd = dev_get_drvdata(dev);
644
645	disable_irq(cd->irq);
646	goodix_berlin_power_off(cd);
647
648	return 0;
649}
650
651static int goodix_berlin_resume(struct device *dev)
652{
653	struct goodix_berlin_core *cd = dev_get_drvdata(dev);
654	int error;
655
656	error = goodix_berlin_power_on(cd);
657	if (error)
658		return error;
659
660	enable_irq(cd->irq);
661
662	return 0;
663}
664
665EXPORT_GPL_SIMPLE_DEV_PM_OPS(goodix_berlin_pm_ops,
666			     goodix_berlin_suspend, goodix_berlin_resume);
667
668static void goodix_berlin_power_off_act(void *data)
669{
670	struct goodix_berlin_core *cd = data;
671
672	goodix_berlin_power_off(cd);
673}
674
675static ssize_t registers_read(struct file *filp, struct kobject *kobj,
676			      struct bin_attribute *bin_attr,
677			      char *buf, loff_t off, size_t count)
678{
679	struct device *dev = kobj_to_dev(kobj);
680	struct goodix_berlin_core *cd = dev_get_drvdata(dev);
681	int error;
682
683	error = regmap_raw_read(cd->regmap, off, buf, count);
684
685	return error ? error : count;
686}
687
688static ssize_t registers_write(struct file *filp, struct kobject *kobj,
689			       struct bin_attribute *bin_attr,
690			       char *buf, loff_t off, size_t count)
691{
692	struct device *dev = kobj_to_dev(kobj);
693	struct goodix_berlin_core *cd = dev_get_drvdata(dev);
694	int error;
695
696	error = regmap_raw_write(cd->regmap, off, buf, count);
697
698	return error ? error : count;
699}
700
701static BIN_ATTR_ADMIN_RW(registers, 0);
702
703static struct bin_attribute *goodix_berlin_bin_attrs[] = {
704	&bin_attr_registers,
705	NULL,
706};
707
708static const struct attribute_group goodix_berlin_attr_group = {
709	.bin_attrs = goodix_berlin_bin_attrs,
710};
711
712const struct attribute_group *goodix_berlin_groups[] = {
713	&goodix_berlin_attr_group,
714	NULL,
715};
716EXPORT_SYMBOL_GPL(goodix_berlin_groups);
717
718int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
719			struct regmap *regmap)
720{
721	struct goodix_berlin_core *cd;
722	int error;
723
724	if (irq <= 0) {
725		dev_err(dev, "Missing interrupt number\n");
726		return -EINVAL;
727	}
728
729	cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL);
730	if (!cd)
731		return -ENOMEM;
732
733	cd->dev = dev;
734	cd->regmap = regmap;
735	cd->irq = irq;
736
737	cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
738	if (IS_ERR(cd->reset_gpio))
739		return dev_err_probe(dev, PTR_ERR(cd->reset_gpio),
740				     "Failed to request reset gpio\n");
741
742	cd->avdd = devm_regulator_get(dev, "avdd");
743	if (IS_ERR(cd->avdd))
744		return dev_err_probe(dev, PTR_ERR(cd->avdd),
745				     "Failed to request avdd regulator\n");
746
747	cd->iovdd = devm_regulator_get(dev, "iovdd");
748	if (IS_ERR(cd->iovdd))
749		return dev_err_probe(dev, PTR_ERR(cd->iovdd),
750				     "Failed to request iovdd regulator\n");
751
752	error = goodix_berlin_power_on(cd);
753	if (error) {
754		dev_err(dev, "failed power on");
755		return error;
756	}
757
758	error = devm_add_action_or_reset(dev, goodix_berlin_power_off_act, cd);
759	if (error)
760		return error;
761
762	error = goodix_berlin_read_version(cd);
763	if (error) {
764		dev_err(dev, "failed to get version info");
765		return error;
766	}
767
768	error = goodix_berlin_get_ic_info(cd);
769	if (error) {
770		dev_err(dev, "invalid ic info, abort");
771		return error;
772	}
773
774	error = goodix_berlin_input_dev_config(cd, id);
775	if (error) {
776		dev_err(dev, "failed set input device");
777		return error;
778	}
779
780	error = devm_request_threaded_irq(dev, cd->irq, NULL, goodix_berlin_irq,
781					  IRQF_ONESHOT, "goodix-berlin", cd);
782	if (error) {
783		dev_err(dev, "request threaded irq failed: %d\n", error);
784		return error;
785	}
786
787	dev_set_drvdata(dev, cd);
788
789	dev_dbg(dev, "Goodix Berlin %s Touchscreen Controller",
790		cd->fw_version.patch_pid);
791
792	return 0;
793}
794EXPORT_SYMBOL_GPL(goodix_berlin_probe);
795
796MODULE_LICENSE("GPL");
797MODULE_DESCRIPTION("Goodix Berlin Core Touchscreen driver");
798MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");