.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * TI DaVinci GPIO Support |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2006-2007 David Brownell |
---|
5 | 6 | * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.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 as published by |
---|
9 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
10 | | - * (at your option) any later version. |
---|
11 | 7 | */ |
---|
| 8 | + |
---|
12 | 9 | #include <linux/gpio/driver.h> |
---|
13 | 10 | #include <linux/errno.h> |
---|
14 | 11 | #include <linux/kernel.h> |
---|
.. | .. |
---|
24 | 21 | #include <linux/platform_device.h> |
---|
25 | 22 | #include <linux/platform_data/gpio-davinci.h> |
---|
26 | 23 | #include <linux/irqchip/chained_irq.h> |
---|
| 24 | +#include <linux/spinlock.h> |
---|
| 25 | + |
---|
| 26 | +#include <asm-generic/gpio.h> |
---|
| 27 | + |
---|
| 28 | +#define MAX_REGS_BANKS 5 |
---|
| 29 | +#define MAX_INT_PER_BANK 32 |
---|
27 | 30 | |
---|
28 | 31 | struct davinci_gpio_regs { |
---|
29 | 32 | u32 dir; |
---|
.. | .. |
---|
41 | 44 | typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq); |
---|
42 | 45 | |
---|
43 | 46 | #define BINTEN 0x8 /* GPIO Interrupt Per-Bank Enable Register */ |
---|
44 | | -#define MAX_LABEL_SIZE 20 |
---|
45 | 47 | |
---|
46 | 48 | static void __iomem *gpio_base; |
---|
47 | 49 | static unsigned int offset_array[5] = {0x10, 0x38, 0x60, 0x88, 0xb0}; |
---|
| 50 | + |
---|
| 51 | +struct davinci_gpio_irq_data { |
---|
| 52 | + void __iomem *regs; |
---|
| 53 | + struct davinci_gpio_controller *chip; |
---|
| 54 | + int bank_num; |
---|
| 55 | +}; |
---|
| 56 | + |
---|
| 57 | +struct davinci_gpio_controller { |
---|
| 58 | + struct gpio_chip chip; |
---|
| 59 | + struct irq_domain *irq_domain; |
---|
| 60 | + /* Serialize access to GPIO registers */ |
---|
| 61 | + spinlock_t lock; |
---|
| 62 | + void __iomem *regs[MAX_REGS_BANKS]; |
---|
| 63 | + int gpio_unbanked; |
---|
| 64 | + int irqs[MAX_INT_PER_BANK]; |
---|
| 65 | +}; |
---|
| 66 | + |
---|
| 67 | +static inline u32 __gpio_mask(unsigned gpio) |
---|
| 68 | +{ |
---|
| 69 | + return 1 << (gpio % 32); |
---|
| 70 | +} |
---|
48 | 71 | |
---|
49 | 72 | static inline struct davinci_gpio_regs __iomem *irq2regs(struct irq_data *d) |
---|
50 | 73 | { |
---|
.. | .. |
---|
166 | 189 | |
---|
167 | 190 | static int davinci_gpio_probe(struct platform_device *pdev) |
---|
168 | 191 | { |
---|
169 | | - static int ctrl_num, bank_base; |
---|
170 | | - int gpio, bank, i, ret = 0; |
---|
| 192 | + int bank, i, ret = 0; |
---|
171 | 193 | unsigned int ngpio, nbank, nirq; |
---|
172 | 194 | struct davinci_gpio_controller *chips; |
---|
173 | 195 | struct davinci_gpio_platform_data *pdata; |
---|
174 | 196 | struct device *dev = &pdev->dev; |
---|
175 | | - struct resource *res; |
---|
176 | | - char label[MAX_LABEL_SIZE]; |
---|
177 | 197 | |
---|
178 | 198 | pdata = davinci_gpio_get_pdata(pdev); |
---|
179 | 199 | if (!pdata) { |
---|
.. | .. |
---|
207 | 227 | else |
---|
208 | 228 | nirq = DIV_ROUND_UP(ngpio, 16); |
---|
209 | 229 | |
---|
210 | | - nbank = DIV_ROUND_UP(ngpio, 32); |
---|
211 | | - chips = devm_kcalloc(dev, |
---|
212 | | - nbank, sizeof(struct davinci_gpio_controller), |
---|
213 | | - GFP_KERNEL); |
---|
| 230 | + chips = devm_kzalloc(dev, sizeof(*chips), GFP_KERNEL); |
---|
214 | 231 | if (!chips) |
---|
215 | 232 | return -ENOMEM; |
---|
216 | 233 | |
---|
217 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
218 | | - gpio_base = devm_ioremap_resource(dev, res); |
---|
| 234 | + gpio_base = devm_platform_ioremap_resource(pdev, 0); |
---|
219 | 235 | if (IS_ERR(gpio_base)) |
---|
220 | 236 | return PTR_ERR(gpio_base); |
---|
221 | 237 | |
---|
222 | 238 | for (i = 0; i < nirq; i++) { |
---|
223 | 239 | chips->irqs[i] = platform_get_irq(pdev, i); |
---|
224 | | - if (chips->irqs[i] < 0) { |
---|
225 | | - if (chips->irqs[i] != -EPROBE_DEFER) |
---|
226 | | - dev_info(dev, "IRQ not populated, err = %d\n", |
---|
227 | | - chips->irqs[i]); |
---|
228 | | - return chips->irqs[i]; |
---|
229 | | - } |
---|
| 240 | + if (chips->irqs[i] < 0) |
---|
| 241 | + return dev_err_probe(dev, chips->irqs[i], "IRQ not populated\n"); |
---|
230 | 242 | } |
---|
231 | 243 | |
---|
232 | | - snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++); |
---|
233 | | - chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL); |
---|
234 | | - if (!chips->chip.label) |
---|
235 | | - return -ENOMEM; |
---|
| 244 | + chips->chip.label = dev_name(dev); |
---|
236 | 245 | |
---|
237 | 246 | chips->chip.direction_input = davinci_direction_in; |
---|
238 | 247 | chips->chip.get = davinci_gpio_get; |
---|
.. | .. |
---|
240 | 249 | chips->chip.set = davinci_gpio_set; |
---|
241 | 250 | |
---|
242 | 251 | chips->chip.ngpio = ngpio; |
---|
243 | | - chips->chip.base = bank_base; |
---|
| 252 | + chips->chip.base = pdata->no_auto_base ? pdata->base : -1; |
---|
244 | 253 | |
---|
245 | 254 | #ifdef CONFIG_OF_GPIO |
---|
246 | 255 | chips->chip.of_gpio_n_cells = 2; |
---|
247 | 256 | chips->chip.parent = dev; |
---|
248 | 257 | chips->chip.of_node = dev->of_node; |
---|
249 | | - |
---|
250 | | - if (of_property_read_bool(dev->of_node, "gpio-ranges")) { |
---|
251 | | - chips->chip.request = gpiochip_generic_request; |
---|
252 | | - chips->chip.free = gpiochip_generic_free; |
---|
253 | | - } |
---|
| 258 | + chips->chip.request = gpiochip_generic_request; |
---|
| 259 | + chips->chip.free = gpiochip_generic_free; |
---|
254 | 260 | #endif |
---|
255 | 261 | spin_lock_init(&chips->lock); |
---|
256 | | - bank_base += ngpio; |
---|
257 | 262 | |
---|
258 | | - for (gpio = 0, bank = 0; gpio < ngpio; gpio += 32, bank++) |
---|
| 263 | + nbank = DIV_ROUND_UP(ngpio, 32); |
---|
| 264 | + for (bank = 0; bank < nbank; bank++) |
---|
259 | 265 | chips->regs[bank] = gpio_base + offset_array[bank]; |
---|
260 | 266 | |
---|
261 | 267 | ret = devm_gpiochip_add_data(dev, &chips->chip, chips); |
---|
262 | 268 | if (ret) |
---|
263 | | - goto err; |
---|
| 269 | + return ret; |
---|
264 | 270 | |
---|
265 | 271 | platform_set_drvdata(pdev, chips); |
---|
266 | 272 | ret = davinci_gpio_irq_setup(pdev); |
---|
267 | 273 | if (ret) |
---|
268 | | - goto err; |
---|
| 274 | + return ret; |
---|
269 | 275 | |
---|
270 | 276 | return 0; |
---|
271 | | - |
---|
272 | | -err: |
---|
273 | | - /* Revert the static variable increments */ |
---|
274 | | - ctrl_num--; |
---|
275 | | - bank_base -= ngpio; |
---|
276 | | - |
---|
277 | | - return ret; |
---|
278 | 277 | } |
---|
279 | 278 | |
---|
280 | 279 | /*--------------------------------------------------------------------------*/ |
---|
.. | .. |
---|
292 | 291 | static void gpio_irq_disable(struct irq_data *d) |
---|
293 | 292 | { |
---|
294 | 293 | struct davinci_gpio_regs __iomem *g = irq2regs(d); |
---|
295 | | - u32 mask = (u32) irq_data_get_irq_handler_data(d); |
---|
| 294 | + uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d); |
---|
296 | 295 | |
---|
297 | 296 | writel_relaxed(mask, &g->clr_falling); |
---|
298 | 297 | writel_relaxed(mask, &g->clr_rising); |
---|
.. | .. |
---|
301 | 300 | static void gpio_irq_enable(struct irq_data *d) |
---|
302 | 301 | { |
---|
303 | 302 | struct davinci_gpio_regs __iomem *g = irq2regs(d); |
---|
304 | | - u32 mask = (u32) irq_data_get_irq_handler_data(d); |
---|
| 303 | + uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d); |
---|
305 | 304 | unsigned status = irqd_get_trigger_type(d); |
---|
306 | 305 | |
---|
307 | 306 | status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; |
---|
.. | .. |
---|
442 | 441 | "davinci_gpio"); |
---|
443 | 442 | irq_set_irq_type(irq, IRQ_TYPE_NONE); |
---|
444 | 443 | irq_set_chip_data(irq, (__force void *)g); |
---|
445 | | - irq_set_handler_data(irq, (void *)__gpio_mask(hw)); |
---|
| 444 | + irq_set_handler_data(irq, (void *)(uintptr_t)__gpio_mask(hw)); |
---|
446 | 445 | |
---|
447 | 446 | return 0; |
---|
448 | 447 | } |
---|
.. | .. |
---|
627 | 626 | |
---|
628 | 627 | static const struct of_device_id davinci_gpio_ids[] = { |
---|
629 | 628 | { .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip}, |
---|
| 629 | + { .compatible = "ti,am654-gpio", keystone_gpio_get_irq_chip}, |
---|
630 | 630 | { .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip}, |
---|
631 | 631 | { /* sentinel */ }, |
---|
632 | 632 | }; |
---|