brcm2708: update to v3.18
[15.05/openwrt.git] / target / linux / brcm2708 / patches-3.18 / 0068-lirc-rpi-Add-device-tree-support-and-a-suitable-over.patch
1 From f3c1830096661e270f11f2a33ffb7274f50c90a6 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Thu, 18 Dec 2014 16:48:32 +0000
4 Subject: [PATCH 068/114] lirc-rpi: Add device tree support, and a suitable
5  overlay
6
7 The overlay supports DT parameters that match the old module
8 parameters, except that gpio_in_pull should be set using the
9 strings "up", "down" or "off".
10
11 lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode
12 ---
13  arch/arm/boot/dts/lirc-rpi-overlay.dts |  57 ++++++++++++
14  drivers/staging/media/lirc/lirc_rpi.c  | 154 +++++++++++++++++++++++++++------
15  2 files changed, 183 insertions(+), 28 deletions(-)
16  create mode 100644 arch/arm/boot/dts/lirc-rpi-overlay.dts
17
18 diff --git a/arch/arm/boot/dts/lirc-rpi-overlay.dts b/arch/arm/boot/dts/lirc-rpi-overlay.dts
19 new file mode 100644
20 index 0000000..7d5d82b
21 --- /dev/null
22 +++ b/arch/arm/boot/dts/lirc-rpi-overlay.dts
23 @@ -0,0 +1,57 @@
24 +// Definitions for lirc-rpi module
25 +/dts-v1/;
26 +/plugin/;
27 +
28 +/ {
29 +       compatible = "brcm,bcm2708";
30 +
31 +       fragment@0 {
32 +               target-path = "/";
33 +               __overlay__ {
34 +                       lirc_rpi: lirc_rpi {
35 +                               compatible = "rpi,lirc-rpi";
36 +                               pinctrl-names = "default";
37 +                               pinctrl-0 = <&lirc_pins>;
38 +                               status = "okay";
39 +
40 +                               // Override autodetection of IR receiver circuit
41 +                               // (0 = active high, 1 = active low, -1 = no override )
42 +                               rpi,sense = <0xffffffff>;
43 +
44 +                               // Software carrier
45 +                               // (0 = off, 1 = on)
46 +                               rpi,softcarrier = <1>;
47 +
48 +                               // Invert output
49 +                               // (0 = off, 1 = on)
50 +                               rpi,invert = <0>;
51 +
52 +                               // Enable debugging messages
53 +                               // (0 = off, 1 = on)
54 +                               rpi,debug = <0>;
55 +                       };
56 +               };
57 +       };
58 +
59 +       fragment@1 {
60 +               target = <&gpio>;
61 +               __overlay__ {
62 +                       lirc_pins: lirc_pins {
63 +                               brcm,pins = <17 18>;
64 +                               brcm,function = <1 0>; // out in
65 +                               brcm,pull = <0 1>; // off down
66 +                       };
67 +               };
68 +       };
69 +
70 +       __overrides__ {
71 +               gpio_out_pin =  <&lirc_pins>,"brcm,pins:0";
72 +               gpio_in_pin =   <&lirc_pins>,"brcm,pins:4";
73 +               gpio_in_pull =  <&lirc_pins>,"brcm,pull:4";
74 +
75 +               sense =         <&lirc_rpi>,"rpi,sense:0";
76 +               softcarrier =   <&lirc_rpi>,"rpi,softcarrier:0";
77 +               invert =        <&lirc_rpi>,"rpi,invert:0";
78 +               debug =         <&lirc_rpi>,"rpi,debug:0";
79 +       };
80 +};
81 diff --git a/drivers/staging/media/lirc/lirc_rpi.c b/drivers/staging/media/lirc/lirc_rpi.c
82 index c688364..cd66ca2 100644
83 --- a/drivers/staging/media/lirc/lirc_rpi.c
84 +++ b/drivers/staging/media/lirc/lirc_rpi.c
85 @@ -40,6 +40,7 @@
86  #include <media/lirc_dev.h>
87  #include <mach/gpio.h>
88  #include <linux/gpio.h>
89 +#include <linux/of_platform.h>
90  
91  #include <linux/platform_data/bcm2708.h>
92  
93 @@ -295,32 +296,117 @@ static int is_right_chip(struct gpio_chip *chip, void *data)
94         return 0;
95  }
96  
97 +static inline int read_bool_property(const struct device_node *np,
98 +                                    const char *propname,
99 +                                    bool *out_value)
100 +{
101 +       u32 value = 0;
102 +       int err = of_property_read_u32(np, propname, &value);
103 +       if (err == 0)
104 +               *out_value = (value != 0);
105 +       return err;
106 +}
107 +
108 +static void read_pin_settings(struct device_node *node)
109 +{
110 +       u32 pin;
111 +       int index;
112 +
113 +       for (index = 0;
114 +            of_property_read_u32_index(
115 +                    node,
116 +                    "brcm,pins",
117 +                    index,
118 +                    &pin) == 0;
119 +            index++) {
120 +               u32 function;
121 +               int err;
122 +               err = of_property_read_u32_index(
123 +                       node,
124 +                       "brcm,function",
125 +                       index,
126 +                       &function);
127 +               if (err == 0) {
128 +                       if (function == 1) /* Output */
129 +                               gpio_out_pin = pin;
130 +                       else if (function == 0) /* Input */
131 +                               gpio_in_pin = pin;
132 +               }
133 +       }
134 +}
135 +
136  static int init_port(void)
137  {
138         int i, nlow, nhigh, ret;
139 +       struct device_node *node;
140 +
141 +       node = lirc_rpi_dev->dev.of_node;
142  
143         gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
144  
145 -       if (!gpiochip)
146 +       /*
147 +        * Because of the lack of a setpull function, only support
148 +        * pinctrl-bcm2835 if using device tree.
149 +       */
150 +       if (!gpiochip && node)
151 +               gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip);
152 +
153 +       if (!gpiochip) {
154 +               pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n");
155                 return -ENODEV;
156 +       }
157 +
158 +       if (node) {
159 +               struct device_node *pins_node;
160 +
161 +               pins_node = of_parse_phandle(node, "pinctrl-0", 0);
162 +               if (!pins_node) {
163 +                       printk(KERN_ERR LIRC_DRIVER_NAME
164 +                              ": pinctrl settings not found!\n");
165 +                       ret = -EINVAL;
166 +                       goto exit_init_port;
167 +               }
168 +
169 +               read_pin_settings(pins_node);
170 +
171 +               of_property_read_u32(node, "rpi,sense", &sense);
172 +
173 +               read_bool_property(node, "rpi,softcarrier", &softcarrier);
174 +
175 +               read_bool_property(node, "rpi,invert", &invert);
176 +
177 +               read_bool_property(node, "rpi,debug", &debug);
178  
179 -       if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
180 -               printk(KERN_ALERT LIRC_DRIVER_NAME
181 -                      ": cant claim gpio pin %d\n", gpio_out_pin);
182 -               ret = -ENODEV;
183 -               goto exit_init_port;
184         }
185 +       else
186 +       {
187 +               if (gpio_in_pin >= BCM2708_NR_GPIOS ||
188 +                   gpio_out_pin >= BCM2708_NR_GPIOS) {
189 +                       ret = -EINVAL;
190 +                       printk(KERN_ERR LIRC_DRIVER_NAME
191 +                              ": invalid GPIO pin(s) specified!\n");
192 +                       goto exit_init_port;
193 +               }
194  
195 -       if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
196 -               printk(KERN_ALERT LIRC_DRIVER_NAME
197 -                      ": cant claim gpio pin %d\n", gpio_in_pin);
198 -               ret = -ENODEV;
199 -               goto exit_gpio_free_out_pin;
200 +               if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
201 +                       printk(KERN_ALERT LIRC_DRIVER_NAME
202 +                              ": cant claim gpio pin %d\n", gpio_out_pin);
203 +                       ret = -ENODEV;
204 +                       goto exit_init_port;
205 +               }
206 +
207 +               if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
208 +                       printk(KERN_ALERT LIRC_DRIVER_NAME
209 +                              ": cant claim gpio pin %d\n", gpio_in_pin);
210 +                       ret = -ENODEV;
211 +                       goto exit_gpio_free_out_pin;
212 +               }
213 +
214 +               bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
215 +               gpiochip->direction_input(gpiochip, gpio_in_pin);
216 +               gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
217         }
218  
219 -       bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
220 -       gpiochip->direction_input(gpiochip, gpio_in_pin);
221 -       gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
222         gpiochip->set(gpiochip, gpio_out_pin, invert);
223  
224         irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin);
225 @@ -514,15 +600,23 @@ static struct lirc_driver driver = {
226         .owner          = THIS_MODULE,
227  };
228  
229 +static const struct of_device_id lirc_rpi_of_match[] = {
230 +       { .compatible = "rpi,lirc-rpi", },
231 +       {},
232 +};
233 +MODULE_DEVICE_TABLE(of, lirc_rpi_of_match);
234 +
235  static struct platform_driver lirc_rpi_driver = {
236         .driver = {
237                 .name   = LIRC_DRIVER_NAME,
238                 .owner  = THIS_MODULE,
239 +               .of_match_table = of_match_ptr(lirc_rpi_of_match),
240         },
241  };
242  
243  static int __init lirc_rpi_init(void)
244  {
245 +       struct device_node *node;
246         int result;
247  
248         /* Init read buffer. */
249 @@ -537,15 +631,26 @@ static int __init lirc_rpi_init(void)
250                 goto exit_buffer_free;
251         }
252  
253 -       lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
254 -       if (!lirc_rpi_dev) {
255 -               result = -ENOMEM;
256 -               goto exit_driver_unregister;
257 +       node = of_find_compatible_node(NULL, NULL,
258 +                                      lirc_rpi_of_match[0].compatible);
259 +
260 +       if (node) {
261 +               /* DT-enabled */
262 +               lirc_rpi_dev = of_find_device_by_node(node);
263 +               WARN_ON(lirc_rpi_dev->dev.of_node != node);
264 +               of_node_put(node);
265         }
266 +       else {
267 +               lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
268 +               if (!lirc_rpi_dev) {
269 +                       result = -ENOMEM;
270 +                       goto exit_driver_unregister;
271 +               }
272  
273 -       result = platform_device_add(lirc_rpi_dev);
274 -       if (result)
275 -               goto exit_device_put;
276 +               result = platform_device_add(lirc_rpi_dev);
277 +               if (result)
278 +                       goto exit_device_put;
279 +       }
280  
281         return 0;
282  
283 @@ -577,13 +682,6 @@ static int __init lirc_rpi_init_module(void)
284         if (result)
285                 return result;
286  
287 -       if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) {
288 -               result = -EINVAL;
289 -               printk(KERN_ERR LIRC_DRIVER_NAME
290 -                      ": invalid GPIO pin(s) specified!\n");
291 -               goto exit_rpi;
292 -       }
293 -
294         result = init_port();
295         if (result < 0)
296                 goto exit_rpi;
297 -- 
298 1.8.3.2
299