aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-lynxpoint.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2012-12-12 10:42:38 -0500
committerGrant Likely <grant.likely@secretlab.ca>2013-02-05 08:33:29 -0500
commit1d09aaa6a325d55680506d585c7d5ee4744f5539 (patch)
tree1612a491f2d5cd73aeb5f281fe7c247b18aa54a7 /drivers/gpio/gpio-lynxpoint.c
parent88b62b915b0b7e25870eb0604ed9a92ba4bfc9f7 (diff)
gpio/lynxpoint: add chipset gpio driver.
Add gpio support for Intel Lynxpoint chipset. Lynxpoint supports 94 gpio pins which can generate interrupts. Driver will fail requests for pins that are marked as owned by ACPI, or set in an alternate mode (non-gpio). Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio/gpio-lynxpoint.c')
-rw-r--r--drivers/gpio/gpio-lynxpoint.c469
1 files changed, 469 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
new file mode 100644
index 000000000000..3472b05ac512
--- /dev/null
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -0,0 +1,469 @@
1/*
2 * GPIO controller driver for Intel Lynxpoint PCH chipset>
3 * Copyright (c) 2012, Intel Corporation.
4 *
5 * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/types.h>
26#include <linux/bitops.h>
27#include <linux/interrupt.h>
28#include <linux/irq.h>
29#include <linux/gpio.h>
30#include <linux/irqdomain.h>
31#include <linux/slab.h>
32#include <linux/acpi.h>
33#include <linux/platform_device.h>
34#include <linux/pm_runtime.h>
35
36/* LynxPoint chipset has support for 94 gpio pins */
37
38#define LP_NUM_GPIO 94
39
40/* Bitmapped register offsets */
41#define LP_ACPI_OWNED 0x00 /* Bitmap, set by bios, 0: pin reserved for ACPI */
42#define LP_GC 0x7C /* set APIC IRQ to IRQ14 or IRQ15 for all pins */
43#define LP_INT_STAT 0x80
44#define LP_INT_ENABLE 0x90
45
46/* Each pin has two 32 bit config registers, starting at 0x100 */
47#define LP_CONFIG1 0x100
48#define LP_CONFIG2 0x104
49
50/* LP_CONFIG1 reg bits */
51#define OUT_LVL_BIT BIT(31)
52#define IN_LVL_BIT BIT(30)
53#define TRIG_SEL_BIT BIT(4) /* 0: Edge, 1: Level */
54#define INT_INV_BIT BIT(3) /* Invert interrupt triggering */
55#define DIR_BIT BIT(2) /* 0: Output, 1: Input */
56#define USE_SEL_BIT BIT(0) /* 0: Native, 1: GPIO */
57
58/* LP_CONFIG2 reg bits */
59#define GPINDIS_BIT BIT(2) /* disable input sensing */
60#define GPIWP_BIT (BIT(0) | BIT(1)) /* weak pull options */
61
62struct lp_gpio {
63 struct gpio_chip chip;
64 struct irq_domain *domain;
65 struct platform_device *pdev;
66 spinlock_t lock;
67 unsigned long reg_base;
68};
69
70/*
71 * Lynxpoint gpios are controlled through both bitmapped registers and
72 * per gpio specific registers. The bitmapped registers are in chunks of
73 * 3 x 32bit registers to cover all 94 gpios
74 *
75 * per gpio specific registers consist of two 32bit registers per gpio
76 * (LP_CONFIG1 and LP_CONFIG2), with 94 gpios there's a total of
77 * 188 config registes.
78 *
79 * A simplified view of the register layout look like this:
80 *
81 * LP_ACPI_OWNED[31:0] gpio ownerships for gpios 0-31 (bitmapped registers)
82 * LP_ACPI_OWNED[63:32] gpio ownerships for gpios 32-63
83 * LP_ACPI_OWNED[94:64] gpio ownerships for gpios 63-94
84 * ...
85 * LP_INT_ENABLE[31:0] ...
86 * LP_INT_ENABLE[63:31] ...
87 * LP_INT_ENABLE[94:64] ...
88 * LP0_CONFIG1 (gpio 0) config1 reg for gpio 0 (per gpio registers)
89 * LP0_CONFIG2 (gpio 0) config2 reg for gpio 0
90 * LP1_CONFIG1 (gpio 1) config1 reg for gpio 1
91 * LP1_CONFIG2 (gpio 1) config2 reg for gpio 1
92 * LP2_CONFIG1 (gpio 2) ...
93 * LP2_CONFIG2 (gpio 2) ...
94 * ...
95 * LP94_CONFIG1 (gpio 94) ...
96 * LP94_CONFIG2 (gpio 94) ...
97 */
98
99static unsigned long lp_gpio_reg(struct gpio_chip *chip, unsigned offset,
100 int reg)
101{
102 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
103 int reg_offset;
104
105 if (reg == LP_CONFIG1 || reg == LP_CONFIG2)
106 /* per gpio specific config registers */
107 reg_offset = offset * 8;
108 else
109 /* bitmapped registers */
110 reg_offset = (offset / 32) * 4;
111
112 return lg->reg_base + reg + reg_offset;
113}
114
115static int lp_gpio_request(struct gpio_chip *chip, unsigned offset)
116{
117 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
118 unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
119 unsigned long conf2 = lp_gpio_reg(chip, offset, LP_CONFIG2);
120 unsigned long acpi_use = lp_gpio_reg(chip, offset, LP_ACPI_OWNED);
121
122 pm_runtime_get(&lg->pdev->dev); /* should we put if failed */
123
124 /* Fail if BIOS reserved pin for ACPI use */
125 if (!(inl(acpi_use) & BIT(offset % 32))) {
126 dev_err(&lg->pdev->dev, "gpio %d reserved for ACPI\n", offset);
127 return -EBUSY;
128 }
129 /* Fail if pin is in alternate function mode (not GPIO mode) */
130 if (!(inl(reg) & USE_SEL_BIT))
131 return -ENODEV;
132
133 /* enable input sensing */
134 outl(inl(conf2) & ~GPINDIS_BIT, conf2);
135
136
137 return 0;
138}
139
140static void lp_gpio_free(struct gpio_chip *chip, unsigned offset)
141{
142 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
143 unsigned long conf2 = lp_gpio_reg(chip, offset, LP_CONFIG2);
144
145 /* disable input sensing */
146 outl(inl(conf2) | GPINDIS_BIT, conf2);
147
148 pm_runtime_put(&lg->pdev->dev);
149}
150
151static int lp_irq_type(struct irq_data *d, unsigned type)
152{
153 struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
154 u32 hwirq = irqd_to_hwirq(d);
155 unsigned long flags;
156 u32 value;
157 unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1);
158
159 if (hwirq >= lg->chip.ngpio)
160 return -EINVAL;
161
162 spin_lock_irqsave(&lg->lock, flags);
163 value = inl(reg);
164
165 /* set both TRIG_SEL and INV bits to 0 for rising edge */
166 if (type & IRQ_TYPE_EDGE_RISING)
167 value &= ~(TRIG_SEL_BIT | INT_INV_BIT);
168
169 /* TRIG_SEL bit 0, INV bit 1 for falling edge */
170 if (type & IRQ_TYPE_EDGE_FALLING)
171 value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT;
172
173 /* TRIG_SEL bit 1, INV bit 0 for level low */
174 if (type & IRQ_TYPE_LEVEL_LOW)
175 value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT;
176
177 /* TRIG_SEL bit 1, INV bit 1 for level high */
178 if (type & IRQ_TYPE_LEVEL_HIGH)
179 value |= TRIG_SEL_BIT | INT_INV_BIT;
180
181 outl(value, reg);
182 spin_unlock_irqrestore(&lg->lock, flags);
183
184 return 0;
185}
186
187static int lp_gpio_get(struct gpio_chip *chip, unsigned offset)
188{
189 unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
190 return inl(reg) & IN_LVL_BIT;
191}
192
193static void lp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
194{
195 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
196 unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
197 unsigned long flags;
198
199 spin_lock_irqsave(&lg->lock, flags);
200
201 if (value)
202 outl(inl(reg) | OUT_LVL_BIT, reg);
203 else
204 outl(inl(reg) & ~OUT_LVL_BIT, reg);
205
206 spin_unlock_irqrestore(&lg->lock, flags);
207}
208
209static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
210{
211 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
212 unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
213 unsigned long flags;
214
215 spin_lock_irqsave(&lg->lock, flags);
216 outl(inl(reg) | DIR_BIT, reg);
217 spin_unlock_irqrestore(&lg->lock, flags);
218
219 return 0;
220}
221
222static int lp_gpio_direction_output(struct gpio_chip *chip,
223 unsigned offset, int value)
224{
225 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
226 unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
227 unsigned long flags;
228
229 lp_gpio_set(chip, offset, value);
230
231 spin_lock_irqsave(&lg->lock, flags);
232 outl(inl(reg) & ~DIR_BIT, reg);
233 spin_unlock_irqrestore(&lg->lock, flags);
234
235 return 0;
236}
237
238static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
239{
240 struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
241 return irq_create_mapping(lg->domain, offset);
242}
243
244static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
245{
246 struct irq_data *data = irq_desc_get_irq_data(desc);
247 struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
248 struct irq_chip *chip = irq_data_get_irq_chip(data);
249 u32 base, pin, mask;
250 unsigned long reg, pending;
251 unsigned virq;
252
253 /* check from GPIO controller which pin triggered the interrupt */
254 for (base = 0; base < lg->chip.ngpio; base += 32) {
255 reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
256
257 while ((pending = inl(reg))) {
258 pin = __ffs(pending);
259 mask = BIT(pin);
260 /* Clear before handling so we don't lose an edge */
261 outl(mask, reg);
262 virq = irq_find_mapping(lg->domain, base + pin);
263 generic_handle_irq(virq);
264 }
265 }
266 chip->irq_eoi(data);
267}
268
269static void lp_irq_unmask(struct irq_data *d)
270{
271}
272
273static void lp_irq_mask(struct irq_data *d)
274{
275}
276
277static void lp_irq_enable(struct irq_data *d)
278{
279 struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
280 u32 hwirq = irqd_to_hwirq(d);
281 unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
282 unsigned long flags;
283
284 spin_lock_irqsave(&lg->lock, flags);
285 outl(inl(reg) | BIT(hwirq % 32), reg);
286 spin_unlock_irqrestore(&lg->lock, flags);
287}
288
289static void lp_irq_disable(struct irq_data *d)
290{
291 struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
292 u32 hwirq = irqd_to_hwirq(d);
293 unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
294 unsigned long flags;
295
296 spin_lock_irqsave(&lg->lock, flags);
297 outl(inl(reg) & ~BIT(hwirq % 32), reg);
298 spin_unlock_irqrestore(&lg->lock, flags);
299}
300
301static struct irq_chip lp_irqchip = {
302 .name = "LP-GPIO",
303 .irq_mask = lp_irq_mask,
304 .irq_unmask = lp_irq_unmask,
305 .irq_enable = lp_irq_enable,
306 .irq_disable = lp_irq_disable,
307 .irq_set_type = lp_irq_type,
308 .flags = IRQCHIP_SKIP_SET_WAKE,
309};
310
311static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
312{
313 unsigned long reg;
314 unsigned base;
315
316 for (base = 0; base < lg->chip.ngpio; base += 32) {
317 /* disable gpio pin interrupts */
318 reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
319 outl(0, reg);
320 /* Clear interrupt status register */
321 reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
322 outl(0xffffffff, reg);
323 }
324}
325
326static int lp_gpio_irq_map(struct irq_domain *d, unsigned int virq,
327 irq_hw_number_t hw)
328{
329 struct lp_gpio *lg = d->host_data;
330
331 irq_set_chip_and_handler_name(virq, &lp_irqchip, handle_simple_irq,
332 "demux");
333 irq_set_chip_data(virq, lg);
334 irq_set_irq_type(virq, IRQ_TYPE_NONE);
335
336 return 0;
337}
338
339static const struct irq_domain_ops lp_gpio_irq_ops = {
340 .map = lp_gpio_irq_map,
341};
342
343static int lp_gpio_probe(struct platform_device *pdev)
344{
345 struct lp_gpio *lg;
346 struct gpio_chip *gc;
347 struct resource *io_rc, *irq_rc;
348 struct device *dev = &pdev->dev;
349 unsigned long reg_len;
350 unsigned hwirq;
351 int ret = -ENODEV;
352
353 lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
354 if (!lg) {
355 dev_err(dev, "can't allocate lp_gpio chip data\n");
356 return -ENOMEM;
357 }
358
359 lg->pdev = pdev;
360 platform_set_drvdata(pdev, lg);
361
362 io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
363 irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
364
365 if (!io_rc) {
366 dev_err(dev, "missing IO resources\n");
367 return -EINVAL;
368 }
369
370 lg->reg_base = io_rc->start;
371 reg_len = resource_size(io_rc);
372
373 if (!devm_request_region(dev, lg->reg_base, reg_len, "lp-gpio")) {
374 dev_err(dev, "failed requesting IO region 0x%x\n",
375 (unsigned int)lg->reg_base);
376 return -EBUSY;
377 }
378
379 spin_lock_init(&lg->lock);
380
381 gc = &lg->chip;
382 gc->label = dev_name(dev);
383 gc->owner = THIS_MODULE;
384 gc->request = lp_gpio_request;
385 gc->free = lp_gpio_free;
386 gc->direction_input = lp_gpio_direction_input;
387 gc->direction_output = lp_gpio_direction_output;
388 gc->get = lp_gpio_get;
389 gc->set = lp_gpio_set;
390 gc->base = -1;
391 gc->ngpio = LP_NUM_GPIO;
392 gc->can_sleep = 0;
393 gc->dev = dev;
394
395 /* set up interrupts */
396 if (irq_rc && irq_rc->start) {
397 hwirq = irq_rc->start;
398 gc->to_irq = lp_gpio_to_irq;
399
400 lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO,
401 &lp_gpio_irq_ops, lg);
402 if (!lg->domain)
403 return -ENXIO;
404
405 lp_gpio_irq_init_hw(lg);
406
407 irq_set_handler_data(hwirq, lg);
408 irq_set_chained_handler(hwirq, lp_gpio_irq_handler);
409 }
410
411 ret = gpiochip_add(gc);
412 if (ret) {
413 dev_err(dev, "failed adding lp-gpio chip\n");
414 return ret;
415 }
416 pm_runtime_enable(dev);
417
418 return 0;
419}
420
421static int lp_gpio_runtime_suspend(struct device *dev)
422{
423 return 0;
424}
425
426static int lp_gpio_runtime_resume(struct device *dev)
427{
428 return 0;
429}
430
431static const struct dev_pm_ops lp_gpio_pm_ops = {
432 .runtime_suspend = lp_gpio_runtime_suspend,
433 .runtime_resume = lp_gpio_runtime_resume,
434};
435
436static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {
437 { "INT33C7", 0 },
438 { }
439};
440MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match);
441
442static int lp_gpio_remove(struct platform_device *pdev)
443{
444 struct lp_gpio *lg = platform_get_drvdata(pdev);
445 int err;
446 err = gpiochip_remove(&lg->chip);
447 if (err)
448 dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
449 platform_set_drvdata(pdev, NULL);
450 return 0;
451}
452
453static struct platform_driver lp_gpio_driver = {
454 .probe = lp_gpio_probe,
455 .remove = lp_gpio_remove,
456 .driver = {
457 .name = "lp_gpio",
458 .owner = THIS_MODULE,
459 .pm = &lp_gpio_pm_ops,
460 .acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match),
461 },
462};
463
464static int __init lp_gpio_init(void)
465{
466 return platform_driver_register(&lp_gpio_driver);
467}
468
469subsys_initcall(lp_gpio_init);