aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.9/950-0045-lirc-added-support-for-RaspberryPi-GPIO.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/950-0045-lirc-added-support-for-RaspberryPi-GPIO.patch')
-rw-r--r--target/linux/brcm2708/patches-4.9/950-0045-lirc-added-support-for-RaspberryPi-GPIO.patch855
1 files changed, 0 insertions, 855 deletions
diff --git a/target/linux/brcm2708/patches-4.9/950-0045-lirc-added-support-for-RaspberryPi-GPIO.patch b/target/linux/brcm2708/patches-4.9/950-0045-lirc-added-support-for-RaspberryPi-GPIO.patch
deleted file mode 100644
index 0cbc1c45a4..0000000000
--- a/target/linux/brcm2708/patches-4.9/950-0045-lirc-added-support-for-RaspberryPi-GPIO.patch
+++ /dev/null
@@ -1,855 +0,0 @@
-From 277c109833c1d78543bec0723ab42f4c79937df9 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