Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp20052321ybl; Sat, 4 Jan 2020 16:12:18 -0800 (PST) X-Google-Smtp-Source: APXvYqxTVM/TpPofwsjERdwiLlEm+kvlXuHrycv8jcRZdsWS0MyRFR+th0BuVg6dyzLJiP8lLqNc X-Received: by 2002:a9d:7:: with SMTP id 7mr101115209ota.26.1578183138443; Sat, 04 Jan 2020 16:12:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578183138; cv=none; d=google.com; s=arc-20160816; b=D4IluTDtzNsE6PpRqaEO+waaNaP37C8bMGiAINIRieNcaBFCnxq738349Xo8A+0dKT j421/Dd+R42kXNCuRma1TNpHmZZOX5ceYFTtBW27uDoXaQNDW9xBimVpZII4XicTW9YF G22WshkPcqVyuIJsfFfvhIZIxlbp/D9UZ5cHQIQEahDoMAZpeaAJY9CiPgbmVyVMnfz1 DNYV6Wd4fWlIxiPq9IoUGK/etG1SBVhviN2dAsAoLE5CyApGmpJ8gNR6hkzmB/9ExBmO R6O97C2/O3G3KdS7NnjMKK8WOxUJejeoxCkbMvrQw7jwblNTR2Oksz4nG3y4bSY1PILH yxqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=z3KxqVFrmuHs6d8EbzVmS02kUBxdXTE+hJA7uHaCCJM=; b=OHfm5NHn2SeAQ3m858JwymDh/Ob6VV/XFZnnP+y+IGRyOKopIwO1y9vXL22QYq0R7G T9ZxNN0kMD6080sor3JlsWHJ6qvgaVGgH+QOp1JnpynxkFzg0x4qb/ubCI3hlLbV58Ze PM0e4TJI+Zr+MAl3krLXm1+I6L3Jhk5N2n1eBMKlwE9a7umK7Pdb1kwzqxtqdakKvk9B bB5skmyMSF4gzbkDUlXur3EE64qVGYN3xtW0Ay/I8BBqzjs0SirSgj/Oo8jXBJwXt3G6 sRGPVI3tvxefeyh9uoBFfiUyRHHLNnor2JWVxe/esapsi8HcV6Jl7wkyHQw3o6uNZCkl ckuQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e15si25340696oti.29.2020.01.04.16.11.53; Sat, 04 Jan 2020 16:12:18 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726484AbgAEAKn (ORCPT + 99 others); Sat, 4 Jan 2020 19:10:43 -0500 Received: from relay5-d.mail.gandi.net ([217.70.183.197]:42367 "EHLO relay5-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726264AbgAEAKn (ORCPT ); Sat, 4 Jan 2020 19:10:43 -0500 X-Originating-IP: 195.189.32.242 Received: from pc.localdomain (unknown [195.189.32.242]) (Authenticated sender: contact@artur-rojek.eu) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id A885E1C0005; Sun, 5 Jan 2020 00:10:39 +0000 (UTC) From: Artur Rojek To: Dmitry Torokhov , Rob Herring , Mark Rutland , Jonathan Cameron , Paul Cercueil Cc: linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Artur Rojek Subject: [PATCH 3/5] IIO: Ingenic JZ47xx: Add touchscreen mode. Date: Sun, 5 Jan 2020 01:16:37 +0100 Message-Id: <20200105001639.142061-3-contact@artur-rojek.eu> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200105001639.142061-1-contact@artur-rojek.eu> References: <20200105001639.142061-1-contact@artur-rojek.eu> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement support for the touchscreen mode found in JZ47xx SoCs ADC. Signed-off-by: Artur Rojek Tested-by: Paul Cercueil --- drivers/iio/adc/Kconfig | 3 + drivers/iio/adc/ingenic-adc.c | 120 +++++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 5d8540b7b427..dabbf15032af 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -446,6 +446,9 @@ config INA2XX_ADC config INGENIC_ADC tristate "Ingenic JZ47xx SoCs ADC driver" depends on MIPS || COMPILE_TEST + select IIO_BUFFER + select IIO_BUFFER_CB + select IIO_KFIFO_BUF help Say yes here to build support for the Ingenic JZ47xx SoCs ADC unit. diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c index 7a24bc1dabe1..4dbf15fdd95d 100644 --- a/drivers/iio/adc/ingenic-adc.c +++ b/drivers/iio/adc/ingenic-adc.c @@ -8,7 +8,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -20,6 +23,8 @@ #define JZ_ADC_REG_CFG 0x04 #define JZ_ADC_REG_CTRL 0x08 #define JZ_ADC_REG_STATUS 0x0c +#define JZ_ADC_REG_ADSAME 0x10 +#define JZ_ADC_REG_ADWAIT 0x14 #define JZ_ADC_REG_ADTCH 0x18 #define JZ_ADC_REG_ADBDAT 0x1c #define JZ_ADC_REG_ADSDAT 0x20 @@ -28,6 +33,9 @@ #define JZ_ADC_REG_ENABLE_PD BIT(7) #define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1)) #define JZ_ADC_REG_CFG_BAT_MD BIT(4) +#define JZ_ADC_REG_CFG_PULL_UP(n) ((n) << 16) +#define JZ_ADC_REG_CFG_SAMPLE_NUM(n) ((n) << 10) +#define JZ_ADC_REG_CFG_TOUCH_OPS_MASK (BIT(31) | GENMASK(23, 10)) #define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0 #define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB 16 #define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB 8 @@ -44,6 +52,14 @@ #define JZ4770_ADC_BATTERY_VREF 6600 #define JZ4770_ADC_BATTERY_VREF_BITS 12 +#define JZ_ADC_IRQ_AUX BIT(0) +#define JZ_ADC_IRQ_BATTERY BIT(1) +#define JZ_ADC_IRQ_TOUCH BIT(2) +#define JZ_ADC_IRQ_PEN_DOWN BIT(3) +#define JZ_ADC_IRQ_PEN_UP BIT(4) +#define JZ_ADC_IRQ_PEN_DOWN_SLEEP BIT(5) +#define JZ_ADC_IRQ_SLEEP BIT(7) + struct ingenic_adc; struct ingenic_adc_soc_data { @@ -411,6 +427,30 @@ static const struct iio_info ingenic_adc_info = { }; static const struct iio_chan_spec ingenic_channels[] = { + { + .extend_name = "touchscreen_xp", + .type = IIO_POSITIONRELATIVE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_XP, + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16 + }, + }, + { + .extend_name = "touchscreen_yp", + .type = IIO_POSITIONRELATIVE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_YP, + .scan_index = 1, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16 + }, + }, { .extend_name = "aux", .type = IIO_VOLTAGE, @@ -418,6 +458,7 @@ static const struct iio_chan_spec ingenic_channels[] = { BIT(IIO_CHAN_INFO_SCALE), .indexed = 1, .channel = INGENIC_ADC_AUX, + .scan_index = -1 }, { .extend_name = "battery", @@ -428,6 +469,7 @@ static const struct iio_chan_spec ingenic_channels[] = { BIT(IIO_CHAN_INFO_SCALE), .indexed = 1, .channel = INGENIC_ADC_BATTERY, + .scan_index = -1 }, { /* Must always be last in the array. */ .extend_name = "aux2", @@ -436,16 +478,70 @@ static const struct iio_chan_spec ingenic_channels[] = { BIT(IIO_CHAN_INFO_SCALE), .indexed = 1, .channel = INGENIC_ADC_AUX2, + .scan_index = -1 }, }; +static int ingenic_adc_buffer_enable(struct iio_dev *iio_dev) +{ + struct ingenic_adc *adc = iio_priv(iio_dev); + + clk_enable(adc->clk); + /* It takes significant time for the touchscreen hw to stabilize. */ + msleep(50); + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, + JZ_ADC_REG_CFG_SAMPLE_NUM(4) | + JZ_ADC_REG_CFG_PULL_UP(4)); + writew(80, adc->base + JZ_ADC_REG_ADWAIT); + writew(2, adc->base + JZ_ADC_REG_ADSAME); + writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL); + writel(0, adc->base + JZ_ADC_REG_ADTCH); + ingenic_adc_enable(adc, 2, true); + + return 0; +} + +static int ingenic_adc_buffer_disable(struct iio_dev *iio_dev) +{ + struct ingenic_adc *adc = iio_priv(iio_dev); + + ingenic_adc_enable(adc, 2, false); + writeb(0xff, adc->base + JZ_ADC_REG_CTRL); + writeb(0xff, adc->base + JZ_ADC_REG_STATUS); + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0); + writew(0, adc->base + JZ_ADC_REG_ADSAME); + writew(0, adc->base + JZ_ADC_REG_ADWAIT); + clk_disable(adc->clk); + + return 0; +} + +static const struct iio_buffer_setup_ops ingenic_buffer_setup_ops = { + .postenable = &ingenic_adc_buffer_enable, + .predisable = &ingenic_adc_buffer_disable +}; + +static irqreturn_t ingenic_adc_irq(int irq, void *data) +{ + struct iio_dev *iio_dev = data; + struct ingenic_adc *adc = iio_priv(iio_dev); + u32 tdat; + + tdat = readl(adc->base + JZ_ADC_REG_ADTCH); + iio_push_to_buffers(iio_dev, &tdat); + writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS); + + return IRQ_HANDLED; +} + static int ingenic_adc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iio_dev *iio_dev; struct ingenic_adc *adc; const struct ingenic_adc_soc_data *soc_data; - int ret; + struct iio_buffer *buffer; + int irq, ret; soc_data = device_get_match_data(dev); if (!soc_data) @@ -460,6 +556,18 @@ static int ingenic_adc_probe(struct platform_device *pdev) mutex_init(&adc->aux_lock); adc->soc_data = soc_data; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "Failed to get irq: %d\n", irq); + return irq; + } + ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0, + dev_name(dev), iio_dev); + if (ret < 0) { + dev_err(dev, "Failed to request irq: %d\n", ret); + return ret; + } + adc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc->base)) return PTR_ERR(adc->base); @@ -499,7 +607,8 @@ static int ingenic_adc_probe(struct platform_device *pdev) iio_dev->dev.parent = dev; iio_dev->name = "jz-adc"; - iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + iio_dev->setup_ops = &ingenic_buffer_setup_ops; iio_dev->channels = ingenic_channels; iio_dev->num_channels = ARRAY_SIZE(ingenic_channels); /* Remove AUX2 from the list of supported channels. */ @@ -507,6 +616,13 @@ static int ingenic_adc_probe(struct platform_device *pdev) iio_dev->num_channels -= 1; iio_dev->info = &ingenic_adc_info; + buffer = devm_iio_kfifo_allocate(dev); + if (!buffer) { + dev_err(dev, "Unable to add IIO buffer\n"); + return -ENOMEM; + } + iio_device_attach_buffer(iio_dev, buffer); + ret = devm_iio_device_register(dev, iio_dev); if (ret) dev_err(dev, "Unable to register IIO device\n"); -- 2.24.1