| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/drivers/gpio/gpio-mb86s7x.c |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2015 Fujitsu Semiconductor Limited |
|---|
| 5 | 6 | * Copyright (C) 2015 Linaro Ltd. |
|---|
| 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, version 2 of the License. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | 7 | */ |
|---|
| 16 | 8 | |
|---|
| 9 | +#include <linux/acpi.h> |
|---|
| 17 | 10 | #include <linux/io.h> |
|---|
| 18 | 11 | #include <linux/init.h> |
|---|
| 19 | 12 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 26 | 19 | #include <linux/platform_device.h> |
|---|
| 27 | 20 | #include <linux/spinlock.h> |
|---|
| 28 | 21 | #include <linux/slab.h> |
|---|
| 22 | + |
|---|
| 23 | +#include "gpiolib.h" |
|---|
| 24 | +#include "gpiolib-acpi.h" |
|---|
| 29 | 25 | |
|---|
| 30 | 26 | /* |
|---|
| 31 | 27 | * Only first 8bits of a register correspond to each pin, |
|---|
| .. | .. |
|---|
| 143 | 139 | spin_unlock_irqrestore(&gchip->lock, flags); |
|---|
| 144 | 140 | } |
|---|
| 145 | 141 | |
|---|
| 142 | +static int mb86s70_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) |
|---|
| 143 | +{ |
|---|
| 144 | + int irq, index; |
|---|
| 145 | + |
|---|
| 146 | + for (index = 0;; index++) { |
|---|
| 147 | + irq = platform_get_irq(to_platform_device(gc->parent), index); |
|---|
| 148 | + if (irq < 0) |
|---|
| 149 | + return irq; |
|---|
| 150 | + if (irq == 0) |
|---|
| 151 | + break; |
|---|
| 152 | + if (irq_get_irq_data(irq)->hwirq == offset) |
|---|
| 153 | + return irq; |
|---|
| 154 | + } |
|---|
| 155 | + return -EINVAL; |
|---|
| 156 | +} |
|---|
| 157 | + |
|---|
| 146 | 158 | static int mb86s70_gpio_probe(struct platform_device *pdev) |
|---|
| 147 | 159 | { |
|---|
| 148 | 160 | struct mb86s70_gpio_chip *gchip; |
|---|
| 149 | | - struct resource *res; |
|---|
| 150 | 161 | int ret; |
|---|
| 151 | 162 | |
|---|
| 152 | 163 | gchip = devm_kzalloc(&pdev->dev, sizeof(*gchip), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 155 | 166 | |
|---|
| 156 | 167 | platform_set_drvdata(pdev, gchip); |
|---|
| 157 | 168 | |
|---|
| 158 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 159 | | - gchip->base = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 169 | + gchip->base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 160 | 170 | if (IS_ERR(gchip->base)) |
|---|
| 161 | 171 | return PTR_ERR(gchip->base); |
|---|
| 162 | 172 | |
|---|
| 163 | | - gchip->clk = devm_clk_get(&pdev->dev, NULL); |
|---|
| 173 | + gchip->clk = devm_clk_get_optional(&pdev->dev, NULL); |
|---|
| 164 | 174 | if (IS_ERR(gchip->clk)) |
|---|
| 165 | 175 | return PTR_ERR(gchip->clk); |
|---|
| 166 | 176 | |
|---|
| .. | .. |
|---|
| 176 | 186 | gchip->gc.free = mb86s70_gpio_free; |
|---|
| 177 | 187 | gchip->gc.get = mb86s70_gpio_get; |
|---|
| 178 | 188 | gchip->gc.set = mb86s70_gpio_set; |
|---|
| 189 | + gchip->gc.to_irq = mb86s70_gpio_to_irq; |
|---|
| 179 | 190 | gchip->gc.label = dev_name(&pdev->dev); |
|---|
| 180 | 191 | gchip->gc.ngpio = 32; |
|---|
| 181 | 192 | gchip->gc.owner = THIS_MODULE; |
|---|
| .. | .. |
|---|
| 186 | 197 | if (ret) { |
|---|
| 187 | 198 | dev_err(&pdev->dev, "couldn't register gpio driver\n"); |
|---|
| 188 | 199 | clk_disable_unprepare(gchip->clk); |
|---|
| 200 | + return ret; |
|---|
| 189 | 201 | } |
|---|
| 190 | 202 | |
|---|
| 191 | | - return ret; |
|---|
| 203 | + acpi_gpiochip_request_interrupts(&gchip->gc); |
|---|
| 204 | + |
|---|
| 205 | + return 0; |
|---|
| 192 | 206 | } |
|---|
| 193 | 207 | |
|---|
| 194 | 208 | static int mb86s70_gpio_remove(struct platform_device *pdev) |
|---|
| 195 | 209 | { |
|---|
| 196 | 210 | struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev); |
|---|
| 197 | 211 | |
|---|
| 212 | + acpi_gpiochip_free_interrupts(&gchip->gc); |
|---|
| 198 | 213 | gpiochip_remove(&gchip->gc); |
|---|
| 199 | 214 | clk_disable_unprepare(gchip->clk); |
|---|
| 200 | 215 | |
|---|
| .. | .. |
|---|
| 207 | 222 | }; |
|---|
| 208 | 223 | MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids); |
|---|
| 209 | 224 | |
|---|
| 225 | +#ifdef CONFIG_ACPI |
|---|
| 226 | +static const struct acpi_device_id mb86s70_gpio_acpi_ids[] = { |
|---|
| 227 | + { "SCX0007" }, |
|---|
| 228 | + { /* sentinel */ } |
|---|
| 229 | +}; |
|---|
| 230 | +MODULE_DEVICE_TABLE(acpi, mb86s70_gpio_acpi_ids); |
|---|
| 231 | +#endif |
|---|
| 232 | + |
|---|
| 210 | 233 | static struct platform_driver mb86s70_gpio_driver = { |
|---|
| 211 | 234 | .driver = { |
|---|
| 212 | 235 | .name = "mb86s70-gpio", |
|---|
| 213 | 236 | .of_match_table = mb86s70_gpio_dt_ids, |
|---|
| 237 | + .acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids), |
|---|
| 214 | 238 | }, |
|---|
| 215 | 239 | .probe = mb86s70_gpio_probe, |
|---|
| 216 | 240 | .remove = mb86s70_gpio_remove, |
|---|