summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-rcar.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-18 08:22:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-18 08:22:10 -0400
commit510965dd4a0a59504ba38455f77339ea8b4c6a70 (patch)
tree36492629ac68de94457482562660154f28e9e039 /drivers/gpio/gpio-rcar.c
parent40d7839879b4584f91522d841afb22ed401cf40f (diff)
parent03daa6f82f2b634019fe8261698f6af3c133497f (diff)
Merge tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.1 development cycle: - A new GPIO hogging mechanism has been added. This can be used on boards that want to drive some GPIO line high, low, or set it as input on boot and then never touch it again. For some embedded systems this is bliss and simplifies things to a great extent. - Some API cleanup and closure: gpiod_get_array() and gpiod_put_array() has been added to get and put GPIOs in bulk as was possible with the non-descriptor API. - Encapsulate cross-calls to the pin control subsystem in <linux/gpio/driver.h>. Now this should be the only header any GPIO driver needs to include or something is wrong. Cleanups restricting drivers to this include are welcomed if tested. - Sort the GPIO Kconfig and split it into submenus, as it was becoming and unstructured, illogical and unnavigatable mess. I hope this is easier to follow. Menus that require a certain subsystem like I2C can now be hidden nicely for example, still working on others. - New drivers: - New driver for the Altera Soft GPIO. - The F7188x driver now handles the F71869 and F71869A variants. - The MIPS Loongson driver has been moved to drivers/gpio for consolidation and cleanup. - Cleanups: - The MAX732x is converted to use the GPIOLIB_IRQCHIP infrastructure. - The PCF857x is converted to use the GPIOLIB_IRQCHIP infrastructure. - Radical cleanup of the OMAP driver. - Misc: - Enable the DWAPB GPIO for all architectures. This is a "hard IP" block from Synopsys which has started to turn up in so diverse architectures as X86 Quark, ARC and a slew of ARM systems. So even though it's not an expander, it's generic enough to be available for all. - We add a mock GPIO on Crystalcove PMIC after a long discussion with Daniel Vetter et al, tracing back to the shootout at the kernel summit where DRM drivers and sub-componentization was discussed. In this case a mock GPIO is assumed to be the best compromise gaining some reuse of infrastructure without making DRM drivers overly complex at the same time. Let's see" * tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (62 commits) Revert "gpio: sch: use uapi/linux/pci_ids.h directly" gpio: dwapb: remove dependencies gpio: dwapb: enable for ARC gpio: removing kfree remove functionality gpio: mvebu: Fix mask/unmask managment per irq chip type gpio: split GPIO drivers in submenus gpio: move MFD GPIO drivers under their own comment gpio: move BCM Kona Kconfig option gpio: arrange SPI Kconfig symbols alphabetically gpio: arrange PCI GPIO controllers alphabetically gpio: arrange I2C Kconfig symbols alphabetically gpio: arrange Kconfig symbols alphabetically gpio: ich: Implement get_direction function gpio: use (!foo) instead of (foo == NULL) gpio: arizona: drop owner assignment from platform_drivers gpio: max7300: remove 'ret' variable gpio: use devm_kzalloc gpio: sch: use uapi/linux/pci_ids.h directly gpio: x-gene: fix devm_ioremap_resource() check gpio: loongson: Add Loongson-3A/3B GPIO driver support ...
Diffstat (limited to 'drivers/gpio/gpio-rcar.c')
-rw-r--r--drivers/gpio/gpio-rcar.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index c49522efa7b3..fd3977465948 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -14,6 +14,7 @@
* GNU General Public License for more details.
*/
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
@@ -37,20 +38,22 @@ struct gpio_rcar_priv {
struct platform_device *pdev;
struct gpio_chip gpio_chip;
struct irq_chip irq_chip;
+ unsigned int irq_parent;
+ struct clk *clk;
};
-#define IOINTSEL 0x00
-#define INOUTSEL 0x04
-#define OUTDT 0x08
-#define INDT 0x0c
-#define INTDT 0x10
-#define INTCLR 0x14
-#define INTMSK 0x18
-#define MSKCLR 0x1c
-#define POSNEG 0x20
-#define EDGLEVEL 0x24
-#define FILONOFF 0x28
-#define BOTHEDGE 0x4c
+#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
+#define INOUTSEL 0x04 /* General Input/Output Switching Register */
+#define OUTDT 0x08 /* General Output Register */
+#define INDT 0x0c /* General Input Register */
+#define INTDT 0x10 /* Interrupt Display Register */
+#define INTCLR 0x14 /* Interrupt Clear Register */
+#define INTMSK 0x18 /* Interrupt Mask Register */
+#define MSKCLR 0x1c /* Interrupt Mask Clear Register */
+#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
+#define EDGLEVEL 0x24 /* Edge/level Select Register */
+#define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
+#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
#define RCAR_MAX_GPIO_PER_BANK 32
@@ -169,6 +172,25 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
return 0;
}
+static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
+ gpio_chip);
+
+ irq_set_irq_wake(p->irq_parent, on);
+
+ if (!p->clk)
+ return 0;
+
+ if (on)
+ clk_enable(p->clk);
+ else
+ clk_disable(p->clk);
+
+ return 0;
+}
+
static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
{
struct gpio_rcar_priv *p = dev_id;
@@ -367,6 +389,12 @@ static int gpio_rcar_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p);
+ p->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(p->clk)) {
+ dev_warn(dev, "unable to get clock\n");
+ p->clk = NULL;
+ }
+
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
@@ -404,8 +432,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
irq_chip->irq_mask = gpio_rcar_irq_disable;
irq_chip->irq_unmask = gpio_rcar_irq_enable;
irq_chip->irq_set_type = gpio_rcar_irq_set_type;
- irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED
- | IRQCHIP_MASK_ON_SUSPEND;
+ irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
+ irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
ret = gpiochip_add(gpio_chip);
if (ret) {
@@ -413,13 +441,14 @@ static int gpio_rcar_probe(struct platform_device *pdev)
goto err0;
}
- ret = gpiochip_irqchip_add(&p->gpio_chip, irq_chip, p->config.irq_base,
+ ret = gpiochip_irqchip_add(gpio_chip, irq_chip, p->config.irq_base,
handle_level_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "cannot add irqchip\n");
goto err1;
}
+ p->irq_parent = irq->start;
if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler,
IRQF_SHARED, name, p)) {
dev_err(dev, "failed to request IRQ\n");
@@ -431,7 +460,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
/* warn in case of mismatch if irq base is specified */
if (p->config.irq_base) {
- ret = irq_find_mapping(p->gpio_chip.irqdomain, 0);
+ ret = irq_find_mapping(gpio_chip->irqdomain, 0);
if (p->config.irq_base != ret)
dev_warn(dev, "irq base mismatch (%u/%u)\n",
p->config.irq_base, ret);
@@ -447,7 +476,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
return 0;
err1:
- gpiochip_remove(&p->gpio_chip);
+ gpiochip_remove(gpio_chip);
err0:
pm_runtime_put(dev);
pm_runtime_disable(dev);