aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches/0087-tty-serial-msm-Remove-direct-access-to-GSBI.patch
blob: 8cbb52a903d08a0f442d3e535e8ed04f56c53d90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
From 025909cbf933cc20c2ff5ea9f87de8e17a739a08 Mon Sep 17 00:00:00 2001
From: Andy Gross <agross@codeaurora.org>
Date: Thu, 24 Apr 2014 11:31:22 -0500
Subject: [PATCH 087/182] tty: serial: msm: Remove direct access to GSBI

This patch removes direct access of the GSBI registers.  GSBI configuration
should be done through the GSBI driver directly.

Signed-off-by: Andy Gross <agross@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
---
 drivers/tty/serial/msm_serial.c |   48 ++-------------------------------------
 drivers/tty/serial/msm_serial.h |    5 ----
 2 files changed, 2 insertions(+), 51 deletions(-)

diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 053b98e..778e376 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -52,7 +52,6 @@ struct msm_port {
 	struct clk		*clk;
 	struct clk		*pclk;
 	unsigned int		imr;
-	void __iomem		*gsbi_base;
 	int			is_uartdm;
 	unsigned int		old_snap_state;
 };
@@ -599,9 +598,7 @@ static const char *msm_type(struct uart_port *port)
 static void msm_release_port(struct uart_port *port)
 {
 	struct platform_device *pdev = to_platform_device(port->dev);
-	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct resource *uart_resource;
-	struct resource *gsbi_resource;
 	resource_size_t size;
 
 	uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -612,28 +609,12 @@ static void msm_release_port(struct uart_port *port)
 	release_mem_region(port->mapbase, size);
 	iounmap(port->membase);
 	port->membase = NULL;
-
-	if (msm_port->gsbi_base) {
-		writel_relaxed(GSBI_PROTOCOL_IDLE,
-				msm_port->gsbi_base + GSBI_CONTROL);
-
-		gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (unlikely(!gsbi_resource))
-			return;
-
-		size = resource_size(gsbi_resource);
-		release_mem_region(gsbi_resource->start, size);
-		iounmap(msm_port->gsbi_base);
-		msm_port->gsbi_base = NULL;
-	}
 }
 
 static int msm_request_port(struct uart_port *port)
 {
-	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct platform_device *pdev = to_platform_device(port->dev);
 	struct resource *uart_resource;
-	struct resource *gsbi_resource;
 	resource_size_t size;
 	int ret;
 
@@ -652,30 +633,8 @@ static int msm_request_port(struct uart_port *port)
 		goto fail_release_port;
 	}
 
-	gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	/* Is this a GSBI-based port? */
-	if (gsbi_resource) {
-		size = resource_size(gsbi_resource);
-
-		if (!request_mem_region(gsbi_resource->start, size,
-						 "msm_serial")) {
-			ret = -EBUSY;
-			goto fail_release_port_membase;
-		}
-
-		msm_port->gsbi_base = ioremap(gsbi_resource->start, size);
-		if (!msm_port->gsbi_base) {
-			ret = -EBUSY;
-			goto fail_release_gsbi;
-		}
-	}
-
 	return 0;
 
-fail_release_gsbi:
-	release_mem_region(gsbi_resource->start, size);
-fail_release_port_membase:
-	iounmap(port->membase);
 fail_release_port:
 	release_mem_region(port->mapbase, size);
 	return ret;
@@ -683,7 +642,6 @@ fail_release_port:
 
 static void msm_config_port(struct uart_port *port, int flags)
 {
-	struct msm_port *msm_port = UART_TO_MSM(port);
 	int ret;
 	if (flags & UART_CONFIG_TYPE) {
 		port->type = PORT_MSM;
@@ -691,9 +649,6 @@ static void msm_config_port(struct uart_port *port, int flags)
 		if (ret)
 			return;
 	}
-	if (msm_port->gsbi_base)
-		writel_relaxed(GSBI_PROTOCOL_UART,
-				msm_port->gsbi_base + GSBI_CONTROL);
 }
 
 static int msm_verify_port(struct uart_port *port, struct serial_struct *ser)
