Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio-tz1090-pdc: add TZ1090 PDC gpio driver

Add a GPIO driver for the low-power Powerdown Controller GPIOs in the
TZ1090 SoC.

The driver is instantiated by device tree and supports interrupts for
the SysWake GPIOs only.

Changes in v4:
- fix typos in DT bindings compatible properties
- reference Documentation/devicetree/bindings/gpio/gpio.txt in
gpio-ranges description in DT bindings
- fix gpio-ranges examples in DT bindings (it must now have 3 cells)

Changes in v3:
- separated from irq-imgpdc and removed arch/metag changes to allow
these patches to go upstream separately via the pinctrl[/gpio] trees
(particularly the pinctrl drivers depend on the new pinconf DT
bindings).
- some s/unsigned/unsigned int/.
- gpio-tz1090*: refer to <dt-bindings/gpio/gpio.h> and
<dt-bindings/interrupt-controller/irq.h> flags in bindings.
- gpio-tz1090*: move initcall from postcore to subsys.

Changes in v2:
- gpio-tz1090-pdc: remove references to Linux flags in dt bindings
- gpio-tz1090-pdc: make use of BIT() from linux/bitops.h
- gpio-tz1090-pdc: make register accessors inline to match pinctrl
- gpio-tz1090-pdc: update gpio-ranges to use 3 cells after recent ABI
breakage

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-doc@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

James Hogan and committed by
Linus Walleij
79bb6460 9caf1f22

