123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- 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
- --- /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";
- + };
- +};
- --- 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_chi
- 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);
- +
- + }
- + 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_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);
- + }
-
- - 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);
- 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);
-
- - result = platform_device_add(lirc_rpi_dev);
- - if (result)
- - goto exit_device_put;
- + 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;
-
- @@ -577,13 +682,6 @@ static int __init lirc_rpi_init_module(v
- 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;
|