300 lines
7.6 KiB
Diff
300 lines
7.6 KiB
Diff
|
From f3c1830096661e270f11f2a33ffb7274f50c90a6 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Elwell <phil@raspberrypi.org>
|
||
|
Date: Thu, 18 Dec 2014 16:48:32 +0000
|
||
|
Subject: [PATCH 068/114] 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
|
||
|
---
|
||
|
arch/arm/boot/dts/lirc-rpi-overlay.dts | 57 ++++++++++++
|
||
|
drivers/staging/media/lirc/lirc_rpi.c | 154 +++++++++++++++++++++++++++------
|
||
|
2 files changed, 183 insertions(+), 28 deletions(-)
|
||
|
create mode 100644 arch/arm/boot/dts/lirc-rpi-overlay.dts
|
||
|
|
||
|
diff --git a/arch/arm/boot/dts/lirc-rpi-overlay.dts b/arch/arm/boot/dts/lirc-rpi-overlay.dts
|
||
|
new file mode 100644
|
||
|
index 0000000..7d5d82b
|
||
|
--- /dev/null
|
||
|
+++ b/arch/arm/boot/dts/lirc-rpi-overlay.dts
|
||
|
@@ -0,0 +1,57 @@
|
||
|
+// Definitions for lirc-rpi module
|
||
|
+/dts-v1/;
|
||
|
+/plugin/;
|
||
|
+
|
||
|
+/ {
|
||
|
+ compatible = "brcm,bcm2708";
|
||
|
+
|
||
|
+ fragment@0 {
|
||
|
+ target-path = "/";
|
||
|
+ __overlay__ {
|
||
|
+ lirc_rpi: lirc_rpi {
|
||
|
+ compatible = "rpi,lirc-rpi";
|
||
|
+ pinctrl-names = "default";
|
||
|
+ pinctrl-0 = <&lirc_pins>;
|
||
|
+ status = "okay";
|
||
|
+
|
||
|
+ // Override autodetection of IR receiver circuit
|
||
|
+ // (0 = active high, 1 = active low, -1 = no override )
|
||
|
+ rpi,sense = <0xffffffff>;
|
||
|
+
|
||
|
+ // Software carrier
|
||
|
+ // (0 = off, 1 = on)
|
||
|
+ rpi,softcarrier = <1>;
|
||
|
+
|
||
|
+ // Invert output
|
||
|
+ // (0 = off, 1 = on)
|
||
|
+ rpi,invert = <0>;
|
||
|
+
|
||
|
+ // Enable debugging messages
|
||
|
+ // (0 = off, 1 = on)
|
||
|
+ rpi,debug = <0>;
|
||
|
+ };
|
||
|
+ };
|
||
|
+ };
|
||
|
+
|
||
|
+ fragment@1 {
|
||
|
+ target = <&gpio>;
|
||
|
+ __overlay__ {
|
||
|
+ lirc_pins: lirc_pins {
|
||
|
+ brcm,pins = <17 18>;
|
||
|
+ brcm,function = <1 0>; // out in
|
||
|
+ brcm,pull = <0 1>; // off down
|
||
|
+ };
|
||
|
+ };
|
||
|
+ };
|
||
|
+
|
||
|
+ __overrides__ {
|
||
|
+ gpio_out_pin = <&lirc_pins>,"brcm,pins:0";
|
||
|
+ gpio_in_pin = <&lirc_pins>,"brcm,pins:4";
|
||
|
+ gpio_in_pull = <&lirc_pins>,"brcm,pull:4";
|
||
|
+
|
||
|
+ sense = <&lirc_rpi>,"rpi,sense:0";
|
||
|
+ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0";
|
||
|
+ invert = <&lirc_rpi>,"rpi,invert:0";
|
||
|
+ debug = <&lirc_rpi>,"rpi,debug:0";
|
||
|
+ };
|
||
|
+};
|
||
|
diff --git a/drivers/staging/media/lirc/lirc_rpi.c b/drivers/staging/media/lirc/lirc_rpi.c
|
||
|
index c688364..cd66ca2 100644
|
||
|
--- a/drivers/staging/media/lirc/lirc_rpi.c
|
||
|
+++ b/drivers/staging/media/lirc/lirc_rpi.c
|
||
|
@@ -40,6 +40,7 @@
|
||
|
#include <media/lirc_dev.h>
|
||
|
#include <mach/gpio.h>
|
||
|
#include <linux/gpio.h>
|
||
|
+#include <linux/of_platform.h>
|
||
|
|
||
|
#include <linux/platform_data/bcm2708.h>
|
||
|
|
||
|
@@ -295,32 +296,117 @@ static int is_right_chip(struct gpio_chip *chip, void *data)
|
||
|
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, ret;
|
||
|
+ struct device_node *node;
|
||
|
+
|
||
|
+ node = lirc_rpi_dev->dev.of_node;
|
||
|
|
||
|
gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
|
||
|
|
||
|
- if (!gpiochip)
|
||
|
+ /*
|
||
|
+ * 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");
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto exit_init_port;
|
||
|
+ }
|
||
|
+
|
||
|
+ 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);
|
||
|
|
||
|
- if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
|
||
|
- printk(KERN_ALERT LIRC_DRIVER_NAME
|
||
|
- ": cant claim gpio pin %d\n", gpio_out_pin);
|
||
|
- ret = -ENODEV;
|
||
|
- goto exit_init_port;
|
||
|
}
|
||
|
+ else
|
||
|
+ {
|
||
|
+ if (gpio_in_pin >= BCM2708_NR_GPIOS ||
|
||
|
+ gpio_out_pin >= BCM2708_NR_GPIOS) {
|
||
|
+ ret = -EINVAL;
|
||
|
+ printk(KERN_ERR LIRC_DRIVER_NAME
|
||
|
+ ": invalid GPIO pin(s) specified!\n");
|
||
|
+ goto exit_init_port;
|
||
|
+ }
|
||
|
|
||
|
- if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
|
||
|
- printk(KERN_ALERT LIRC_DRIVER_NAME
|
||
|
- ": cant claim gpio pin %d\n", gpio_in_pin);
|
||
|
- ret = -ENODEV;
|
||
|
- goto exit_gpio_free_out_pin;
|
||
|
+ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
|
||
|
+ printk(KERN_ALERT LIRC_DRIVER_NAME
|
||
|
+ ": cant claim gpio pin %d\n", gpio_out_pin);
|
||
|
+ ret = -ENODEV;
|
||
|
+ goto exit_init_port;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
|
||
|
+ printk(KERN_ALERT LIRC_DRIVER_NAME
|
||
|
+ ": cant claim gpio pin %d\n", gpio_in_pin);
|
||
|
+ ret = -ENODEV;
|
||
|
+ goto exit_gpio_free_out_pin;
|
||
|
+ }
|
||
|
+
|
||
|
+ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
|
||
|
+ gpiochip->direction_input(gpiochip, gpio_in_pin);
|
||
|
+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
|
||
|
}
|
||
|
|
||
|
- bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
|
||
|
- gpiochip->direction_input(gpiochip, gpio_in_pin);
|
||
|
- gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
|
||
|
gpiochip->set(gpiochip, gpio_out_pin, invert);
|
||
|
|
||
|
irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin);
|
||
|
@@ -514,15 +600,23 @@ static struct lirc_driver driver = {
|
||
|
.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. */
|
||
|
@@ -537,15 +631,26 @@ static int __init lirc_rpi_init(void)
|
||
|
goto exit_buffer_free;
|
||
|
}
|
||
|
|
||
|
- lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
|
||
|
- if (!lirc_rpi_dev) {
|
||
|
- result = -ENOMEM;
|
||
|
- goto exit_driver_unregister;
|
||
|
+ 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;
|
||
|
+ result = platform_device_add(lirc_rpi_dev);
|
||
|
+ if (result)
|
||
|
+ goto exit_device_put;
|
||
|
+ }
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
@@ -577,13 +682,6 @@ static int __init lirc_rpi_init_module(void)
|
||
|
if (result)
|
||
|
return result;
|
||
|
|
||
|
- if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) {
|
||
|
- result = -EINVAL;
|
||
|
- printk(KERN_ERR LIRC_DRIVER_NAME
|
||
|
- ": invalid GPIO pin(s) specified!\n");
|
||
|
- goto exit_rpi;
|
||
|
- }
|
||
|
-
|
||
|
result = init_port();
|
||
|
if (result < 0)
|
||
|
goto exit_rpi;
|
||
|
--
|
||
|
1.8.3.2
|
||
|
|