.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | | - * gpio-crystalcove.c - Intel Crystal Cove GPIO Driver |
---|
| 3 | + * Intel Crystal Cove GPIO Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License version |
---|
8 | | - * 2 as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 6 | * |
---|
15 | 7 | * Author: Yang, Bin <bin.yang@intel.com> |
---|
16 | 8 | */ |
---|
17 | 9 | |
---|
| 10 | +#include <linux/bitops.h> |
---|
| 11 | +#include <linux/gpio/driver.h> |
---|
18 | 12 | #include <linux/interrupt.h> |
---|
| 13 | +#include <linux/mfd/intel_soc_pmic.h> |
---|
19 | 14 | #include <linux/module.h> |
---|
20 | 15 | #include <linux/platform_device.h> |
---|
21 | | -#include <linux/gpio/driver.h> |
---|
22 | | -#include <linux/seq_file.h> |
---|
23 | | -#include <linux/bitops.h> |
---|
24 | 16 | #include <linux/regmap.h> |
---|
25 | | -#include <linux/mfd/intel_soc_pmic.h> |
---|
| 17 | +#include <linux/seq_file.h> |
---|
26 | 18 | |
---|
27 | 19 | #define CRYSTALCOVE_GPIO_NUM 16 |
---|
28 | 20 | #define CRYSTALCOVE_VGPIO_NUM 95 |
---|
.. | .. |
---|
137 | 129 | regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value); |
---|
138 | 130 | } |
---|
139 | 131 | |
---|
140 | | -static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) |
---|
| 132 | +static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned int gpio) |
---|
141 | 133 | { |
---|
142 | 134 | struct crystalcove_gpio *cg = gpiochip_get_data(chip); |
---|
143 | 135 | int reg = to_reg(gpio, CTRL_OUT); |
---|
.. | .. |
---|
148 | 140 | return regmap_write(cg->regmap, reg, CTLO_INPUT_SET); |
---|
149 | 141 | } |
---|
150 | 142 | |
---|
151 | | -static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, |
---|
| 143 | +static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio, |
---|
152 | 144 | int value) |
---|
153 | 145 | { |
---|
154 | 146 | struct crystalcove_gpio *cg = gpiochip_get_data(chip); |
---|
.. | .. |
---|
160 | 152 | return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value); |
---|
161 | 153 | } |
---|
162 | 154 | |
---|
163 | | -static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) |
---|
| 155 | +static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned int gpio) |
---|
164 | 156 | { |
---|
165 | 157 | struct crystalcove_gpio *cg = gpiochip_get_data(chip); |
---|
166 | 158 | unsigned int val; |
---|
.. | .. |
---|
177 | 169 | } |
---|
178 | 170 | |
---|
179 | 171 | static void crystalcove_gpio_set(struct gpio_chip *chip, |
---|
180 | | - unsigned gpio, int value) |
---|
| 172 | + unsigned int gpio, int value) |
---|
181 | 173 | { |
---|
182 | 174 | struct crystalcove_gpio *cg = gpiochip_get_data(chip); |
---|
183 | 175 | int reg = to_reg(gpio, CTRL_OUT); |
---|
.. | .. |
---|
191 | 183 | regmap_update_bits(cg->regmap, reg, 1, 0); |
---|
192 | 184 | } |
---|
193 | 185 | |
---|
194 | | -static int crystalcove_irq_type(struct irq_data *data, unsigned type) |
---|
| 186 | +static int crystalcove_irq_type(struct irq_data *data, unsigned int type) |
---|
195 | 187 | { |
---|
196 | 188 | struct crystalcove_gpio *cg = |
---|
197 | 189 | gpiochip_get_data(irq_data_get_irq_chip_data(data)); |
---|
.. | .. |
---|
279 | 271 | static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) |
---|
280 | 272 | { |
---|
281 | 273 | struct crystalcove_gpio *cg = data; |
---|
| 274 | + unsigned long pending; |
---|
282 | 275 | unsigned int p0, p1; |
---|
283 | | - int pending; |
---|
284 | 276 | int gpio; |
---|
285 | 277 | unsigned int virq; |
---|
286 | 278 | |
---|
.. | .. |
---|
293 | 285 | |
---|
294 | 286 | pending = p0 | p1 << 8; |
---|
295 | 287 | |
---|
296 | | - for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) { |
---|
297 | | - if (pending & BIT(gpio)) { |
---|
298 | | - virq = irq_find_mapping(cg->chip.irq.domain, gpio); |
---|
299 | | - handle_nested_irq(virq); |
---|
300 | | - } |
---|
| 288 | + for_each_set_bit(gpio, &pending, CRYSTALCOVE_GPIO_NUM) { |
---|
| 289 | + virq = irq_find_mapping(cg->chip.irq.domain, gpio); |
---|
| 290 | + handle_nested_irq(virq); |
---|
301 | 291 | } |
---|
302 | 292 | |
---|
303 | 293 | return IRQ_HANDLED; |
---|
.. | .. |
---|
340 | 330 | int retval; |
---|
341 | 331 | struct device *dev = pdev->dev.parent; |
---|
342 | 332 | struct intel_soc_pmic *pmic = dev_get_drvdata(dev); |
---|
| 333 | + struct gpio_irq_chip *girq; |
---|
343 | 334 | |
---|
344 | 335 | if (irq < 0) |
---|
345 | 336 | return irq; |
---|
.. | .. |
---|
363 | 354 | cg->chip.dbg_show = crystalcove_gpio_dbg_show; |
---|
364 | 355 | cg->regmap = pmic->regmap; |
---|
365 | 356 | |
---|
| 357 | + girq = &cg->chip.irq; |
---|
| 358 | + girq->chip = &crystalcove_irqchip; |
---|
| 359 | + /* This will let us handle the parent IRQ in the driver */ |
---|
| 360 | + girq->parent_handler = NULL; |
---|
| 361 | + girq->num_parents = 0; |
---|
| 362 | + girq->parents = NULL; |
---|
| 363 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 364 | + girq->handler = handle_simple_irq; |
---|
| 365 | + girq->threaded = true; |
---|
| 366 | + |
---|
| 367 | + retval = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
---|
| 368 | + crystalcove_gpio_irq_handler, |
---|
| 369 | + IRQF_ONESHOT, KBUILD_MODNAME, cg); |
---|
| 370 | + if (retval) { |
---|
| 371 | + dev_warn(&pdev->dev, "request irq failed: %d\n", retval); |
---|
| 372 | + return retval; |
---|
| 373 | + } |
---|
| 374 | + |
---|
366 | 375 | retval = devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg); |
---|
367 | 376 | if (retval) { |
---|
368 | 377 | dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval); |
---|
369 | 378 | return retval; |
---|
370 | 379 | } |
---|
371 | 380 | |
---|
372 | | - gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0, |
---|
373 | | - handle_simple_irq, IRQ_TYPE_NONE); |
---|
374 | | - |
---|
375 | | - retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler, |
---|
376 | | - IRQF_ONESHOT, KBUILD_MODNAME, cg); |
---|
377 | | - |
---|
378 | | - if (retval) { |
---|
379 | | - dev_warn(&pdev->dev, "request irq failed: %d\n", retval); |
---|
380 | | - return retval; |
---|
381 | | - } |
---|
382 | | - |
---|
383 | | - gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq); |
---|
384 | | - |
---|
385 | | - return 0; |
---|
386 | | -} |
---|
387 | | - |
---|
388 | | -static int crystalcove_gpio_remove(struct platform_device *pdev) |
---|
389 | | -{ |
---|
390 | | - struct crystalcove_gpio *cg = platform_get_drvdata(pdev); |
---|
391 | | - int irq = platform_get_irq(pdev, 0); |
---|
392 | | - |
---|
393 | | - if (irq >= 0) |
---|
394 | | - free_irq(irq, cg); |
---|
395 | 381 | return 0; |
---|
396 | 382 | } |
---|
397 | 383 | |
---|
398 | 384 | static struct platform_driver crystalcove_gpio_driver = { |
---|
399 | 385 | .probe = crystalcove_gpio_probe, |
---|
400 | | - .remove = crystalcove_gpio_remove, |
---|
401 | 386 | .driver = { |
---|
402 | 387 | .name = "crystal_cove_gpio", |
---|
403 | 388 | }, |
---|
404 | 389 | }; |
---|
405 | | - |
---|
406 | 390 | module_platform_driver(crystalcove_gpio_driver); |
---|
407 | 391 | |
---|
408 | 392 | MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>"); |
---|