/
0031-misc-add-gpevt-driver.patch
222 lines (217 loc) · 5.8 KB
/
0031-misc-add-gpevt-driver.patch
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
From 47877897dd1f70357c357f51c5f512c493b694c7 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@ti.com>
Date: Wed, 17 Oct 2012 10:48:22 -0400
Subject: [PATCH 31/35] misc: add gpevt driver
Simply amazing...'nuff said.
Signed-off-by: Matt Porter <mporter@ti.com>
---
drivers/misc/Kconfig | 6 ++
drivers/misc/Makefile | 1 +
drivers/misc/gpevt.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 179 insertions(+)
create mode 100644 drivers/misc/gpevt.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b151b7c..cd43cbd 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -499,6 +499,12 @@ config USB_SWITCH_FSA9480
stereo and mono audio, video, microphone and UART data to use
a common connector port.
+config GPEVT
+ tristate "Amazing GPIO DMA Event Test Driver(tm)"
+ depends on TI_EDMA
+ help
+ Simply amazing!
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2129377..661d093 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,3 +49,4 @@ obj-y += carma/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_INTEL_MEI) += mei/
+obj-$(CONFIG_GPEVT) += gpevt.o
diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
new file mode 100644
index 0000000..4fe256c
--- /dev/null
+++ b/drivers/misc/gpevt.c
@@ -0,0 +1,172 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
+#define GPEVT_MAGIC 0xdeadbeef
+
+static u32 *dst_fifo;
+static dma_addr_t fifo_addr;
+
+static void gpevt_callback(void *data)
+{
+ struct device *dev = data;
+
+ dma_unmap_single(dev, fifo_addr, 32, DMA_FROM_DEVICE);
+
+ if (*dst_fifo == GPEVT_MAGIC)
+ dev_info(dev, "*** DMA transfer succeeded ***\n");
+ else
+ dev_info(dev, "*** DMA transfer failed ***\n");
+}
+
+static int __devinit gpevt_probe (struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct pinctrl *pinctrl;
+ struct dma_chan *chan;
+ struct dma_slave_config cfg;
+ struct dma_async_tx_descriptor *tx;
+ int gpio_evt = 0;
+ int ret;
+ u32 *src_buf;
+ struct scatterlist sg;
+
+ src_buf = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
+ if (!src_buf) {
+ dev_err(&pdev->dev, "failed to allocate src buffer\n");
+ return -ENOMEM;
+ }
+
+ dst_fifo = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
+ if (!dst_fifo) {
+ dev_err(&pdev->dev, "failed to allocate dst fifo\n");
+ return -ENOMEM;
+ }
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev,
+ "pins are not configured from the driver\n");
+
+ gpio_evt = of_get_named_gpio(np, "gpio-evt", 0);
+ if (gpio_evt < 0) {
+ dev_err(&pdev->dev, "failed to find gpio event signal!\n");
+ return -EINVAL;
+ }
+
+ ret = devm_gpio_request_one(&pdev->dev, gpio_evt,
+ GPIOF_IN, "GPIO Event Pin");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to claim gpio-evt pin\n");
+ return ret;
+ }
+
+ ret = request_irq(gpio_to_irq(gpio_evt), no_action,
+ IRQ_TYPE_EDGE_FALLING, "gpevt", &pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request falling edge irq/event\n");
+ return ret;
+ }
+
+ chan = dma_request_slave_channel(&pdev->dev, "gpioevt");
+ if (!chan) {
+ dev_err(&pdev->dev, "no gpio channel for gpevt\n");
+ return -EAGAIN;
+ }
+
+ fifo_addr = dma_map_single(&pdev->dev, dst_fifo, 32, DMA_FROM_DEVICE);
+ if (!fifo_addr) {
+ dev_err(&pdev->dev, "could not map dst fifo\n");
+ return -EIO;
+ }
+ cfg.dst_addr = fifo_addr;
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.dst_maxburst = 1;
+
+ ret = dmaengine_slave_config(chan, &cfg);
+ if (ret)
+ return ret;
+
+ *src_buf = GPEVT_MAGIC;
+ sg_init_table(&sg, 1);
+ sg_dma_address(&sg) = dma_map_single(&pdev->dev, src_buf, 32, DMA_TO_DEVICE);
+ sg_dma_len(&sg) = 4;
+
+ tx = dmaengine_prep_slave_sg(chan, &sg, 1, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx) {
+ dev_err(&pdev->dev, "prep_slave_sg() failed\n");
+ return -EIO;
+ }
+
+ tx->callback = gpevt_callback;
+ tx->callback_param = &pdev->dev;
+ dmaengine_submit(tx);
+
+ dma_async_issue_pending(chan);
+
+ dev_info(&pdev->dev, "Amazing GPIO DMA Event Test Driver(tm) engaged\n");
+
+ return 0;
+}
+
+static int __devexit gpevt_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id gpevt_dt_ids[] = {
+ { .compatible = "gpevt", .data = (void *) NULL, },
+};
+MODULE_DEVICE_TABLE(of, gpevt_dt_ids);
+
+static struct platform_driver gpevt_driver = {
+ .driver = {
+ .name = "gpevt",
+ .owner = THIS_MODULE,
+ .of_match_table = gpevt_dt_ids,
+ },
+ .probe = gpevt_probe,
+ .remove = __devexit_p(gpevt_remove),
+};
+
+static int __init gpevt_init(void)
+{
+ return platform_driver_register(&gpevt_driver);
+}
+
+static void __exit gpevt_exit(void)
+{
+ platform_driver_unregister(&gpevt_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+module_init(gpevt_init);
+module_exit(gpevt_exit);
+
+MODULE_DESCRIPTION("Amazing GPIO DMA Event Test Driver(tm)");
+MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
+MODULE_LICENSE("GPL");
--
1.8.2.1