brcm2708: remove linux 4.1 support
[openwrt.git] / target / linux / brcm2708 / patches-4.1 / 0002-Add-bcm2708_gpio-driver.patch
diff --git a/target/linux/brcm2708/patches-4.1/0002-Add-bcm2708_gpio-driver.patch b/target/linux/brcm2708/patches-4.1/0002-Add-bcm2708_gpio-driver.patch
deleted file mode 100644 (file)
index a735798..0000000
+++ /dev/null
@@ -1,615 +0,0 @@
-From c7eee1285590f15010feaf91970b9e3447e757f4 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Wed, 8 Oct 2014 18:50:05 +0100
-Subject: [PATCH 002/222] Add bcm2708_gpio driver
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
-
-bcm2708: Add extension to configure internal pulls
-
-The bcm2708 gpio controller supports internal pulls to be used as pull-up,
-pull-down or being entirely disabled. As it can be useful for a driver to
-change the pull configuration from it's default pull-down state, add an
-extension which allows configuring the pull per gpio.
-
-Signed-off-by: Julian Scheel <julian@jusst.de>
-
-bcm2708-gpio: Revert the use of pinctrl_request_gpio
-
-In non-DT systems, pinctrl_request_gpio always fails causing
-"requests probe deferral" messages. In DT systems, it isn't useful
-because the reference counting is independent of the normal pinctrl
-pin reservations.
-
-gpio: Only clear the currently occurring interrupt. Avoids losing interrupts
-
-See: linux #760
-
-bcm2708_gpio: Avoid calling irq_unmask for all interrupts
-
-When setting up the interrupts, specify that the handle_simple_irq
-handler should be used. This leaves interrupt acknowledgement to
-the caller, and prevents irq_unmask from being called for all
-interrupts.
-
-Issue: linux #760
----
- arch/arm/mach-bcm2708/Kconfig             |   8 +
- arch/arm/mach-bcm2708/Makefile            |   1 +
- arch/arm/mach-bcm2708/bcm2708.c           |  25 ++
- arch/arm/mach-bcm2708/bcm2708_gpio.c      | 426 ++++++++++++++++++++++++++++++
- arch/arm/mach-bcm2708/include/mach/gpio.h |  17 ++
- arch/arm/mach-bcm2709/bcm2709.c           |  25 ++
- include/linux/platform_data/bcm2708.h     |  23 ++
- 7 files changed, 525 insertions(+)
- create mode 100644 arch/arm/mach-bcm2708/bcm2708_gpio.c
- create mode 100644 arch/arm/mach-bcm2708/include/mach/gpio.h
- create mode 100644 include/linux/platform_data/bcm2708.h
-
---- a/arch/arm/mach-bcm2708/Kconfig
-+++ b/arch/arm/mach-bcm2708/Kconfig
-@@ -20,6 +20,14 @@ config BCM2708_DT
-       help
-         Enable Device Tree support for BCM2708
-+config BCM2708_GPIO
-+      bool "BCM2708 gpio support"
-+      depends on MACH_BCM2708
-+      select ARCH_REQUIRE_GPIOLIB
-+        default y
-+      help
-+        Include support for the Broadcom(R) BCM2708 gpio.
-+
- config BCM2708_NOL2CACHE
-       bool "Videocore L2 cache disable"
-       depends on MACH_BCM2708
---- a/arch/arm/mach-bcm2708/Makefile
-+++ b/arch/arm/mach-bcm2708/Makefile
-@@ -3,3 +3,4 @@
- #
- obj-$(CONFIG_MACH_BCM2708)    += bcm2708.o armctrl.o
-+obj-$(CONFIG_BCM2708_GPIO)    += bcm2708_gpio.o
---- a/arch/arm/mach-bcm2708/bcm2708.c
-+++ b/arch/arm/mach-bcm2708/bcm2708.c
-@@ -298,6 +298,31 @@ static struct platform_device bcm2708_vc
-               },
- };
-+#ifdef CONFIG_BCM2708_GPIO
-+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
-+
-+static struct resource bcm2708_gpio_resources[] = {
-+      [0] = {                 /* general purpose I/O */
-+             .start = GPIO_BASE,
-+             .end = GPIO_BASE + SZ_4K - 1,
-+             .flags = IORESOURCE_MEM,
-+             },
-+};
-+
-+static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
-+
-+static struct platform_device bcm2708_gpio_device = {
-+      .name = BCM_GPIO_DRIVER_NAME,
-+      .id = -1,               /* only one VideoCore I/O area */
-+      .resource = bcm2708_gpio_resources,
-+      .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
-+      .dev = {
-+              .dma_mask = &gpio_dmamask,
-+              .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
-+              },
-+};
-+#endif
-+
- int __init bcm_register_device(struct platform_device *pdev)
- {
-       int ret;
---- /dev/null
-+++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c
-@@ -0,0 +1,426 @@
-+/*
-+ *  linux/arch/arm/mach-bcm2708/bcm2708_gpio.c
-+ *
-+ *  Copyright (C) 2010 Broadcom
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/spinlock.h>
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/list.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <mach/gpio.h>
-+#include <linux/gpio.h>
-+#include <linux/platform_device.h>
-+#include <mach/platform.h>
-+#include <linux/pinctrl/consumer.h>
-+
-+#include <linux/platform_data/bcm2708.h>
-+
-+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
-+#define DRIVER_NAME BCM_GPIO_DRIVER_NAME
-+#define BCM_GPIO_USE_IRQ 1
-+
-+#define GPIOFSEL(x)  (0x00+(x)*4)
-+#define GPIOSET(x)   (0x1c+(x)*4)
-+#define GPIOCLR(x)   (0x28+(x)*4)
-+#define GPIOLEV(x)   (0x34+(x)*4)
-+#define GPIOEDS(x)   (0x40+(x)*4)
-+#define GPIOREN(x)   (0x4c+(x)*4)
-+#define GPIOFEN(x)   (0x58+(x)*4)
-+#define GPIOHEN(x)   (0x64+(x)*4)
-+#define GPIOLEN(x)   (0x70+(x)*4)
-+#define GPIOAREN(x)  (0x7c+(x)*4)
-+#define GPIOAFEN(x)  (0x88+(x)*4)
-+#define GPIOUD(x)    (0x94+(x)*4)
-+#define GPIOUDCLK(x) (0x98+(x)*4)
-+
-+#define GPIO_BANKS 2
-+
-+enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT,
-+      GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4,
-+      GPIO_FSEL_ALT0, GPIO_FSEL_ALT1,
-+      GPIO_FSEL_ALT2, GPIO_FSEL_ALT3,
-+};
-+
-+      /* Each of the two spinlocks protects a different set of hardware
-+       * regiters and data structurs. This decouples the code of the IRQ from
-+       * the GPIO code. This also makes the case of a GPIO routine call from
-+       * the IRQ code simpler.
-+       */
-+static DEFINE_SPINLOCK(lock); /* GPIO registers */
-+
-+struct bcm2708_gpio {
-+      struct list_head list;
-+      void __iomem *base;
-+      struct gpio_chip gc;
-+      unsigned long rising[(BCM2708_NR_GPIOS + 31) / 32];
-+      unsigned long falling[(BCM2708_NR_GPIOS + 31) / 32];
-+      unsigned long high[(BCM2708_NR_GPIOS + 31) / 32];
-+      unsigned long low[(BCM2708_NR_GPIOS + 31) / 32];
-+};
-+
-+static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
-+                              int function)
-+{
-+      struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
-+      unsigned long flags;
-+      unsigned gpiodir;
-+      unsigned gpio_bank = offset / 10;
-+      unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;
-+
-+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function);
-+      if (offset >= BCM2708_NR_GPIOS)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&lock, flags);
-+
-+      gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));
-+      gpiodir &= ~(7 << gpio_field_offset);
-+      gpiodir |= function << gpio_field_offset;
-+      writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank));
-+      spin_unlock_irqrestore(&lock, flags);
-+      gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));
-+
-+      return 0;
-+}
-+
-+static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset)
-+{
-+      return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT);
-+}
-+
-+static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value);
-+static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset,
-+                              int value)
-+{
-+      int ret;
-+      ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT);
-+      if (ret >= 0)
-+              bcm2708_gpio_set(gc, offset, value);
-+      return ret;
-+}
-+
-+static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset)
-+{
-+      struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
-+      unsigned gpio_bank = offset / 32;
-+      unsigned gpio_field_offset = (offset - 32 * gpio_bank);
-+      unsigned lev;
-+
-+      if (offset >= BCM2708_NR_GPIOS)
-+              return 0;
-+      lev = readl(gpio->base + GPIOLEV(gpio_bank));
-+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset));
-+      return 0x1 & (lev >> gpio_field_offset);
-+}
-+
-+static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
-+{
-+      struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
-+      unsigned gpio_bank = offset / 32;
-+      unsigned gpio_field_offset = (offset - 32 * gpio_bank);
-+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value);
-+      if (offset >= BCM2708_NR_GPIOS)
-+              return;
-+      if (value)
-+              writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank));
-+      else
-+              writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank));
-+}
-+
-+/**********************
-+ * extension to configure pullups
-+ */
-+int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset,
-+              bcm2708_gpio_pull_t value)
-+{
-+      struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
-+      unsigned gpio_bank = offset / 32;
-+      unsigned gpio_field_offset = (offset - 32 * gpio_bank);
-+
-+      if (offset >= BCM2708_NR_GPIOS)
-+              return -EINVAL;
-+
-+      switch (value) {
-+      case BCM2708_PULL_UP:
-+              writel(2, gpio->base + GPIOUD(0));
-+              break;
-+      case BCM2708_PULL_DOWN:
-+              writel(1, gpio->base + GPIOUD(0));
-+              break;
-+      case BCM2708_PULL_OFF:
-+              writel(0, gpio->base + GPIOUD(0));
-+              break;
-+      }
-+
-+      udelay(5);
-+      writel(1 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank));
-+      udelay(5);
-+      writel(0, gpio->base + GPIOUD(0));
-+      writel(0 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank));
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(bcm2708_gpio_setpull);
-+
-+/*************************************************************************************************************************
-+ * bcm2708 GPIO IRQ
-+ */
-+
-+#if BCM_GPIO_USE_IRQ
-+
-+static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
-+{
-+      return gpio_to_irq(gpio);
-+}
-+
-+static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type)
-+{
-+      unsigned irq = d->irq;
-+      struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
-+      unsigned gn = irq_to_gpio(irq);
-+      unsigned gb = gn / 32;
-+      unsigned go = gn % 32;
-+
-+      gpio->rising[gb]  &= ~(1 << go);
-+      gpio->falling[gb] &= ~(1 << go);
-+      gpio->high[gb]    &= ~(1 << go);
-+      gpio->low[gb]     &= ~(1 << go);
-+
-+      if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-+              return -EINVAL;
-+
-+      if (type & IRQ_TYPE_EDGE_RISING)
-+              gpio->rising[gb] |= (1 << go);
-+      if (type & IRQ_TYPE_EDGE_FALLING)
-+              gpio->falling[gb] |= (1 << go);
-+      if (type & IRQ_TYPE_LEVEL_HIGH)
-+              gpio->high[gb] |= (1 << go);
-+      if (type & IRQ_TYPE_LEVEL_LOW)
-+              gpio->low[gb] |= (1 << go);
-+      return 0;
-+}
-+
-+static void bcm2708_gpio_irq_mask(struct irq_data *d)
-+{
-+      unsigned irq = d->irq;
-+      struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
-+      unsigned gn = irq_to_gpio(irq);
-+      unsigned gb = gn / 32;
-+      unsigned long rising  = readl(gpio->base + GPIOREN(gb));
-+      unsigned long falling = readl(gpio->base + GPIOFEN(gb));
-+      unsigned long high    = readl(gpio->base + GPIOHEN(gb));
-+      unsigned long low     = readl(gpio->base + GPIOLEN(gb));
-+
-+      gn = gn % 32;
-+
-+      writel(rising  & ~(1 << gn), gpio->base + GPIOREN(gb));
-+      writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
-+      writel(high    & ~(1 << gn), gpio->base + GPIOHEN(gb));
-+      writel(low     & ~(1 << gn), gpio->base + GPIOLEN(gb));
-+}
-+
-+static void bcm2708_gpio_irq_unmask(struct irq_data *d)
-+{
-+      unsigned irq = d->irq;
-+      struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
-+      unsigned gn = irq_to_gpio(irq);
-+      unsigned gb = gn / 32;
-+      unsigned go = gn % 32;
-+      unsigned long rising  = readl(gpio->base + GPIOREN(gb));
-+      unsigned long falling = readl(gpio->base + GPIOFEN(gb));
-+      unsigned long high    = readl(gpio->base + GPIOHEN(gb));
-+      unsigned long low     = readl(gpio->base + GPIOLEN(gb));
-+
-+      if (gpio->rising[gb] & (1 << go)) {
-+              writel(rising |  (1 << go), gpio->base + GPIOREN(gb));
-+      } else {
-+              writel(rising & ~(1 << go), gpio->base + GPIOREN(gb));
-+      }
-+
-+      if (gpio->falling[gb] & (1 << go)) {
-+              writel(falling |  (1 << go), gpio->base + GPIOFEN(gb));
-+      } else {
-+              writel(falling & ~(1 << go), gpio->base + GPIOFEN(gb));
-+      }
-+
-+      if (gpio->high[gb] & (1 << go)) {
-+              writel(high |  (1 << go), gpio->base + GPIOHEN(gb));
-+      } else {
-+              writel(high & ~(1 << go), gpio->base + GPIOHEN(gb));
-+      }
-+
-+      if (gpio->low[gb] & (1 << go)) {
-+              writel(low |  (1 << go), gpio->base + GPIOLEN(gb));
-+      } else {
-+              writel(low & ~(1 << go), gpio->base + GPIOLEN(gb));
-+      }
-+}
-+
-+static struct irq_chip bcm2708_irqchip = {
-+      .name = "GPIO",
-+      .irq_enable = bcm2708_gpio_irq_unmask,
-+      .irq_disable = bcm2708_gpio_irq_mask,
-+      .irq_unmask = bcm2708_gpio_irq_unmask,
-+      .irq_mask = bcm2708_gpio_irq_mask,
-+      .irq_set_type = bcm2708_gpio_irq_set_type,
-+};
-+
-+static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id)
-+{
-+      unsigned long edsr;
-+      unsigned bank;
-+      int i;
-+      unsigned gpio;
-+      unsigned level_bits;
-+      struct bcm2708_gpio *gpio_data = dev_id;
-+
-+      for (bank = 0; bank < GPIO_BANKS; bank++) {
-+              edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank));
-+              level_bits = gpio_data->high[bank] | gpio_data->low[bank];
-+
-+              for_each_set_bit(i, &edsr, 32) {
-+                      gpio = i + bank * 32;
-+                      /* ack edge triggered IRQs immediately */
-+                      if (!(level_bits & (1<<i)))
-+                              writel(1<<i,
-+                                     __io_address(GPIO_BASE) + GPIOEDS(bank));
-+                      generic_handle_irq(gpio_to_irq(gpio));
-+                      /* ack level triggered IRQ after handling them */
-+                      if (level_bits & (1<<i))
-+                              writel(1<<i,
-+                                     __io_address(GPIO_BASE) + GPIOEDS(bank));
-+              }
-+      }
-+      return IRQ_HANDLED;
-+}
-+
-+static struct irqaction bcm2708_gpio_irq = {
-+      .name = "BCM2708 GPIO catchall handler",
-+      .flags = IRQF_TIMER | IRQF_IRQPOLL,
-+      .handler = bcm2708_gpio_interrupt,
-+};
-+
-+static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
-+{
-+      unsigned irq;
-+
-+      ucb->gc.to_irq = bcm2708_gpio_to_irq;
-+
-+      for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) {
-+              irq_set_chip_data(irq, ucb);
-+              irq_set_chip_and_handler(irq, &bcm2708_irqchip,
-+                                       handle_simple_irq);
-+              set_irq_flags(irq, IRQF_VALID);
-+      }
-+
-+      bcm2708_gpio_irq.dev_id = ucb;
-+      setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq);
-+}
-+
-+#else
-+
-+static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
-+{
-+}
-+
-+#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */
-+
-+static int bcm2708_gpio_probe(struct platform_device *dev)
-+{
-+      struct bcm2708_gpio *ucb;
-+      struct resource *res;
-+      int bank;
-+      int err = 0;
-+
-+      printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev);
-+
-+      ucb = kzalloc(sizeof(*ucb), GFP_KERNEL);
-+      if (NULL == ucb) {
-+              printk(KERN_ERR DRIVER_NAME ": failed to allocate "
-+                     "mailbox memory\n");
-+              err = -ENOMEM;
-+              goto err;
-+      }
-+
-+      res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-+
-+      platform_set_drvdata(dev, ucb);
-+      ucb->base = __io_address(GPIO_BASE);
-+
-+      ucb->gc.label = "bcm2708_gpio";
-+      ucb->gc.base = 0;
-+      ucb->gc.ngpio = BCM2708_NR_GPIOS;
-+      ucb->gc.owner = THIS_MODULE;
-+
-+      ucb->gc.direction_input = bcm2708_gpio_dir_in;
-+      ucb->gc.direction_output = bcm2708_gpio_dir_out;
-+      ucb->gc.get = bcm2708_gpio_get;
-+      ucb->gc.set = bcm2708_gpio_set;
-+      ucb->gc.can_sleep = 0;
-+
-+      for (bank = 0; bank < GPIO_BANKS; bank++) {
-+              writel(0, ucb->base + GPIOREN(bank));
-+              writel(0, ucb->base + GPIOFEN(bank));
-+              writel(0, ucb->base + GPIOHEN(bank));
-+              writel(0, ucb->base + GPIOLEN(bank));
-+              writel(0, ucb->base + GPIOAREN(bank));
-+              writel(0, ucb->base + GPIOAFEN(bank));
-+              writel(~0, ucb->base + GPIOEDS(bank));
-+      }
-+
-+      bcm2708_gpio_irq_init(ucb);
-+
-+      err = gpiochip_add(&ucb->gc);
-+
-+err:
-+      return err;
-+
-+}
-+
-+static int bcm2708_gpio_remove(struct platform_device *dev)
-+{
-+      int err = 0;
-+      struct bcm2708_gpio *ucb = platform_get_drvdata(dev);
-+
-+      printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev);
-+
-+      gpiochip_remove(&ucb->gc);
-+
-+      platform_set_drvdata(dev, NULL);
-+      kfree(ucb);
-+
-+      return err;
-+}
-+
-+static struct platform_driver bcm2708_gpio_driver = {
-+      .probe = bcm2708_gpio_probe,
-+      .remove = bcm2708_gpio_remove,
-+      .driver = {
-+                 .name = "bcm2708_gpio"},
-+};
-+
-+static int __init bcm2708_gpio_init(void)
-+{
-+      return platform_driver_register(&bcm2708_gpio_driver);
-+}
-+
-+static void __exit bcm2708_gpio_exit(void)
-+{
-+      platform_driver_unregister(&bcm2708_gpio_driver);
-+}
-+
-+module_init(bcm2708_gpio_init);
-+module_exit(bcm2708_gpio_exit);
-+
-+MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/arch/arm/mach-bcm2708/include/mach/gpio.h
-@@ -0,0 +1,17 @@
-+/*
-+ * arch/arm/mach-bcm2708/include/mach/gpio.h
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * License version 2.  This program is licensed "as is" without any
-+ * warranty of any kind, whether express or implied.
-+ */
-+
-+#ifndef __ASM_ARCH_GPIO_H
-+#define __ASM_ARCH_GPIO_H
-+
-+#define BCM2708_NR_GPIOS 54 // number of gpio lines
-+
-+#define gpio_to_irq(x)        ((x) + GPIO_IRQ_START)
-+#define irq_to_gpio(x)        ((x) - GPIO_IRQ_START)
-+
-+#endif
---- a/arch/arm/mach-bcm2709/bcm2709.c
-+++ b/arch/arm/mach-bcm2709/bcm2709.c
-@@ -329,6 +329,31 @@ static struct platform_device bcm2708_vc
-               },
- };
-+#ifdef CONFIG_BCM2708_GPIO
-+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
-+
-+static struct resource bcm2708_gpio_resources[] = {
-+      [0] = {                 /* general purpose I/O */
-+             .start = GPIO_BASE,
-+             .end = GPIO_BASE + SZ_4K - 1,
-+             .flags = IORESOURCE_MEM,
-+             },
-+};
-+
-+static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
-+
-+static struct platform_device bcm2708_gpio_device = {
-+      .name = BCM_GPIO_DRIVER_NAME,
-+      .id = -1,               /* only one VideoCore I/O area */
-+      .resource = bcm2708_gpio_resources,
-+      .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
-+      .dev = {
-+              .dma_mask = &gpio_dmamask,
-+              .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
-+              },
-+};
-+#endif
-+
- int __init bcm_register_device(struct platform_device *pdev)
- {
-       int ret;
---- /dev/null
-+++ b/include/linux/platform_data/bcm2708.h
-@@ -0,0 +1,23 @@
-+/*
-+ * include/linux/platform_data/bcm2708.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * (C) 2014 Julian Scheel <julian@jusst.de>
-+ *
-+ */
-+#ifndef __BCM2708_H_
-+#define __BCM2708_H_
-+
-+typedef enum {
-+      BCM2708_PULL_OFF,
-+      BCM2708_PULL_UP,
-+      BCM2708_PULL_DOWN
-+} bcm2708_gpio_pull_t;
-+
-+extern int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset,
-+              bcm2708_gpio_pull_t value);
-+
-+#endif