summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-merrifield.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2016-07-08 07:08:23 -0400
committerLinus Walleij <linus.walleij@linaro.org>2016-07-22 09:30:41 -0400
commitccf6fd6dcc86143002dec6c392d8aa41a6a46353 (patch)
tree45c1ba1bdd3218c11ac09e052c0522a760bfbf7a /drivers/gpio/gpio-merrifield.c
parentc78e3cf14e4c77746168936d84d03c119d0c984e (diff)
gpio: merrifield: Introduce GPIO driver to support Merrifield
Intel Merrifield platform has a special GPIO controller to drive pads when they are muxed in corresponding mode. Intel Merrifield GPIO IP is slightly different here and there in comparison to the older Intel MID platforms. These differences include in particular the shaked register offsets, specific support of level triggered interrupts and wake capable sources, as well as a pinctrl which is a separate IP. Instead of uglifying existing driver I decide to provide a new one slightly based on gpio-intel-mid.c. So, anyone can easily compare what changes are happened to be here. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Brian J Wood <brian.j.wood@intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-merrifield.c')
-rw-r--r--drivers/gpio/gpio-merrifield.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
new file mode 100644
index 000000000000..11066f6eb412
--- /dev/null
+++ b/drivers/gpio/gpio-merrifield.c
@@ -0,0 +1,433 @@
1/*
2 * Intel Merrifield SoC GPIO driver
3 *
4 * Copyright (c) 2016 Intel Corporation.
5 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/bitops.h>
13#include <linux/gpio/driver.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/module.h>
18#include <linux/pci.h>
19#include <linux/pinctrl/consumer.h>
20
21#define GCCR 0x000 /* controller configuration */
22#define GPLR 0x004 /* pin level r/o */
23#define GPDR 0x01c /* pin direction */
24#define GPSR 0x034 /* pin set w/o */
25#define GPCR 0x04c /* pin clear w/o */
26#define GRER 0x064 /* rising edge detect */
27#define GFER 0x07c /* falling edge detect */
28#define GFBR 0x094 /* glitch filter bypass */
29#define GIMR 0x0ac /* interrupt mask */
30#define GISR 0x0c4 /* interrupt source */
31#define GITR 0x300 /* input type */
32#define GLPR 0x318 /* level input polarity */
33#define GWMR 0x400 /* wake mask */
34#define GWSR 0x418 /* wake source */
35#define GSIR 0xc00 /* secure input */
36
37/* Intel Merrifield has 192 GPIO pins */
38#define MRFLD_NGPIO 192
39
40struct mrfld_gpio_pinrange {
41 unsigned int gpio_base;
42 unsigned int pin_base;
43 unsigned int npins;
44};
45
46#define GPIO_PINRANGE(gstart, gend, pstart) \
47 { \
48 .gpio_base = (gstart), \
49 .pin_base = (pstart), \
50 .npins = (gend) - (gstart) + 1, \
51 }
52
53struct mrfld_gpio {
54 struct gpio_chip chip;
55 void __iomem *reg_base;
56 raw_spinlock_t lock;
57 struct device *dev;
58};
59
60static const struct mrfld_gpio_pinrange mrfld_gpio_ranges[] = {
61 GPIO_PINRANGE(0, 11, 146),
62 GPIO_PINRANGE(12, 13, 144),
63 GPIO_PINRANGE(14, 15, 35),
64 GPIO_PINRANGE(16, 16, 164),
65 GPIO_PINRANGE(17, 18, 105),
66 GPIO_PINRANGE(19, 22, 101),
67 GPIO_PINRANGE(23, 30, 107),
68 GPIO_PINRANGE(32, 43, 67),
69 GPIO_PINRANGE(44, 63, 195),
70 GPIO_PINRANGE(64, 67, 140),
71 GPIO_PINRANGE(68, 69, 165),
72 GPIO_PINRANGE(70, 71, 65),
73 GPIO_PINRANGE(72, 76, 228),
74 GPIO_PINRANGE(77, 86, 37),
75 GPIO_PINRANGE(87, 87, 48),
76 GPIO_PINRANGE(88, 88, 47),
77 GPIO_PINRANGE(89, 96, 49),
78 GPIO_PINRANGE(97, 97, 34),
79 GPIO_PINRANGE(102, 119, 83),
80 GPIO_PINRANGE(120, 123, 79),
81 GPIO_PINRANGE(124, 135, 115),
82 GPIO_PINRANGE(137, 142, 158),
83 GPIO_PINRANGE(154, 163, 24),
84 GPIO_PINRANGE(164, 176, 215),
85 GPIO_PINRANGE(177, 189, 127),
86 GPIO_PINRANGE(190, 191, 178),
87};
88
89static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset,
90 unsigned int reg_type_offset)
91{
92 struct mrfld_gpio *priv = gpiochip_get_data(chip);
93 u8 reg = offset / 32;
94
95 return priv->reg_base + reg_type_offset + reg * 4;
96}
97
98static int mrfld_gpio_get(struct gpio_chip *chip, unsigned int offset)
99{
100 void __iomem *gplr = gpio_reg(chip, offset, GPLR);
101
102 return !!(readl(gplr) & BIT(offset % 32));
103}
104
105static void mrfld_gpio_set(struct gpio_chip *chip, unsigned int offset,
106 int value)
107{
108 void __iomem *gpsr, *gpcr;
109
110 if (value) {
111 gpsr = gpio_reg(chip, offset, GPSR);
112 writel(BIT(offset % 32), gpsr);
113 } else {
114 gpcr = gpio_reg(chip, offset, GPCR);
115 writel(BIT(offset % 32), gpcr);
116 }
117}
118
119static int mrfld_gpio_direction_input(struct gpio_chip *chip,
120 unsigned int offset)
121{
122 struct mrfld_gpio *priv = gpiochip_get_data(chip);
123 void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
124 unsigned long flags;
125 u32 value;
126
127 raw_spin_lock_irqsave(&priv->lock, flags);
128
129 value = readl(gpdr);
130 value &= ~BIT(offset % 32);
131 writel(value, gpdr);
132
133 raw_spin_unlock_irqrestore(&priv->lock, flags);
134
135 return 0;
136}
137
138static int mrfld_gpio_direction_output(struct gpio_chip *chip,
139 unsigned int offset, int value)
140{
141 struct mrfld_gpio *priv = gpiochip_get_data(chip);
142 void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
143 unsigned long flags;
144
145 mrfld_gpio_set(chip, offset, value);
146
147 raw_spin_lock_irqsave(&priv->lock, flags);
148
149 value = readl(gpdr);
150 value |= BIT(offset % 32);
151 writel(value, gpdr);
152
153 raw_spin_unlock_irqrestore(&priv->lock, flags);
154
155 return 0;
156}
157
158static void mrfld_irq_ack(struct irq_data *d)
159{
160 struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
161 u32 gpio = irqd_to_hwirq(d);
162 void __iomem *gisr = gpio_reg(&priv->chip, gpio, GISR);
163
164 writel(BIT(gpio % 32), gisr);
165}
166
167static void mrfld_irq_unmask_mask(struct irq_data *d, bool unmask)
168{
169 struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
170 u32 gpio = irqd_to_hwirq(d);
171 void __iomem *gimr = gpio_reg(&priv->chip, gpio, GIMR);
172 unsigned long flags;
173 u32 value;
174
175 raw_spin_lock_irqsave(&priv->lock, flags);
176
177 if (unmask)
178 value = readl(gimr) | BIT(gpio % 32);
179 else
180 value = readl(gimr) & ~BIT(gpio % 32);
181 writel(value, gimr);
182
183 raw_spin_unlock_irqrestore(&priv->lock, flags);
184}
185
186static void mrfld_irq_mask(struct irq_data *d)
187{
188 mrfld_irq_unmask_mask(d, false);
189}
190
191static void mrfld_irq_unmask(struct irq_data *d)
192{
193 mrfld_irq_unmask_mask(d, true);
194}
195
196static int mrfld_irq_set_type(struct irq_data *d, unsigned int type)
197{
198 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
199 struct mrfld_gpio *priv = gpiochip_get_data(gc);
200 u32 gpio = irqd_to_hwirq(d);
201 void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
202 void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
203 void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR);
204 void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR);
205 unsigned long flags;
206 u32 value;
207
208 raw_spin_lock_irqsave(&priv->lock, flags);
209
210 if (type & IRQ_TYPE_EDGE_RISING)
211 value = readl(grer) | BIT(gpio % 32);
212 else
213 value = readl(grer) & ~BIT(gpio % 32);
214 writel(value, grer);
215
216 if (type & IRQ_TYPE_EDGE_FALLING)
217 value = readl(gfer) | BIT(gpio % 32);
218 else
219 value = readl(gfer) & ~BIT(gpio % 32);
220 writel(value, gfer);
221
222 /*
223 * To prevent glitches from triggering an unintended level interrupt,
224 * configure GLPR register first and then configure GITR.
225 */
226 if (type & IRQ_TYPE_LEVEL_LOW)
227 value = readl(glpr) | BIT(gpio % 32);
228 else
229 value = readl(glpr) & ~BIT(gpio % 32);
230 writel(value, glpr);
231
232 if (type & IRQ_TYPE_LEVEL_MASK) {
233 value = readl(gitr) | BIT(gpio % 32);
234 writel(value, gitr);
235
236 irq_set_handler_locked(d, handle_level_irq);
237 } else if (type & IRQ_TYPE_EDGE_BOTH) {
238 value = readl(gitr) & ~BIT(gpio % 32);
239 writel(value, gitr);
240
241 irq_set_handler_locked(d, handle_edge_irq);
242 }
243
244 raw_spin_unlock_irqrestore(&priv->lock, flags);
245
246 return 0;
247}
248
249static int mrfld_irq_set_wake(struct irq_data *d, unsigned int on)
250{
251 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
252 struct mrfld_gpio *priv = gpiochip_get_data(gc);
253 u32 gpio = irqd_to_hwirq(d);
254 void __iomem *gwmr = gpio_reg(&priv->chip, gpio, GWMR);
255 void __iomem *gwsr = gpio_reg(&priv->chip, gpio, GWSR);
256 unsigned long flags;
257 u32 value;
258
259 raw_spin_lock_irqsave(&priv->lock, flags);
260
261 /* Clear the existing wake status */
262 writel(BIT(gpio % 32), gwsr);
263
264 if (on)
265 value = readl(gwmr) | BIT(gpio % 32);
266 else
267 value = readl(gwmr) & ~BIT(gpio % 32);
268 writel(value, gwmr);
269
270 raw_spin_unlock_irqrestore(&priv->lock, flags);
271
272 dev_dbg(priv->dev, "%sable wake for gpio %u\n", on ? "en" : "dis", gpio);
273 return 0;
274}
275
276static struct irq_chip mrfld_irqchip = {
277 .name = "gpio-merrifield",
278 .irq_ack = mrfld_irq_ack,
279 .irq_mask = mrfld_irq_mask,
280 .irq_unmask = mrfld_irq_unmask,
281 .irq_set_type = mrfld_irq_set_type,
282 .irq_set_wake = mrfld_irq_set_wake,
283};
284
285static void mrfld_irq_handler(struct irq_desc *desc)
286{
287 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
288 struct mrfld_gpio *priv = gpiochip_get_data(gc);
289 struct irq_chip *irqchip = irq_desc_get_chip(desc);
290 unsigned long base, gpio;
291
292 chained_irq_enter(irqchip, desc);
293
294 /* Check GPIO controller to check which pin triggered the interrupt */
295 for (base = 0; base < priv->chip.ngpio; base += 32) {
296 void __iomem *gisr = gpio_reg(&priv->chip, base, GISR);
297 void __iomem *gimr = gpio_reg(&priv->chip, base, GIMR);
298 unsigned long pending, enabled;
299
300 pending = readl(gisr);
301 enabled = readl(gimr);
302
303 /* Only interrupts that are enabled */
304 pending &= enabled;
305
306 for_each_set_bit(gpio, &pending, 32) {
307 unsigned int irq;
308
309 irq = irq_find_mapping(gc->irqdomain, base + gpio);
310 generic_handle_irq(irq);
311 }
312 }
313
314 chained_irq_exit(irqchip, desc);
315}
316
317static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
318{
319 void __iomem *reg;
320 unsigned int base;
321
322 for (base = 0; base < priv->chip.ngpio; base += 32) {
323 /* Clear the rising-edge detect register */
324 reg = gpio_reg(&priv->chip, base, GRER);
325 writel(0, reg);
326 /* Clear the falling-edge detect register */
327 reg = gpio_reg(&priv->chip, base, GFER);
328 writel(0, reg);
329 }
330}
331
332static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id)
333{
334 const struct mrfld_gpio_pinrange *range;
335 struct mrfld_gpio *priv;
336 u32 gpio_base, irq_base;
337 void __iomem *base;
338 unsigned int i;
339 int retval;
340
341 retval = pcim_enable_device(pdev);
342 if (retval)
343 return retval;
344
345 retval = pcim_iomap_regions(pdev, BIT(1) | BIT(0), pci_name(pdev));
346 if (retval) {
347 dev_err(&pdev->dev, "I/O memory mapping error\n");
348 return retval;
349 }
350
351 base = pcim_iomap_table(pdev)[1];
352
353 irq_base = readl(base);
354 gpio_base = readl(sizeof(u32) + base);
355
356 /* Release the IO mapping, since we already get the info from BAR1 */
357 pcim_iounmap_regions(pdev, BIT(1));
358
359 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
360 if (!priv) {
361 dev_err(&pdev->dev, "can't allocate chip data\n");
362 return -ENOMEM;
363 }
364
365 priv->dev = &pdev->dev;
366 priv->reg_base = pcim_iomap_table(pdev)[0];
367
368 priv->chip.label = dev_name(&pdev->dev);
369 priv->chip.parent = &pdev->dev;
370 priv->chip.request = gpiochip_generic_request;
371 priv->chip.free = gpiochip_generic_free;
372 priv->chip.direction_input = mrfld_gpio_direction_input;
373 priv->chip.direction_output = mrfld_gpio_direction_output;
374 priv->chip.get = mrfld_gpio_get;
375 priv->chip.set = mrfld_gpio_set;
376 priv->chip.base = gpio_base;
377 priv->chip.ngpio = MRFLD_NGPIO;
378 priv->chip.can_sleep = false;
379
380 raw_spin_lock_init(&priv->lock);
381
382 pci_set_drvdata(pdev, priv);
383 retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
384 if (retval) {
385 dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
386 return retval;
387 }
388
389 for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) {
390 range = &mrfld_gpio_ranges[i];
391 retval = gpiochip_add_pin_range(&priv->chip,
392 "pinctrl-merrifield",
393 range->gpio_base,
394 range->pin_base,
395 range->npins);
396 if (retval) {
397 dev_err(&pdev->dev, "failed to add GPIO pin range\n");
398 return retval;
399 }
400 }
401
402 retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
403 handle_simple_irq, IRQ_TYPE_NONE);
404 if (retval) {
405 dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
406 return retval;
407 }
408
409 mrfld_irq_init_hw(priv);
410
411 gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq,
412 mrfld_irq_handler);
413
414 return 0;
415}
416
417static const struct pci_device_id mrfld_gpio_ids[] = {
418 { PCI_VDEVICE(INTEL, 0x1199) },
419 { }
420};
421MODULE_DEVICE_TABLE(pci, mrfld_gpio_ids);
422
423static struct pci_driver mrfld_gpio_driver = {
424 .name = "gpio-merrifield",
425 .id_table = mrfld_gpio_ids,
426 .probe = mrfld_gpio_probe,
427};
428
429module_pci_driver(mrfld_gpio_driver);
430
431MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
432MODULE_DESCRIPTION("Intel Merrifield SoC GPIO driver");
433MODULE_LICENSE("GPL v2");