blob: 16b66d51f10982c752585742d9e845d87aee06ae [file] [log] [blame]
Gregory Fong3b0213d2015-05-28 19:14:05 -07001/*
2 * Copyright (C) 2015 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/bitops.h>
15#include <linux/gpio/driver.h>
16#include <linux/of_device.h>
17#include <linux/of_irq.h>
18#include <linux/module.h>
19#include <linux/basic_mmio_gpio.h>
Gregory Fong19a7b692015-07-31 18:17:43 -070020#include <linux/irqdomain.h>
21#include <linux/irqchip/chained_irq.h>
22#include <linux/interrupt.h>
Gregory Fong3b0213d2015-05-28 19:14:05 -070023
24#define GIO_BANK_SIZE 0x20
25#define GIO_ODEN(bank) (((bank) * GIO_BANK_SIZE) + 0x00)
26#define GIO_DATA(bank) (((bank) * GIO_BANK_SIZE) + 0x04)
27#define GIO_IODIR(bank) (((bank) * GIO_BANK_SIZE) + 0x08)
28#define GIO_EC(bank) (((bank) * GIO_BANK_SIZE) + 0x0c)
29#define GIO_EI(bank) (((bank) * GIO_BANK_SIZE) + 0x10)
30#define GIO_MASK(bank) (((bank) * GIO_BANK_SIZE) + 0x14)
31#define GIO_LEVEL(bank) (((bank) * GIO_BANK_SIZE) + 0x18)
32#define GIO_STAT(bank) (((bank) * GIO_BANK_SIZE) + 0x1c)
33
34struct brcmstb_gpio_bank {
35 struct list_head node;
36 int id;
37 struct bgpio_chip bgc;
38 struct brcmstb_gpio_priv *parent_priv;
39 u32 width;
Gregory Fong19a7b692015-07-31 18:17:43 -070040 struct irq_chip irq_chip;
Gregory Fong3b0213d2015-05-28 19:14:05 -070041};
42
43struct brcmstb_gpio_priv {
44 struct list_head bank_list;
45 void __iomem *reg_base;
Gregory Fong3b0213d2015-05-28 19:14:05 -070046 struct platform_device *pdev;
Gregory Fong19a7b692015-07-31 18:17:43 -070047 int parent_irq;
Gregory Fong3b0213d2015-05-28 19:14:05 -070048 int gpio_base;
Gregory Fong19a7b692015-07-31 18:17:43 -070049 bool can_wake;
50 int parent_wake_irq;
Gregory Fong3b0213d2015-05-28 19:14:05 -070051};
52
53#define MAX_GPIO_PER_BANK 32
54#define GPIO_BANK(gpio) ((gpio) >> 5)
55/* assumes MAX_GPIO_PER_BANK is a multiple of 2 */
56#define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1))
57
58static inline struct brcmstb_gpio_bank *
59brcmstb_gpio_gc_to_bank(struct gpio_chip *gc)
60{
61 struct bgpio_chip *bgc = to_bgpio_chip(gc);
62 return container_of(bgc, struct brcmstb_gpio_bank, bgc);
63}
64
65static inline struct brcmstb_gpio_priv *
66brcmstb_gpio_gc_to_priv(struct gpio_chip *gc)
67{
68 struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
69 return bank->parent_priv;
70}
71
Gregory Fong19a7b692015-07-31 18:17:43 -070072static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank,
73 unsigned int offset, bool enable)
74{
75 struct bgpio_chip *bgc = &bank->bgc;
76 struct brcmstb_gpio_priv *priv = bank->parent_priv;
77 u32 mask = bgc->pin2mask(bgc, offset);
78 u32 imask;
79 unsigned long flags;
80
81 spin_lock_irqsave(&bgc->lock, flags);
82 imask = bgc->read_reg(priv->reg_base + GIO_MASK(bank->id));
83 if (enable)
84 imask |= mask;
85 else
86 imask &= ~mask;
87 bgc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask);
88 spin_unlock_irqrestore(&bgc->lock, flags);
89}
90
91/* -------------------- IRQ chip functions -------------------- */
92
93static void brcmstb_gpio_irq_mask(struct irq_data *d)
94{
95 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
96 struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
97
98 brcmstb_gpio_set_imask(bank, d->hwirq, false);
99}
100
101static void brcmstb_gpio_irq_unmask(struct irq_data *d)
102{
103 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
104 struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
105
106 brcmstb_gpio_set_imask(bank, d->hwirq, true);
107}
108
109static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
110{
111 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
112 struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
113 struct brcmstb_gpio_priv *priv = bank->parent_priv;
114 u32 mask = BIT(d->hwirq);
115 u32 edge_insensitive, iedge_insensitive;
116 u32 edge_config, iedge_config;
117 u32 level, ilevel;
118 unsigned long flags;
119
120 switch (type) {
121 case IRQ_TYPE_LEVEL_LOW:
122 level = 0;
123 edge_config = 0;
124 edge_insensitive = 0;
125 break;
126 case IRQ_TYPE_LEVEL_HIGH:
127 level = mask;
128 edge_config = 0;
129 edge_insensitive = 0;
130 break;
131 case IRQ_TYPE_EDGE_FALLING:
132 level = 0;
133 edge_config = 0;
134 edge_insensitive = 0;
135 break;
136 case IRQ_TYPE_EDGE_RISING:
137 level = 0;
138 edge_config = mask;
139 edge_insensitive = 0;
140 break;
141 case IRQ_TYPE_EDGE_BOTH:
142 level = 0;
143 edge_config = 0; /* don't care, but want known value */
144 edge_insensitive = mask;
145 break;
146 default:
147 return -EINVAL;
148 }
149
150 spin_lock_irqsave(&bank->bgc.lock, flags);
151
152 iedge_config = bank->bgc.read_reg(priv->reg_base +
153 GIO_EC(bank->id)) & ~mask;
154 iedge_insensitive = bank->bgc.read_reg(priv->reg_base +
155 GIO_EI(bank->id)) & ~mask;
156 ilevel = bank->bgc.read_reg(priv->reg_base +
157 GIO_LEVEL(bank->id)) & ~mask;
158
159 bank->bgc.write_reg(priv->reg_base + GIO_EC(bank->id),
160 iedge_config | edge_config);
161 bank->bgc.write_reg(priv->reg_base + GIO_EI(bank->id),
162 iedge_insensitive | edge_insensitive);
163 bank->bgc.write_reg(priv->reg_base + GIO_LEVEL(bank->id),
164 ilevel | level);
165
166 spin_unlock_irqrestore(&bank->bgc.lock, flags);
167 return 0;
168}
169
170static int brcmstb_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
171{
172 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
173 struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
174 int ret = 0;
175
176 /*
177 * Only enable wake IRQ once for however many hwirqs can wake
178 * since they all use the same wake IRQ. Mask will be set
179 * up appropriately thanks to IRQCHIP_MASK_ON_SUSPEND flag.
180 */
181 if (enable)
182 ret = enable_irq_wake(priv->parent_wake_irq);
183 else
184 ret = disable_irq_wake(priv->parent_wake_irq);
185 if (ret)
186 dev_err(&priv->pdev->dev, "failed to %s wake-up interrupt\n",
187 enable ? "enable" : "disable");
188 return ret;
189}
190
191static irqreturn_t brcmstb_gpio_wake_irq_handler(int irq, void *data)
192{
193 struct brcmstb_gpio_priv *priv = data;
194
195 if (!priv || irq != priv->parent_wake_irq)
196 return IRQ_NONE;
197 pm_wakeup_event(&priv->pdev->dev, 0);
198 return IRQ_HANDLED;
199}
200
201static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
202{
203 struct brcmstb_gpio_priv *priv = bank->parent_priv;
204 struct irq_domain *irq_domain = bank->bgc.gc.irqdomain;
205 void __iomem *reg_base = priv->reg_base;
206 unsigned long status;
207 unsigned long flags;
208
209 spin_lock_irqsave(&bank->bgc.lock, flags);
210 while ((status = bank->bgc.read_reg(reg_base + GIO_STAT(bank->id)) &
211 bank->bgc.read_reg(reg_base + GIO_MASK(bank->id)))) {
212 int bit;
213
214 for_each_set_bit(bit, &status, 32) {
215 u32 stat = bank->bgc.read_reg(reg_base +
216 GIO_STAT(bank->id));
217 if (bit >= bank->width)
218 dev_warn(&priv->pdev->dev,
219 "IRQ for invalid GPIO (bank=%d, offset=%d)\n",
220 bank->id, bit);
221 bank->bgc.write_reg(reg_base + GIO_STAT(bank->id),
222 stat | BIT(bit));
223 generic_handle_irq(irq_find_mapping(irq_domain, bit));
224 }
225 }
226 spin_unlock_irqrestore(&bank->bgc.lock, flags);
227}
228
229/* Each UPG GIO block has one IRQ for all banks */
230static void brcmstb_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
231{
232 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
233 struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
234 struct irq_chip *chip = irq_desc_get_chip(desc);
235 struct list_head *pos;
236
237 /* Interrupts weren't properly cleared during probe */
238 BUG_ON(!priv || !chip);
239
240 chained_irq_enter(chip, desc);
241 list_for_each(pos, &priv->bank_list) {
242 struct brcmstb_gpio_bank *bank =
243 list_entry(pos, struct brcmstb_gpio_bank, node);
244 brcmstb_gpio_irq_bank_handler(bank);
245 }
246 chained_irq_exit(chip, desc);
247}
248
Gregory Fong3b0213d2015-05-28 19:14:05 -0700249/* Make sure that the number of banks matches up between properties */
250static int brcmstb_gpio_sanity_check_banks(struct device *dev,
251 struct device_node *np, struct resource *res)
252{
253 int res_num_banks = resource_size(res) / GIO_BANK_SIZE;
254 int num_banks =
255 of_property_count_u32_elems(np, "brcm,gpio-bank-widths");
256
257 if (res_num_banks != num_banks) {
258 dev_err(dev, "Mismatch in banks: res had %d, bank-widths had %d\n",
259 res_num_banks, num_banks);
260 return -EINVAL;
261 } else {
262 return 0;
263 }
264}
265
266static int brcmstb_gpio_remove(struct platform_device *pdev)
267{
268 struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev);
269 struct list_head *pos;
270 struct brcmstb_gpio_bank *bank;
271 int ret = 0;
272
273 list_for_each(pos, &priv->bank_list) {
274 bank = list_entry(pos, struct brcmstb_gpio_bank, node);
275 ret = bgpio_remove(&bank->bgc);
276 if (ret)
Gregory Fong19a7b692015-07-31 18:17:43 -0700277 dev_err(&pdev->dev, "gpiochip_remove fail in cleanup\n");
Gregory Fong3b0213d2015-05-28 19:14:05 -0700278 }
279 return ret;
280}
281
282static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
283 const struct of_phandle_args *gpiospec, u32 *flags)
284{
285 struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
286 struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
287 int offset;
288
289 if (gc->of_gpio_n_cells != 2) {
290 WARN_ON(1);
291 return -EINVAL;
292 }
293
294 if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
295 return -EINVAL;
296
297 offset = gpiospec->args[0] - (gc->base - priv->gpio_base);
Gregory Fong19a7b692015-07-31 18:17:43 -0700298 if (offset >= gc->ngpio || offset < 0)
Gregory Fong3b0213d2015-05-28 19:14:05 -0700299 return -EINVAL;
300
301 if (unlikely(offset >= bank->width)) {
302 dev_warn_ratelimited(&priv->pdev->dev,
303 "Received request for invalid GPIO offset %d\n",
304 gpiospec->args[0]);
305 }
306
307 if (flags)
308 *flags = gpiospec->args[1];
309
310 return offset;
311}
312
Gregory Fong19a7b692015-07-31 18:17:43 -0700313/* Before calling, must have bank->parent_irq set and gpiochip registered */
314static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
315 struct brcmstb_gpio_bank *bank)
316{
317 struct brcmstb_gpio_priv *priv = bank->parent_priv;
318 struct device *dev = &pdev->dev;
319 struct device_node *np = dev->of_node;
320
321 bank->irq_chip.name = dev_name(dev);
322 bank->irq_chip.irq_mask = brcmstb_gpio_irq_mask;
323 bank->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask;
324 bank->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type;
325
326 /* Ensures that all non-wakeup IRQs are disabled at suspend */
327 bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
328
329 if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->can_wake &&
330 of_property_read_bool(np, "wakeup-source")) {
331 priv->parent_wake_irq = platform_get_irq(pdev, 1);
332 if (priv->parent_wake_irq < 0) {
333 dev_warn(dev,
334 "Couldn't get wake IRQ - GPIOs will not be able to wake from sleep");
335 } else {
336 int err = devm_request_irq(dev, priv->parent_wake_irq,
337 brcmstb_gpio_wake_irq_handler, 0,
338 "brcmstb-gpio-wake", priv);
339
340 if (err < 0) {
341 dev_err(dev, "Couldn't request wake IRQ");
342 return err;
343 }
344
345 device_set_wakeup_capable(dev, true);
346 device_wakeup_enable(dev);
347 priv->can_wake = true;
348 }
349 }
350
351 if (priv->can_wake)
352 bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake;
353
354 gpiochip_irqchip_add(&bank->bgc.gc, &bank->irq_chip, 0,
355 handle_simple_irq, IRQ_TYPE_NONE);
356 gpiochip_set_chained_irqchip(&bank->bgc.gc, &bank->irq_chip,
357 priv->parent_irq, brcmstb_gpio_irq_handler);
358
359 return 0;
360}
361
Gregory Fong3b0213d2015-05-28 19:14:05 -0700362static int brcmstb_gpio_probe(struct platform_device *pdev)
363{
364 struct device *dev = &pdev->dev;
365 struct device_node *np = dev->of_node;
366 void __iomem *reg_base;
367 struct brcmstb_gpio_priv *priv;
368 struct resource *res;
369 struct property *prop;
370 const __be32 *p;
371 u32 bank_width;
Gregory Fong19a7b692015-07-31 18:17:43 -0700372 int num_banks = 0;
Gregory Fong3b0213d2015-05-28 19:14:05 -0700373 int err;
374 static int gpio_base;
375
376 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
377 if (!priv)
378 return -ENOMEM;
379
380 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
381 reg_base = devm_ioremap_resource(dev, res);
382 if (IS_ERR(reg_base))
383 return PTR_ERR(reg_base);
384
385 priv->gpio_base = gpio_base;
386 priv->reg_base = reg_base;
387 priv->pdev = pdev;
388
Gregory Fong19a7b692015-07-31 18:17:43 -0700389 if (of_property_read_bool(np, "interrupt-controller")) {
390 priv->parent_irq = platform_get_irq(pdev, 0);
391 if (priv->parent_irq <= 0) {
392 dev_err(dev, "Couldn't get IRQ");
393 return -ENOENT;
394 }
395 } else {
396 priv->parent_irq = -ENOENT;
397 }
398
Gregory Fong3b0213d2015-05-28 19:14:05 -0700399 INIT_LIST_HEAD(&priv->bank_list);
400 if (brcmstb_gpio_sanity_check_banks(dev, np, res))
401 return -EINVAL;
402
403 of_property_for_each_u32(np, "brcm,gpio-bank-widths", prop, p,
404 bank_width) {
405 struct brcmstb_gpio_bank *bank;
406 struct bgpio_chip *bgc;
407 struct gpio_chip *gc;
408
409 bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
410 if (!bank) {
411 err = -ENOMEM;
412 goto fail;
413 }
414
415 bank->parent_priv = priv;
Gregory Fong19a7b692015-07-31 18:17:43 -0700416 bank->id = num_banks;
Gregory Fong3b0213d2015-05-28 19:14:05 -0700417 if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) {
418 dev_err(dev, "Invalid bank width %d\n", bank_width);
419 goto fail;
420 } else {
421 bank->width = bank_width;
422 }
423
424 /*
425 * Regs are 4 bytes wide, have data reg, no set/clear regs,
426 * and direction bits have 0 = output and 1 = input
427 */
428 bgc = &bank->bgc;
429 err = bgpio_init(bgc, dev, 4,
430 reg_base + GIO_DATA(bank->id),
431 NULL, NULL, NULL,
432 reg_base + GIO_IODIR(bank->id), 0);
433 if (err) {
434 dev_err(dev, "bgpio_init() failed\n");
435 goto fail;
436 }
437
438 gc = &bgc->gc;
439 gc->of_node = np;
440 gc->owner = THIS_MODULE;
441 gc->label = np->full_name;
442 gc->base = gpio_base;
443 gc->of_gpio_n_cells = 2;
444 gc->of_xlate = brcmstb_gpio_of_xlate;
445 /* not all ngpio lines are valid, will use bank width later */
446 gc->ngpio = MAX_GPIO_PER_BANK;
447
448 err = gpiochip_add(gc);
449 if (err) {
450 dev_err(dev, "Could not add gpiochip for bank %d\n",
451 bank->id);
452 goto fail;
453 }
454 gpio_base += gc->ngpio;
Gregory Fong19a7b692015-07-31 18:17:43 -0700455
456 if (priv->parent_irq > 0) {
457 err = brcmstb_gpio_irq_setup(pdev, bank);
458 if (err)
459 goto fail;
460 }
461
Gregory Fong3b0213d2015-05-28 19:14:05 -0700462 dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id,
463 gc->base, gc->ngpio, bank->width);
464
465 /* Everything looks good, so add bank to list */
466 list_add(&bank->node, &priv->bank_list);
467
Gregory Fong19a7b692015-07-31 18:17:43 -0700468 num_banks++;
Gregory Fong3b0213d2015-05-28 19:14:05 -0700469 }
470
471 dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n",
Gregory Fong19a7b692015-07-31 18:17:43 -0700472 num_banks, priv->gpio_base, gpio_base - 1);
Gregory Fong3b0213d2015-05-28 19:14:05 -0700473
474 platform_set_drvdata(pdev, priv);
475
476 return 0;
477
478fail:
479 (void) brcmstb_gpio_remove(pdev);
480 return err;
481}
482
483static const struct of_device_id brcmstb_gpio_of_match[] = {
484 { .compatible = "brcm,brcmstb-gpio" },
485 {},
486};
487
488MODULE_DEVICE_TABLE(of, brcmstb_gpio_of_match);
489
490static struct platform_driver brcmstb_gpio_driver = {
491 .driver = {
492 .name = "brcmstb-gpio",
493 .of_match_table = brcmstb_gpio_of_match,
494 },
495 .probe = brcmstb_gpio_probe,
496 .remove = brcmstb_gpio_remove,
497};
498module_platform_driver(brcmstb_gpio_driver);
499
500MODULE_AUTHOR("Gregory Fong");
501MODULE_DESCRIPTION("Driver for Broadcom BRCMSTB SoC UPG GPIO");
502MODULE_LICENSE("GPL v2");