.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) ST-Ericsson SA 2010 |
---|
3 | 4 | * |
---|
4 | | - * License Terms: GNU General Public License, version 2 |
---|
5 | 5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson |
---|
6 | 6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson |
---|
7 | 7 | */ |
---|
.. | .. |
---|
19 | 19 | * These registers are modified under the irq bus lock and cached to avoid |
---|
20 | 20 | * unnecessary writes in bus_sync_unlock. |
---|
21 | 21 | */ |
---|
22 | | -enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; |
---|
| 22 | +enum { REG_IBE, REG_IEV, REG_IS, REG_IE, REG_DIRECT }; |
---|
23 | 23 | |
---|
24 | | -#define CACHE_NR_REGS 4 |
---|
| 24 | +#define CACHE_NR_REGS 5 |
---|
25 | 25 | #define CACHE_NR_BANKS 3 |
---|
26 | 26 | |
---|
27 | 27 | struct tc3589x_gpio { |
---|
.. | .. |
---|
97 | 97 | if (ret < 0) |
---|
98 | 98 | return ret; |
---|
99 | 99 | |
---|
100 | | - return !(ret & BIT(pos)); |
---|
| 100 | + if (ret & BIT(pos)) |
---|
| 101 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 102 | + |
---|
| 103 | + return GPIO_LINE_DIRECTION_IN; |
---|
101 | 104 | } |
---|
102 | 105 | |
---|
103 | 106 | static int tc3589x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, |
---|
.. | .. |
---|
197 | 200 | [REG_IEV] = TC3589x_GPIOIEV0, |
---|
198 | 201 | [REG_IS] = TC3589x_GPIOIS0, |
---|
199 | 202 | [REG_IE] = TC3589x_GPIOIE0, |
---|
| 203 | + [REG_DIRECT] = TC3589x_DIRECT0, |
---|
200 | 204 | }; |
---|
201 | 205 | int i, j; |
---|
202 | 206 | |
---|
.. | .. |
---|
225 | 229 | int mask = BIT(offset % 8); |
---|
226 | 230 | |
---|
227 | 231 | tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; |
---|
| 232 | + tc3589x_gpio->regs[REG_DIRECT][regoffset] |= mask; |
---|
228 | 233 | } |
---|
229 | 234 | |
---|
230 | 235 | static void tc3589x_gpio_irq_unmask(struct irq_data *d) |
---|
.. | .. |
---|
236 | 241 | int mask = BIT(offset % 8); |
---|
237 | 242 | |
---|
238 | 243 | tc3589x_gpio->regs[REG_IE][regoffset] |= mask; |
---|
| 244 | + tc3589x_gpio->regs[REG_DIRECT][regoffset] &= ~mask; |
---|
239 | 245 | } |
---|
240 | 246 | |
---|
241 | 247 | static struct irq_chip tc3589x_gpio_irq_chip = { |
---|
.. | .. |
---|
286 | 292 | struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); |
---|
287 | 293 | struct device_node *np = pdev->dev.of_node; |
---|
288 | 294 | struct tc3589x_gpio *tc3589x_gpio; |
---|
| 295 | + struct gpio_irq_chip *girq; |
---|
289 | 296 | int ret; |
---|
290 | 297 | int irq; |
---|
291 | 298 | |
---|
.. | .. |
---|
314 | 321 | tc3589x_gpio->chip.base = -1; |
---|
315 | 322 | tc3589x_gpio->chip.of_node = np; |
---|
316 | 323 | |
---|
| 324 | + girq = &tc3589x_gpio->chip.irq; |
---|
| 325 | + girq->chip = &tc3589x_gpio_irq_chip; |
---|
| 326 | + /* This will let us handle the parent IRQ in the driver */ |
---|
| 327 | + girq->parent_handler = NULL; |
---|
| 328 | + girq->num_parents = 0; |
---|
| 329 | + girq->parents = NULL; |
---|
| 330 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 331 | + girq->handler = handle_simple_irq; |
---|
| 332 | + girq->threaded = true; |
---|
| 333 | + |
---|
317 | 334 | /* Bring the GPIO module out of reset */ |
---|
318 | 335 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, |
---|
319 | 336 | TC3589x_RSTCTRL_GPIRST, 0); |
---|
| 337 | + if (ret < 0) |
---|
| 338 | + return ret; |
---|
| 339 | + |
---|
| 340 | + /* For tc35894, have to disable Direct KBD interrupts, |
---|
| 341 | + * else IRQST will always be 0x20, IRQN low level, can't |
---|
| 342 | + * clear the irq status. |
---|
| 343 | + * TODO: need more test on other tc3589x chip. |
---|
| 344 | + * |
---|
| 345 | + */ |
---|
| 346 | + ret = tc3589x_reg_write(tc3589x, TC3589x_DKBDMSK, |
---|
| 347 | + TC3589x_DKBDMSK_ELINT | TC3589x_DKBDMSK_EINT); |
---|
320 | 348 | if (ret < 0) |
---|
321 | 349 | return ret; |
---|
322 | 350 | |
---|
.. | .. |
---|
335 | 363 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); |
---|
336 | 364 | return ret; |
---|
337 | 365 | } |
---|
338 | | - |
---|
339 | | - ret = gpiochip_irqchip_add_nested(&tc3589x_gpio->chip, |
---|
340 | | - &tc3589x_gpio_irq_chip, |
---|
341 | | - 0, |
---|
342 | | - handle_simple_irq, |
---|
343 | | - IRQ_TYPE_NONE); |
---|
344 | | - if (ret) { |
---|
345 | | - dev_err(&pdev->dev, |
---|
346 | | - "could not connect irqchip to gpiochip\n"); |
---|
347 | | - return ret; |
---|
348 | | - } |
---|
349 | | - |
---|
350 | | - gpiochip_set_nested_irqchip(&tc3589x_gpio->chip, |
---|
351 | | - &tc3589x_gpio_irq_chip, |
---|
352 | | - irq); |
---|
353 | 366 | |
---|
354 | 367 | platform_set_drvdata(pdev, tc3589x_gpio); |
---|
355 | 368 | |
---|