@@ -1110,6 +1065,7 @@ static struct of_device_id msm_match_table[] = {
 
 static struct platform_driver msm_platform_driver = {
 	.remove = msm_serial_remove,
+	.probe = msm_serial_probe,
 	.driver = {
 		.name = "msm_serial",
 		.owner = THIS_MODULE,
@@ -1125,7 +1081,7 @@ static int __init msm_serial_init(void)
 	if (unlikely(ret))
 		return ret;
 
-	ret = platform_driver_probe(&msm_platform_driver, msm_serial_probe);
+	ret = platform_driver_register(&msm_platform_driver);
 	if (unlikely(ret))
 		uart_unregister_driver(&msm_uart_driver);
 
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index 1e9b68b..d98d45e 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -109,11 +109,6 @@
 #define UART_ISR		0x0014
 #define UART_ISR_TX_READY	(1 << 7)
 
-#define GSBI_CONTROL		0x0
-#define GSBI_PROTOCOL_CODE	0x30
-#define GSBI_PROTOCOL_UART	0x40
-#define GSBI_PROTOCOL_IDLE	0x0
-
 #define UARTDM_RXFS		0x50
 #define UARTDM_RXFS_BUF_SHIFT	0x7
 #define UARTDM_RXFS_BUF_MASK	0x7
-- 
1.7.10.4
contains some complicated heuristics using the aprox. distance between the 2 touches to see if the user is making a pinch open / close movement, and then reports emulated multi-touch events around the last touch coordinate (as the dual-touch coordinates are worthless). These kinds of heuristics are just asking for trouble (and don't belong in the kernel). So this driver offers straight forward, reliable single touch functionality only. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- .../bindings/input/touchscreen/sun4i.txt | 15 ++ drivers/input/touchscreen/Kconfig | 10 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/sun4i-ts.c | 262 +++++++++++++++++++++ 4 files changed, 288 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/sun4i.txt create mode 100644 drivers/input/touchscreen/sun4i-ts.c --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt @@ -0,0 +1,15 @@ +sun4i resistive touchscreen controller +-------------------------------------- + +Required properties: + - compatible: "allwinner,sun4i-ts" + - reg: mmio address range of the chip + - interrupts: interrupt to which the chip is connected + +Example: + + rtp: rtp@01c25000 { + compatible = "allwinner,sun4i-ts"; + reg = <0x01c25000 0x100>; + interrupts = <29>; + }; --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -906,6 +906,16 @@ config TOUCHSCREEN_STMPE To compile this driver as a module, choose M here: the module will be called stmpe-ts. +config TOUCHSCREEN_SUN4I + tristate "Allwinner sun4i resistive touchscreen controller support" + depends on ARCH_SUNXI + help + This selects support for the resistive touchscreen controller + found on Allwinner sunxi SoCs. + + To compile this driver as a module, choose M here: the + module will be called sun4i-ts. + config TOUCHSCREEN_SUR40 tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen" depends on USB --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixc obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o +obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o --- /dev/null +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -0,0 +1,262 @@ +/* + * Allwinner sunxi resistive touchscreen controller driver + * + * Copyright (C) 2013 - 2014 Hans de Goede <hdegoede@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * The sun4i-ts controller is capable of detecting a second touch, but when a + * second touch is present then the accuracy becomes so bad the reported touch + * location is not useable. + * + * The original android driver contains some complicated heuristics using the + * aprox. distance between the 2 touches to see if the user is making a pinch + * open / close movement, and then reports emulated multi-touch events around + * the last touch coordinate (as the dual-touch coordinates are worthless). + * + * These kinds of heuristics are just asking for trouble (and don't belong + * in the kernel). So this driver offers straight forward, reliable single + * touch functionality only. + */ + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define TP_CTRL0 0x00 +#define TP_CTRL1 0x04 +#define TP_CTRL2 0x08 +#define TP_CTRL3 0x0c +#define TP_INT_FIFOC 0x10 +#define TP_INT_FIFOS 0x14 +#define TP_TPR 0x18 +#define TP_CDAT 0x1c +#define TEMP_DATA 0x20 +#define TP_DATA 0x24 + +/* TP_CTRL0 bits */ +#define ADC_FIRST_DLY(x) ((x) << 24) /* 8 bits */ +#define ADC_FIRST_DLY_MODE(x) ((x) << 23) +#define ADC_CLK_SEL(x) ((x) << 22) +#define ADC_CLK_DIV(x) ((x) << 20) /* 3 bits */ +#define FS_DIV(x) ((x) << 16) /* 4 bits */ +#define T_ACQ(x) ((x) << 0) /* 16 bits */ + +/* TP_CTRL1 bits */ +#define STYLUS_UP_DEBOUN(x) ((x) << 12) /* 8 bits */ +#define STYLUS_UP_DEBOUN_EN(x) ((x) << 9) +#define TOUCH_PAN_CALI_EN(x) ((x) << 6) +#define TP_DUAL_EN(x) ((x) << 5) +#define TP_MODE_EN(x) ((x) << 4) +#define TP_ADC_SELECT(x) ((x) << 3) +#define ADC_CHAN_SELECT(x) ((x) << 0) /* 3 bits */ + +/* TP_CTRL2 bits */ +#define TP_SENSITIVE_ADJUST(x) ((x) << 28) /* 4 bits */ +#define TP_MODE_SELECT(x) ((x) << 26) /* 2 bits */ +#define PRE_MEA_EN(x) ((x) << 24) +#define PRE_MEA_THRE_CNT(x) ((x) << 0) /* 24 bits */ + +/* TP_CTRL3 bits */ +#define FILTER_EN(x) ((x) << 2) +#define FILTER_TYPE(x) ((x) << 0) /* 2 bits */ + +/* TP_INT_FIFOC irq and fifo mask / control bits */ +#define TEMP_IRQ_EN(x) ((x) << 18) +#define OVERRUN_IRQ_EN(x) ((x) << 17) +#define DATA_IRQ_EN(x) ((x) << 16) +#define TP_DATA_XY_CHANGE(x) ((x) << 13) +#define FIFO_TRIG(x) ((x) << 8) /* 5 bits */ +#define DATA_DRQ_EN(x) ((x) << 7) +#define FIFO_FLUSH(x) ((x) << 4) +#define TP_UP_IRQ_EN(x) ((x) << 1) +#define TP_DOWN_IRQ_EN(x) ((x) << 0) + +/* TP_INT_FIFOS irq and fifo status bits */ +#define TEMP_DATA_PENDING BIT(18) +#define FIFO_OVERRUN_PENDING BIT(17) +#define FIFO_DATA_PENDING BIT(16) +#define TP_IDLE_FLG BIT(2) +#define TP_UP_PENDING BIT(1) +#define TP_DOWN_PENDING BIT(0) + +/* TP_TPR bits */ +#define TEMP_ENABLE(x) ((x) << 16) +#define TEMP_PERIOD(x) ((x) << 0) /* t = x * 256 * 16 / clkin */ + +struct sun4i_ts_data { + struct device *dev; + struct input_dev *input; + void __iomem *base; + unsigned int irq; + bool ignore_fifo_data; +}; + +static irqreturn_t sun4i_ts_irq(int irq, void *dev_id) +{ + struct sun4i_ts_data *ts = dev_id; + u32 reg_val, x, y; + + reg_val = readl(ts->base + TP_INT_FIFOS); + + if (reg_val & FIFO_DATA_PENDING) { + x = readl(ts->base + TP_DATA); + y = readl(ts->base + TP_DATA); + /* The 1st location reported after an up event is unreliable */ + if (!ts->ignore_fifo_data) { + input_report_abs(ts->input, ABS_X, x); + input_report_abs(ts->input, ABS_Y, y); + /* + * The hardware has a separate down status bit, but + * that gets set before we get the first location, + * resulting in reporting a click on the old location. + */ + input_report_key(ts->input, BTN_TOUCH, 1); + input_sync(ts->input); + } else { + ts->ignore_fifo_data = false; + } + } + + if (reg_val & TP_UP_PENDING) { + ts->ignore_fifo_data = true; + input_report_key(ts->input, BTN_TOUCH, 0); + input_sync(ts->input); + } + + writel(reg_val, ts->base + TP_INT_FIFOS); + + return IRQ_HANDLED; +} + +static int sun4i_ts_open(struct input_dev *dev) +{ + struct sun4i_ts_data *ts = input_get_drvdata(dev); + + /* Flush, set trig level to 1, enable data and up irqs */ + writel(DATA_IRQ_EN(1) | FIFO_TRIG(1) | FIFO_FLUSH(1) | TP_UP_IRQ_EN(1), + ts->base + TP_INT_FIFOC); + + return 0; +} + +static void sun4i_ts_close(struct input_dev *dev) +{ + struct sun4i_ts_data *ts = input_get_drvdata(dev); + + /* Deactivate all IRQs */ + writel(0, ts->base + TP_INT_FIFOC); +} + +static int sun4i_ts_probe(struct platform_device *pdev) +{ + struct sun4i_ts_data *ts; + struct device *dev = &pdev->dev; + int ret; + + ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + ts->dev = dev; + ts->ignore_fifo_data = true; + + ts->input = devm_input_allocate_device(dev); + if (!ts->input) + return -ENOMEM; + + ts->input->name = pdev->name; + ts->input->phys = "sun4i_ts/input0"; + ts->input->open = sun4i_ts_open; + ts->input->close = sun4i_ts_close; + ts->input->id.bustype = BUS_HOST; + ts->input->id.vendor = 0x0001; + ts->input->id.product = 0x0001; + ts->input->id.version = 0x0100; + ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); + set_bit(BTN_TOUCH, ts->input->keybit); + input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0); + input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0); + input_set_drvdata(ts->input, ts); + + ts->base = devm_ioremap_resource(dev, + platform_get_resource(pdev, IORESOURCE_MEM, 0)); + if (IS_ERR(ts->base)) + return PTR_ERR(ts->base); + + ts->irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(dev, ts->irq, sun4i_ts_irq, 0, "sun4i-ts", ts); + if (ret) + return ret; + + /* + * Select HOSC clk, clkin = clk / 6, adc samplefreq = clkin / 8192, + * t_acq = clkin / (16 * 64) + */ + writel(ADC_CLK_SEL(0) | ADC_CLK_DIV(2) | FS_DIV(7) | T_ACQ(63), + ts->base + TP_CTRL0); + + /* + * sensitive_adjust = 15 : max, which is not all that sensitive, + * tp_mode = 0 : only x and y coordinates, as we don't use dual touch + */ + writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0), + ts->base + TP_CTRL2); + + /* Enable median filter, type 1 : 5/3 */ + writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3); + + /* Enable temperature measurement, period 1953 (2 seconds) */ + writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); + + /* + * Set stylus up debounce to aprox 10 ms, enable debounce, and + * finally enable tp mode. + */ + writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1), + ts->base + TP_CTRL1); + + ret = input_register_device(ts->input); + if (ret) + return ret; + + platform_set_drvdata(pdev, ts); + return 0; +} + +static const struct of_device_id sun4i_ts_of_match[] = { + { .compatible = "allwinner,sun4i-ts", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sun4i_ts_of_match); + +static struct platform_driver sun4i_ts_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "sun4i-ts", + .of_match_table = of_match_ptr(sun4i_ts_of_match), + }, + .probe = sun4i_ts_probe, +}; + +module_platform_driver(sun4i_ts_driver); + +MODULE_DESCRIPTION("Allwinner sun4i resistive touchscreen controller driver"); +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); +MODULE_LICENSE("GPL");