brcm2708: add linux 4.9 support
[openwrt/staging/yousong.git] / target / linux / brcm2708 / patches-4.9 / 0045-lirc-added-support-for-RaspberryPi-GPIO.patch
diff --git a/target/linux/brcm2708/patches-4.9/0045-lirc-added-support-for-RaspberryPi-GPIO.patch b/target/linux/brcm2708/patches-4.9/0045-lirc-added-support-for-RaspberryPi-GPIO.patch
new file mode 100644 (file)
index 0000000..ea529b8
--- /dev/null
@@ -0,0 +1,855 @@
+From e12517458be7d5ec0eccc2c23db2b78badd54587 Mon Sep 17 00:00:00 2001
+From: Aron Szabo <aron@aron.ws>
+Date: Sat, 16 Jun 2012 12:15:55 +0200
+Subject: [PATCH] lirc: added support for RaspberryPi GPIO
+
+lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others
+See: https://github.com/raspberrypi/linux/issues/525
+
+lirc: Remove restriction on gpio pins that can be used with lirc
+
+Compute Module, for example could use different pins
+
+lirc_rpi: Add parameter to specify input pin pull
+
+Depending on the connected IR circuitry it might be desirable to change the
+gpios internal pull from it pull-down default behaviour. Add a module
+parameter to allow the user to set it explicitly.
+
+Signed-off-by: Julian Scheel <julian@jusst.de>
+
+lirc-rpi: Use the higher-level irq control functions
+
+This module used to access the irq_chip methods of the
+gpio controller directly, rather than going through the
+standard enable_irq/irq_set_irq_type functions. This
+caused problems on pinctrl-bcm2835 which only implements
+the irq_enable/disable methods and not irq_unmask/mask.
+
+lirc-rpi: Correct the interrupt usage
+
+1) Correct the use of enable_irq (i.e. don't call it so often)
+2) Correct the shutdown sequence.
+3) Avoid a bcm2708_gpio driver quirk by setting the irq flags earlier
+
+lirc-rpi: use getnstimeofday instead of read_current_timer
+
+read_current_timer isn't guaranteed to return values in
+microseconds, and indeed it doesn't on a Pi2.
+
+Issue: linux#827
+
+lirc-rpi: Add device tree support, and a suitable overlay
+
+The overlay supports DT parameters that match the old module
+parameters, except that gpio_in_pull should be set using the
+strings "up", "down" or "off".
+
+lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode
+
+fix auto-sense in lirc_rpi driver
+
+On a Raspberry Pi 2, the lirc_rpi driver might receive spurious
+interrupts and change it's low-active / high-active setting.
+When this happens, the IR remote control stops working.
+
+This patch disables this auto-detection if the 'sense' parameter
+was set in the device tree, making the driver robust to such
+spurious interrupts.
+---
+ drivers/staging/media/lirc/Kconfig    |   6 +
+ drivers/staging/media/lirc/Makefile   |   1 +
+ drivers/staging/media/lirc/lirc_rpi.c | 734 ++++++++++++++++++++++++++++++++++
+ include/linux/platform_data/bcm2708.h |  23 ++
+ 4 files changed, 764 insertions(+)
+ create mode 100644 drivers/staging/media/lirc/lirc_rpi.c
+ create mode 100644 include/linux/platform_data/bcm2708.h
+
+--- a/drivers/staging/media/lirc/Kconfig
++++ b/drivers/staging/media/lirc/Kconfig
+@@ -32,6 +32,12 @@ config LIRC_PARALLEL
+       help
+         Driver for Homebrew Parallel Port Receivers
++config LIRC_RPI
++      tristate "Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi"
++      depends on LIRC
++      help
++        Driver for Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi
++
+ config LIRC_SASEM
+       tristate "Sasem USB IR Remote"
+       depends on LIRC && USB
+--- a/drivers/staging/media/lirc/Makefile
++++ b/drivers/staging/media/lirc/Makefile
+@@ -6,6 +6,7 @@
+ obj-$(CONFIG_LIRC_BT829)      += lirc_bt829.o
+ obj-$(CONFIG_LIRC_IMON)               += lirc_imon.o
+ obj-$(CONFIG_LIRC_PARALLEL)   += lirc_parallel.o
++obj-$(CONFIG_LIRC_RPI)                += lirc_rpi.o
+ obj-$(CONFIG_LIRC_SASEM)      += lirc_sasem.o
+ obj-$(CONFIG_LIRC_SERIAL)     += lirc_serial.o
+ obj-$(CONFIG_LIRC_SIR)                += lirc_sir.o
+--- /dev/null
++++ b/drivers/staging/media/lirc/lirc_rpi.c
+@@ -0,0 +1,734 @@
++/*
++ * lirc_rpi.c
++ *
++ * lirc_rpi - Device driver that records pulse- and pause-lengths
++ *          (space-lengths) (just like the lirc_serial driver does)
++ *          between GPIO interrupt events on the Raspberry Pi.
++ *          Lots of code has been taken from the lirc_serial module,
++ *          so I would like say thanks to the authors.
++ *
++ * Copyright (C) 2012 Aron Robert Szabo <aron@reon.hu>,
++ *                  Michael Bishop <cleverca22@gmail.com>
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/time.h>
++#include <linux/timex.h>
++#include <linux/timekeeping.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++#include <linux/spinlock.h>
++#include <media/lirc.h>
++#include <media/lirc_dev.h>
++#include <linux/gpio.h>
++#include <linux/of_platform.h>
++#include <linux/platform_data/bcm2708.h>
++
++#define LIRC_DRIVER_NAME "lirc_rpi"
++#define RBUF_LEN 256
++#define LIRC_TRANSMITTER_LATENCY 50
++
++#ifndef MAX_UDELAY_MS
++#define MAX_UDELAY_US 5000
++#else
++#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
++#endif
++
++#define dprintk(fmt, args...)                                 \
++      do {                                                    \
++              if (debug)                                      \
++                      printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
++                             fmt, ## args);                   \
++      } while (0)
++
++/* module parameters */
++
++/* set the default GPIO input pin */
++static int gpio_in_pin = 18;
++/* set the default pull behaviour for input pin */
++static int gpio_in_pull = BCM2708_PULL_DOWN;
++/* set the default GPIO output pin */
++static int gpio_out_pin = 17;
++/* enable debugging messages */
++static bool debug;
++/* -1 = auto, 0 = active high, 1 = active low */
++static int sense = -1;
++/* use softcarrier by default */
++static bool softcarrier = 1;
++/* 0 = do not invert output, 1 = invert output */
++static bool invert = 0;
++
++struct gpio_chip *gpiochip;
++static int irq_num;
++static int auto_sense = 1;
++
++/* forward declarations */
++static long send_pulse(unsigned long length);
++static void send_space(long length);
++static void lirc_rpi_exit(void);
++
++static struct platform_device *lirc_rpi_dev;
++static struct timeval lasttv = { 0, 0 };
++static struct lirc_buffer rbuf;
++static spinlock_t lock;
++
++/* initialized/set in init_timing_params() */
++static unsigned int freq = 38000;
++static unsigned int duty_cycle = 50;
++static unsigned long period;
++static unsigned long pulse_width;
++static unsigned long space_width;
++
++static void safe_udelay(unsigned long usecs)
++{
++      while (usecs > MAX_UDELAY_US) {
++              udelay(MAX_UDELAY_US);
++              usecs -= MAX_UDELAY_US;
++      }
++      udelay(usecs);
++}
++
++static unsigned long read_current_us(void)
++{
++      struct timespec now;
++      getnstimeofday(&now);
++      return (now.tv_sec * 1000000) + (now.tv_nsec/1000);
++}
++
++static int init_timing_params(unsigned int new_duty_cycle,
++      unsigned int new_freq)
++{
++      if (1000 * 1000000L / new_freq * new_duty_cycle / 100 <=
++          LIRC_TRANSMITTER_LATENCY)
++              return -EINVAL;
++      if (1000 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
++          LIRC_TRANSMITTER_LATENCY)
++              return -EINVAL;
++      duty_cycle = new_duty_cycle;
++      freq = new_freq;
++      period = 1000 * 1000000L / freq;
++      pulse_width = period * duty_cycle / 100;
++      space_width = period - pulse_width;
++      dprintk("in init_timing_params, freq=%d pulse=%ld, "
++              "space=%ld\n", freq, pulse_width, space_width);
++      return 0;
++}
++
++static long send_pulse_softcarrier(unsigned long length)
++{
++      int flag;
++      unsigned long actual, target;
++      unsigned long actual_us, initial_us, target_us;
++
++      length *= 1000;
++
++      actual = 0; target = 0; flag = 0;
++      actual_us = read_current_us();
++
++      while (actual < length) {
++              if (flag) {
++                      gpiochip->set(gpiochip, gpio_out_pin, invert);
++                      target += space_width;
++              } else {
++                      gpiochip->set(gpiochip, gpio_out_pin, !invert);
++                      target += pulse_width;
++              }
++              initial_us = actual_us;
++              target_us = actual_us + (target - actual) / 1000;
++              /*
++               * Note - we've checked in ioctl that the pulse/space
++               * widths are big enough so that d is > 0
++               */
++              if  ((int)(target_us - actual_us) > 0)
++                      udelay(target_us - actual_us);
++              actual_us = read_current_us();
++              actual += (actual_us - initial_us) * 1000;
++              flag = !flag;
++      }
++      return (actual-length) / 1000;
++}
++
++static long send_pulse(unsigned long length)
++{
++      if (length <= 0)
++              return 0;
++
++      if (softcarrier) {
++              return send_pulse_softcarrier(length);
++      } else {
++              gpiochip->set(gpiochip, gpio_out_pin, !invert);
++              safe_udelay(length);
++              return 0;
++      }
++}
++
++static void send_space(long length)
++{
++      gpiochip->set(gpiochip, gpio_out_pin, invert);
++      if (length <= 0)
++              return;
++      safe_udelay(length);
++}
++
++static void rbwrite(int l)
++{
++      if (lirc_buffer_full(&rbuf)) {
++              /* no new signals will be accepted */
++              dprintk("Buffer overrun\n");
++              return;
++      }
++      lirc_buffer_write(&rbuf, (void *)&l);
++}
++
++static void frbwrite(int l)
++{
++      /* simple noise filter */
++      static int pulse, space;
++      static unsigned int ptr;
++
++      if (ptr > 0 && (l & PULSE_BIT)) {
++              pulse += l & PULSE_MASK;
++              if (pulse > 250) {
++                      rbwrite(space);
++                      rbwrite(pulse | PULSE_BIT);
++                      ptr = 0;
++                      pulse = 0;
++              }
++              return;
++      }
++      if (!(l & PULSE_BIT)) {
++              if (ptr == 0) {
++                      if (l > 20000) {
++                              space = l;
++                              ptr++;
++                              return;
++                      }
++              } else {
++                      if (l > 20000) {
++                              space += pulse;
++                              if (space > PULSE_MASK)
++                                      space = PULSE_MASK;
++                              space += l;
++                              if (space > PULSE_MASK)
++                                      space = PULSE_MASK;
++                              pulse = 0;
++                              return;
++                      }
++                      rbwrite(space);
++                      rbwrite(pulse | PULSE_BIT);
++                      ptr = 0;
++                      pulse = 0;
++              }
++      }
++      rbwrite(l);
++}
++
++static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)
++{
++      struct timeval tv;
++      long deltv;
++      int data;
++      int signal;
++
++      /* use the GPIO signal level */
++      signal = gpiochip->get(gpiochip, gpio_in_pin);
++
++      if (sense != -1) {
++              /* get current time */
++              do_gettimeofday(&tv);
++
++              /* calc time since last interrupt in microseconds */
++              deltv = tv.tv_sec-lasttv.tv_sec;
++              if (tv.tv_sec < lasttv.tv_sec ||
++                  (tv.tv_sec == lasttv.tv_sec &&
++                   tv.tv_usec < lasttv.tv_usec)) {
++                      printk(KERN_WARNING LIRC_DRIVER_NAME
++                             ": AIEEEE: your clock just jumped backwards\n");
++                      printk(KERN_WARNING LIRC_DRIVER_NAME
++                             ": %d %d %lx %lx %lx %lx\n", signal, sense,
++                             tv.tv_sec, lasttv.tv_sec,
++                             tv.tv_usec, lasttv.tv_usec);
++                      data = PULSE_MASK;
++              } else if (deltv > 15) {
++                      data = PULSE_MASK; /* really long time */
++                      if (!(signal^sense)) {
++                              /* sanity check */
++                              printk(KERN_DEBUG LIRC_DRIVER_NAME
++                                     ": AIEEEE: %d %d %lx %lx %lx %lx\n",
++                                     signal, sense, tv.tv_sec, lasttv.tv_sec,
++                                     tv.tv_usec, lasttv.tv_usec);
++                              /*
++                               * detecting pulse while this
++                               * MUST be a space!
++                               */
++                              if (auto_sense) {
++                                      sense = sense ? 0 : 1;
++                              }
++                      }
++              } else {
++                      data = (int) (deltv*1000000 +
++                                    (tv.tv_usec - lasttv.tv_usec));
++              }
++              frbwrite(signal^sense ? data : (data|PULSE_BIT));
++              lasttv = tv;
++              wake_up_interruptible(&rbuf.wait_poll);
++      }
++
++      return IRQ_HANDLED;
++}
++
++static int is_right_chip(struct gpio_chip *chip, void *data)
++{
++      dprintk("is_right_chip %s %d\n", chip->label, strcmp(data, chip->label));
++
++      if (strcmp(data, chip->label) == 0)
++              return 1;
++      return 0;
++}
++
++static inline int read_bool_property(const struct device_node *np,
++                                   const char *propname,
++                                   bool *out_value)
++{
++      u32 value = 0;
++      int err = of_property_read_u32(np, propname, &value);
++      if (err == 0)
++              *out_value = (value != 0);
++      return err;
++}
++
++static void read_pin_settings(struct device_node *node)
++{
++      u32 pin;
++      int index;
++
++      for (index = 0;
++           of_property_read_u32_index(
++                   node,
++                   "brcm,pins",
++                   index,
++                   &pin) == 0;
++           index++) {
++              u32 function;
++              int err;
++              err = of_property_read_u32_index(
++                      node,
++                      "brcm,function",
++                      index,
++                      &function);
++              if (err == 0) {
++                      if (function == 1) /* Output */
++                              gpio_out_pin = pin;
++                      else if (function == 0) /* Input */
++                              gpio_in_pin = pin;
++              }
++      }
++}
++
++static int init_port(void)
++{
++      int i, nlow, nhigh;
++      struct device_node *node;
++
++      node = lirc_rpi_dev->dev.of_node;
++
++      gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
++
++      /*
++       * Because of the lack of a setpull function, only support
++       * pinctrl-bcm2835 if using device tree.
++      */
++      if (!gpiochip && node)
++              gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip);
++
++      if (!gpiochip) {
++              pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n");
++              return -ENODEV;
++      }
++
++      if (node) {
++              struct device_node *pins_node;
++
++              pins_node = of_parse_phandle(node, "pinctrl-0", 0);
++              if (!pins_node) {
++                      printk(KERN_ERR LIRC_DRIVER_NAME
++                             ": pinctrl settings not found!\n");
++                      return -EINVAL;
++              }
++
++              read_pin_settings(pins_node);
++
++              of_property_read_u32(node, "rpi,sense", &sense);
++
++              read_bool_property(node, "rpi,softcarrier", &softcarrier);
++
++              read_bool_property(node, "rpi,invert", &invert);
++
++              read_bool_property(node, "rpi,debug", &debug);
++
++      } else {
++              return -EINVAL;
++      }
++
++      gpiochip->set(gpiochip, gpio_out_pin, invert);
++
++      irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin);
++      dprintk("to_irq %d\n", irq_num);
++
++      /* if pin is high, then this must be an active low receiver. */
++      if (sense == -1) {
++              /* wait 1/2 sec for the power supply */
++              msleep(500);
++
++              /*
++               * probe 9 times every 0.04s, collect "votes" for
++               * active high/low
++               */
++              nlow = 0;
++              nhigh = 0;
++              for (i = 0; i < 9; i++) {
++                      if (gpiochip->get(gpiochip, gpio_in_pin))
++                              nlow++;
++                      else
++                              nhigh++;
++                      msleep(40);
++              }
++              sense = (nlow >= nhigh ? 1 : 0);
++              printk(KERN_INFO LIRC_DRIVER_NAME
++                     ": auto-detected active %s receiver on GPIO pin %d\n",
++                     sense ? "low" : "high", gpio_in_pin);
++      } else {
++              printk(KERN_INFO LIRC_DRIVER_NAME
++                     ": manually using active %s receiver on GPIO pin %d\n",
++                     sense ? "low" : "high", gpio_in_pin);
++              auto_sense = 0;
++      }
++
++      return 0;
++}
++
++// called when the character device is opened
++static int set_use_inc(void *data)
++{
++      int result;
++
++      /* initialize timestamp */
++      do_gettimeofday(&lasttv);
++
++      result = request_irq(irq_num,
++                           (irq_handler_t) irq_handler,
++                           IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
++                           LIRC_DRIVER_NAME, (void*) 0);
++
++      switch (result) {
++      case -EBUSY:
++              printk(KERN_ERR LIRC_DRIVER_NAME
++                     ": IRQ %d is busy\n",
++                     irq_num);
++              return -EBUSY;
++      case -EINVAL:
++              printk(KERN_ERR LIRC_DRIVER_NAME
++                     ": Bad irq number or handler\n");
++              return -EINVAL;
++      default:
++              dprintk("Interrupt %d obtained\n",
++                      irq_num);
++              break;
++      };
++
++      /* initialize pulse/space widths */
++      init_timing_params(duty_cycle, freq);
++
++      return 0;
++}
++
++static void set_use_dec(void *data)
++{
++      /* GPIO Pin Falling/Rising Edge Detect Disable */
++      irq_set_irq_type(irq_num, 0);
++      disable_irq(irq_num);
++
++      free_irq(irq_num, (void *) 0);
++
++      dprintk(KERN_INFO LIRC_DRIVER_NAME
++              ": freed IRQ %d\n", irq_num);
++}
++
++static ssize_t lirc_write(struct file *file, const char *buf,
++      size_t n, loff_t *ppos)
++{
++      int i, count;
++      unsigned long flags;
++      long delta = 0;
++      int *wbuf;
++
++      count = n / sizeof(int);
++      if (n % sizeof(int) || count % 2 == 0)
++              return -EINVAL;
++      wbuf = memdup_user(buf, n);
++      if (IS_ERR(wbuf))
++              return PTR_ERR(wbuf);
++      spin_lock_irqsave(&lock, flags);
++
++      for (i = 0; i < count; i++) {
++              if (i%2)
++                      send_space(wbuf[i] - delta);
++              else
++                      delta = send_pulse(wbuf[i]);
++      }
++      gpiochip->set(gpiochip, gpio_out_pin, invert);
++
++      spin_unlock_irqrestore(&lock, flags);
++      kfree(wbuf);
++      return n;
++}
++
++static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
++{
++      int result;
++      __u32 value;
++
++      switch (cmd) {
++      case LIRC_GET_SEND_MODE:
++              return -ENOIOCTLCMD;
++              break;
++
++      case LIRC_SET_SEND_MODE:
++              result = get_user(value, (__u32 *) arg);
++              if (result)
++                      return result;
++              /* only LIRC_MODE_PULSE supported */
++              if (value != LIRC_MODE_PULSE)
++                      return -ENOSYS;
++              break;
++
++      case LIRC_GET_LENGTH:
++              return -ENOSYS;
++              break;
++
++      case LIRC_SET_SEND_DUTY_CYCLE:
++              dprintk("SET_SEND_DUTY_CYCLE\n");
++              result = get_user(value, (__u32 *) arg);
++              if (result)
++                      return result;
++              if (value <= 0 || value > 100)
++                      return -EINVAL;
++              return init_timing_params(value, freq);
++              break;
++
++      case LIRC_SET_SEND_CARRIER:
++              dprintk("SET_SEND_CARRIER\n");
++              result = get_user(value, (__u32 *) arg);
++              if (result)
++                      return result;
++              if (value > 500000 || value < 20000)
++                      return -EINVAL;
++              return init_timing_params(duty_cycle, value);
++              break;
++
++      default:
++              return lirc_dev_fop_ioctl(filep, cmd, arg);
++      }
++      return 0;
++}
++
++static const struct file_operations lirc_fops = {
++      .owner          = THIS_MODULE,
++      .write          = lirc_write,
++      .unlocked_ioctl = lirc_ioctl,
++      .read           = lirc_dev_fop_read,
++      .poll           = lirc_dev_fop_poll,
++      .open           = lirc_dev_fop_open,
++      .release        = lirc_dev_fop_close,
++      .llseek         = no_llseek,
++};
++
++static struct lirc_driver driver = {
++      .name           = LIRC_DRIVER_NAME,
++      .minor          = -1,
++      .code_length    = 1,
++      .sample_rate    = 0,
++      .data           = NULL,
++      .add_to_buf     = NULL,
++      .rbuf           = &rbuf,
++      .set_use_inc    = set_use_inc,
++      .set_use_dec    = set_use_dec,
++      .fops           = &lirc_fops,
++      .dev            = NULL,
++      .owner          = THIS_MODULE,
++};
++
++static const struct of_device_id lirc_rpi_of_match[] = {
++      { .compatible = "rpi,lirc-rpi", },
++      {},
++};
++MODULE_DEVICE_TABLE(of, lirc_rpi_of_match);
++
++static struct platform_driver lirc_rpi_driver = {
++      .driver = {
++              .name   = LIRC_DRIVER_NAME,
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(lirc_rpi_of_match),
++      },
++};
++
++static int __init lirc_rpi_init(void)
++{
++      struct device_node *node;
++      int result;
++
++      /* Init read buffer. */
++      result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
++      if (result < 0)
++              return -ENOMEM;
++
++      result = platform_driver_register(&lirc_rpi_driver);
++      if (result) {
++              printk(KERN_ERR LIRC_DRIVER_NAME
++                     ": lirc register returned %d\n", result);
++              goto exit_buffer_free;
++      }
++
++      node = of_find_compatible_node(NULL, NULL,
++                                     lirc_rpi_of_match[0].compatible);
++
++      if (node) {
++              /* DT-enabled */
++              lirc_rpi_dev = of_find_device_by_node(node);
++              WARN_ON(lirc_rpi_dev->dev.of_node != node);
++              of_node_put(node);
++      }
++      else {
++              lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
++              if (!lirc_rpi_dev) {
++                      result = -ENOMEM;
++                      goto exit_driver_unregister;
++              }
++
++              result = platform_device_add(lirc_rpi_dev);
++              if (result)
++                      goto exit_device_put;
++      }
++
++      return 0;
++
++      exit_device_put:
++      platform_device_put(lirc_rpi_dev);
++
++      exit_driver_unregister:
++      platform_driver_unregister(&lirc_rpi_driver);
++
++      exit_buffer_free:
++      lirc_buffer_free(&rbuf);
++
++      return result;
++}
++
++static void lirc_rpi_exit(void)
++{
++      if (!lirc_rpi_dev->dev.of_node)
++              platform_device_unregister(lirc_rpi_dev);
++      platform_driver_unregister(&lirc_rpi_driver);
++      lirc_buffer_free(&rbuf);
++}
++
++static int __init lirc_rpi_init_module(void)
++{
++      int result;
++
++      result = lirc_rpi_init();
++      if (result)
++              return result;
++
++      result = init_port();
++      if (result < 0)
++              goto exit_rpi;
++
++      driver.features = LIRC_CAN_SET_SEND_DUTY_CYCLE |
++                        LIRC_CAN_SET_SEND_CARRIER |
++                        LIRC_CAN_SEND_PULSE |
++                        LIRC_CAN_REC_MODE2;
++
++      driver.dev = &lirc_rpi_dev->dev;
++      driver.minor = lirc_register_driver(&driver);
++
++      if (driver.minor < 0) {
++              printk(KERN_ERR LIRC_DRIVER_NAME
++                     ": device registration failed with %d\n", result);
++              result = -EIO;
++              goto exit_rpi;
++      }
++
++      printk(KERN_INFO LIRC_DRIVER_NAME ": driver registered!\n");
++
++      return 0;
++
++      exit_rpi:
++      lirc_rpi_exit();
++
++      return result;
++}
++
++static void __exit lirc_rpi_exit_module(void)
++{
++      lirc_unregister_driver(driver.minor);
++
++      gpio_free(gpio_out_pin);
++      gpio_free(gpio_in_pin);
++
++      lirc_rpi_exit();
++
++      printk(KERN_INFO LIRC_DRIVER_NAME ": cleaned up module\n");
++}
++
++module_init(lirc_rpi_init_module);
++module_exit(lirc_rpi_exit_module);
++
++MODULE_DESCRIPTION("Infra-red receiver and blaster driver for Raspberry Pi GPIO.");
++MODULE_AUTHOR("Aron Robert Szabo <aron@reon.hu>");
++MODULE_AUTHOR("Michael Bishop <cleverca22@gmail.com>");
++MODULE_LICENSE("GPL");
++
++module_param(gpio_out_pin, int, S_IRUGO);
++MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number of the BCM"
++               " processor. (default 17");
++
++module_param(gpio_in_pin, int, S_IRUGO);
++MODULE_PARM_DESC(gpio_in_pin, "GPIO input pin number of the BCM processor."
++               " (default 18");
++
++module_param(gpio_in_pull, int, S_IRUGO);
++MODULE_PARM_DESC(gpio_in_pull, "GPIO input pin pull configuration."
++               " (0 = off, 1 = up, 2 = down, default down)");
++
++module_param(sense, int, S_IRUGO);
++MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
++               " (0 = active high, 1 = active low )");
++
++module_param(softcarrier, bool, S_IRUGO);
++MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
++
++module_param(invert, bool, S_IRUGO);
++MODULE_PARM_DESC(invert, "Invert output (0 = off, 1 = on, default off");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Enable debugging messages");
+--- /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