+296
+45
Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt
··· 1 + ImgTec TZ1090 PDC GPIO Controller 2 + 3 + Required properties: 4 + - compatible: Compatible property value should be "img,tz1090-pdc-gpio". 5 + 6 + - reg: Physical base address of the controller and length of memory mapped 7 + region. This starts at and cover the SOC_GPIO_CONTROL registers. 8 + 9 + - gpio-controller: Specifies that the node is a gpio controller. 10 + 11 + - #gpio-cells: Should be 2. The syntax of the gpio specifier used by client 12 + nodes should have the following values. 13 + <[phandle of the gpio controller node] 14 + [PDC gpio number] 15 + [gpio flags]> 16 + 17 + Values for gpio specifier: 18 + - GPIO number: a value in the range 0 to 6. 19 + - GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>. 20 + Only the following flags are supported: 21 + GPIO_ACTIVE_HIGH 22 + GPIO_ACTIVE_LOW 23 + 24 + Optional properties: 25 + - gpio-ranges: Mapping to pin controller pins (as described in 26 + Documentation/devicetree/bindings/gpio/gpio.txt) 27 + 28 + - interrupts: Individual syswake interrupts (other GPIOs cannot interrupt) 29 + 30 + 31 + Example: 32 + 33 + pdc_gpios: gpio-controller@02006500 { 34 + gpio-controller; 35 + #gpio-cells = <2>; 36 + 37 + compatible = "img,tz1090-pdc-gpio"; 38 + reg = <0x02006500 0x100>; 39 + 40 + interrupt-parent = <&pdc>; 41 + interrupts = <8 IRQ_TYPE_NONE>, /* Syswake 0 */ 42 + <9 IRQ_TYPE_NONE>, /* Syswake 1 */ 43 + <10 IRQ_TYPE_NONE>; /* Syswake 2 */ 44 + gpio-ranges = <&pdc_pinctrl 0 0 7>; 45 + };
+7
drivers/gpio/Kconfig
··· 249 249 help 250 250 Say yes here to support Toumaz Xenif TZ1090 GPIOs. 251 251 252 + config GPIO_TZ1090_PDC 253 + bool "Toumaz Xenif TZ1090 PDC GPIO support" 254 + depends on SOC_TZ1090 255 + default y 256 + help 257 + Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs. 258 + 252 259 config GPIO_XILINX 253 260 bool "Xilinx GPIO support" 254 261 depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
+1
drivers/gpio/Makefile
··· 80 80 obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o 81 81 obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o 82 82 obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o 83 + obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o 83 84 obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o 84 85 obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o 85 86 obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
+243
drivers/gpio/gpio-tz1090-pdc.c
··· 1 + /* 2 + * Toumaz Xenif TZ1090 PDC GPIO handling. 3 + * 4 + * Copyright (C) 2012-2013 Imagination Technologies Ltd. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/bitops.h> 12 + #include <linux/gpio.h> 13 + #include <linux/io.h> 14 + #include <linux/module.h> 15 + #include <linux/of_irq.h> 16 + #include <linux/pinctrl/consumer.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/slab.h> 19 + #include <linux/syscore_ops.h> 20 + #include <asm/global_lock.h> 21 + 22 + /* Register offsets from SOC_GPIO_CONTROL0 */ 23 + #define REG_SOC_GPIO_CONTROL0 0x00 24 + #define REG_SOC_GPIO_CONTROL1 0x04 25 + #define REG_SOC_GPIO_CONTROL2 0x08 26 + #define REG_SOC_GPIO_CONTROL3 0x0c 27 + #define REG_SOC_GPIO_STATUS 0x80 28 + 29 + /* PDC GPIOs go after normal GPIOs */ 30 + #define GPIO_PDC_BASE 90 31 + #define GPIO_PDC_NGPIO 7 32 + 33 + /* Out of PDC gpios, only syswakes have irqs */ 34 + #define GPIO_PDC_IRQ_FIRST 2 35 + #define GPIO_PDC_NIRQ 3 36 + 37 + /** 38 + * struct tz1090_pdc_gpio - GPIO bank private data 39 + * @chip: Generic GPIO chip for GPIO bank 40 + * @reg: Base of registers, offset for this GPIO bank 41 + * @irq: IRQ numbers for Syswake GPIOs 42 + * 43 + * This is the main private data for the PDC GPIO driver. It encapsulates a 44 + * gpio_chip, and the callbacks for the gpio_chip can access the private data 45 + * with the to_pdc() macro below. 46 + */ 47 + struct tz1090_pdc_gpio { 48 + struct gpio_chip chip; 49 + void __iomem *reg; 50 + int irq[GPIO_PDC_NIRQ]; 51 + }; 52 + #define to_pdc(c) container_of(c, struct tz1090_pdc_gpio, chip) 53 + 54 + /* Register accesses into the PDC MMIO area */ 55 + 56 + static inline void pdc_write(struct tz1090_pdc_gpio *priv, unsigned int reg_offs, 57 + unsigned int data) 58 + { 59 + writel(data, priv->reg + reg_offs); 60 + } 61 + 62 + static inline unsigned int pdc_read(struct tz1090_pdc_gpio *priv, 63 + unsigned int reg_offs) 64 + { 65 + return readl(priv->reg + reg_offs); 66 + } 67 + 68 + /* Generic GPIO interface */ 69 + 70 + static int tz1090_pdc_gpio_direction_input(struct gpio_chip *chip, 71 + unsigned int offset) 72 + { 73 + struct tz1090_pdc_gpio *priv = to_pdc(chip); 74 + u32 value; 75 + int lstat; 76 + 77 + __global_lock2(lstat); 78 + value = pdc_read(priv, REG_SOC_GPIO_CONTROL1); 79 + value |= BIT(offset); 80 + pdc_write(priv, REG_SOC_GPIO_CONTROL1, value); 81 + __global_unlock2(lstat); 82 + 83 + return 0; 84 + } 85 + 86 + static int tz1090_pdc_gpio_direction_output(struct gpio_chip *chip, 87 + unsigned int offset, 88 + int output_value) 89 + { 90 + struct tz1090_pdc_gpio *priv = to_pdc(chip); 91 + u32 value; 92 + int lstat; 93 + 94 + __global_lock2(lstat); 95 + /* EXT_POWER doesn't seem to have an output value bit */ 96 + if (offset < 6) { 97 + value = pdc_read(priv, REG_SOC_GPIO_CONTROL0); 98 + if (output_value) 99 + value |= BIT(offset); 100 + else 101 + value &= ~BIT(offset); 102 + pdc_write(priv, REG_SOC_GPIO_CONTROL0, value); 103 + } 104 + 105 + value = pdc_read(priv, REG_SOC_GPIO_CONTROL1); 106 + value &= ~BIT(offset); 107 + pdc_write(priv, REG_SOC_GPIO_CONTROL1, value); 108 + __global_unlock2(lstat); 109 + 110 + return 0; 111 + } 112 + 113 + static int tz1090_pdc_gpio_get(struct gpio_chip *chip, unsigned int offset) 114 + { 115 + struct tz1090_pdc_gpio *priv = to_pdc(chip); 116 + return pdc_read(priv, REG_SOC_GPIO_STATUS) & BIT(offset); 117 + } 118 + 119 + static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset, 120 + int output_value) 121 + { 122 + struct tz1090_pdc_gpio *priv = to_pdc(chip); 123 + u32 value; 124 + int lstat; 125 + 126 + /* EXT_POWER doesn't seem to have an output value bit */ 127 + if (offset >= 6) 128 + return; 129 + 130 + __global_lock2(lstat); 131 + value = pdc_read(priv, REG_SOC_GPIO_CONTROL0); 132 + if (output_value) 133 + value |= BIT(offset); 134 + else 135 + value &= ~BIT(offset); 136 + pdc_write(priv, REG_SOC_GPIO_CONTROL0, value); 137 + __global_unlock2(lstat); 138 + } 139 + 140 + static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset) 141 + { 142 + return pinctrl_request_gpio(chip->base + offset); 143 + } 144 + 145 + static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset) 146 + { 147 + pinctrl_free_gpio(chip->base + offset); 148 + } 149 + 150 + static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) 151 + { 152 + struct tz1090_pdc_gpio *priv = to_pdc(chip); 153 + unsigned int syswake = offset - GPIO_PDC_IRQ_FIRST; 154 + int irq; 155 + 156 + /* only syswakes have irqs */ 157 + if (syswake >= GPIO_PDC_NIRQ) 158 + return -EINVAL; 159 + 160 + irq = priv->irq[syswake]; 161 + if (!irq) 162 + return -EINVAL; 163 + 164 + return irq; 165 + } 166 + 167 + static int tz1090_pdc_gpio_probe(struct platform_device *pdev) 168 + { 169 + struct device_node *np = pdev->dev.of_node; 170 + struct resource *res_regs; 171 + struct tz1090_pdc_gpio *priv; 172 + unsigned int i; 173 + 174 + if (!np) { 175 + dev_err(&pdev->dev, "must be instantiated via devicetree\n"); 176 + return -ENOENT; 177 + } 178 + 179 + res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 180 + if (!res_regs) { 181 + dev_err(&pdev->dev, "cannot find registers resource\n"); 182 + return -ENOENT; 183 + } 184 + 185 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 186 + if (!priv) { 187 + dev_err(&pdev->dev, "unable to allocate driver data\n"); 188 + return -ENOMEM; 189 + } 190 + 191 + /* Ioremap the registers */ 192 + priv->reg = devm_ioremap(&pdev->dev, res_regs->start, 193 + res_regs->end - res_regs->start); 194 + if (!priv->reg) { 195 + dev_err(&pdev->dev, "unable to ioremap registers\n"); 196 + return -ENOMEM; 197 + } 198 + 199 + /* Set up GPIO chip */ 200 + priv->chip.label = "tz1090-pdc-gpio"; 201 + priv->chip.dev = &pdev->dev; 202 + priv->chip.direction_input = tz1090_pdc_gpio_direction_input; 203 + priv->chip.direction_output = tz1090_pdc_gpio_direction_output; 204 + priv->chip.get = tz1090_pdc_gpio_get; 205 + priv->chip.set = tz1090_pdc_gpio_set; 206 + priv->chip.free = tz1090_pdc_gpio_free; 207 + priv->chip.request = tz1090_pdc_gpio_request; 208 + priv->chip.to_irq = tz1090_pdc_gpio_to_irq; 209 + priv->chip.of_node = np; 210 + 211 + /* GPIO numbering */ 212 + priv->chip.base = GPIO_PDC_BASE; 213 + priv->chip.ngpio = GPIO_PDC_NGPIO; 214 + 215 + /* Map the syswake irqs */ 216 + for (i = 0; i < GPIO_PDC_NIRQ; ++i) 217 + priv->irq[i] = irq_of_parse_and_map(np, i); 218 + 219 + /* Add the GPIO bank */ 220 + gpiochip_add(&priv->chip); 221 + 222 + return 0; 223 + } 224 + 225 + static struct of_device_id tz1090_pdc_gpio_of_match[] = { 226 + { .compatible = "img,tz1090-pdc-gpio" }, 227 + { }, 228 + }; 229 + 230 + static struct platform_driver tz1090_pdc_gpio_driver = { 231 + .driver = { 232 + .name = "tz1090-pdc-gpio", 233 + .owner = THIS_MODULE, 234 + .of_match_table = tz1090_pdc_gpio_of_match, 235 + }, 236 + .probe = tz1090_pdc_gpio_probe, 237 + }; 238 + 239 + static int __init tz1090_pdc_gpio_init(void) 240 + { 241 + return platform_driver_register(&tz1090_pdc_gpio_driver); 242 + } 243 + subsys_initcall(tz1090_pdc_gpio_init);