aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-06-14 20:45:39 -0400
committerOlof Johansson <olof@lixom.net>2013-06-14 20:45:39 -0400
commit38d77ff90a47d198d2fd3ebd766ee84eaa71a0d2 (patch)
tree7adc209e84f7c45fba521d3430350d8a70ac4a75 /drivers/gpio
parent2c3165ebb641e0ff3faf1c87ed1c8fbd85871da0 (diff)
parent159f8a0209aff155af7f6fcdedd4a4484dd19c23 (diff)
Merge tag 'renesas-gpio-rcar-for-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/drivers
From Simon Horman: Renesas ARM based SoC GPIO R-Car updates for v3.11 DT support to GPIO R-Car driver by Laurent Pinchart. * tag 'renesas-gpio-rcar-for-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas: (131 commits) gpio-rcar: Add DT support
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-rcar.c94
1 files changed, 78 insertions, 16 deletions
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index b4ca450947b8..5a693dd0ac7a 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -49,6 +49,9 @@ struct gpio_rcar_priv {
49#define POSNEG 0x20 49#define POSNEG 0x20
50#define EDGLEVEL 0x24 50#define EDGLEVEL 0x24
51#define FILONOFF 0x28 51#define FILONOFF 0x28
52#define BOTHEDGE 0x4c
53
54#define RCAR_MAX_GPIO_PER_BANK 32
52 55
53static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs) 56static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
54{ 57{
@@ -91,7 +94,8 @@ static void gpio_rcar_irq_enable(struct irq_data *d)
91static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, 94static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
92 unsigned int hwirq, 95 unsigned int hwirq,
93 bool active_high_rising_edge, 96 bool active_high_rising_edge,
94 bool level_trigger) 97 bool level_trigger,
98 bool both)
95{ 99{
96 unsigned long flags; 100 unsigned long flags;
97 101
@@ -108,6 +112,10 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
108 /* Configure edge or level trigger in EDGLEVEL */ 112 /* Configure edge or level trigger in EDGLEVEL */
109 gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger); 113 gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger);
110 114
115 /* Select one edge or both edges in BOTHEDGE */
116 if (p->config.has_both_edge_trigger)
117 gpio_rcar_modify_bit(p, BOTHEDGE, hwirq, both);
118
111 /* Select "Interrupt Input Mode" in IOINTSEL */ 119 /* Select "Interrupt Input Mode" in IOINTSEL */
112 gpio_rcar_modify_bit(p, IOINTSEL, hwirq, true); 120 gpio_rcar_modify_bit(p, IOINTSEL, hwirq, true);
113 121
@@ -127,16 +135,26 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
127 135
128 switch (type & IRQ_TYPE_SENSE_MASK) { 136 switch (type & IRQ_TYPE_SENSE_MASK) {
129 case IRQ_TYPE_LEVEL_HIGH: 137 case IRQ_TYPE_LEVEL_HIGH:
130 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true); 138 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true,
139 false);
131 break; 140 break;
132 case IRQ_TYPE_LEVEL_LOW: 141 case IRQ_TYPE_LEVEL_LOW:
133 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true); 142 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true,
143 false);
134 break; 144 break;
135 case IRQ_TYPE_EDGE_RISING: 145 case IRQ_TYPE_EDGE_RISING:
136 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false); 146 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
147 false);
137 break; 148 break;
138 case IRQ_TYPE_EDGE_FALLING: 149 case IRQ_TYPE_EDGE_FALLING:
139 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false); 150 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false,
151 false);
152 break;
153 case IRQ_TYPE_EDGE_BOTH:
154 if (!p->config.has_both_edge_trigger)
155 return -EINVAL;
156 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
157 true);
140 break; 158 break;
141 default: 159 default:
142 return -EINVAL; 160 return -EINVAL;
@@ -258,9 +276,39 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = {
258 .map = gpio_rcar_irq_domain_map, 276 .map = gpio_rcar_irq_domain_map,
259}; 277};
260 278
279static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)
280{
281 struct gpio_rcar_config *pdata = p->pdev->dev.platform_data;
282#ifdef CONFIG_OF
283 struct device_node *np = p->pdev->dev.of_node;
284 struct of_phandle_args args;
285 int ret;
286#endif
287
288 if (pdata)
289 p->config = *pdata;
290#ifdef CONFIG_OF
291 else if (np) {
292 ret = of_parse_phandle_with_args(np, "gpio-ranges",
293 "#gpio-range-cells", 0, &args);
294 p->config.number_of_pins = ret == 0 && args.args_count == 3
295 ? args.args[2]
296 : RCAR_MAX_GPIO_PER_BANK;
297 p->config.gpio_base = -1;
298 }
299#endif
300
301 if (p->config.number_of_pins == 0 ||
302 p->config.number_of_pins > RCAR_MAX_GPIO_PER_BANK) {
303 dev_warn(&p->pdev->dev,
304 "Invalid number of gpio lines %u, using %u\n",
305 p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK);
306 p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK;
307 }
308}
309
261static int gpio_rcar_probe(struct platform_device *pdev) 310static int gpio_rcar_probe(struct platform_device *pdev)
262{ 311{
263 struct gpio_rcar_config *pdata = pdev->dev.platform_data;
264 struct gpio_rcar_priv *p; 312 struct gpio_rcar_priv *p;
265 struct resource *io, *irq; 313 struct resource *io, *irq;
266 struct gpio_chip *gpio_chip; 314 struct gpio_chip *gpio_chip;
@@ -275,14 +323,14 @@ static int gpio_rcar_probe(struct platform_device *pdev)
275 goto err0; 323 goto err0;
276 } 324 }
277 325
278 /* deal with driver instance configuration */
279 if (pdata)
280 p->config = *pdata;
281
282 p->pdev = pdev; 326 p->pdev = pdev;
283 platform_set_drvdata(pdev, p);
284 spin_lock_init(&p->lock); 327 spin_lock_init(&p->lock);
285 328
329 /* Get device configuration from DT node or platform data. */
330 gpio_rcar_parse_pdata(p);
331
332 platform_set_drvdata(pdev, p);
333
286 io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 334 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
287 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 335 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
288 336
@@ -309,6 +357,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
309 gpio_chip->set = gpio_rcar_set; 357 gpio_chip->set = gpio_rcar_set;
310 gpio_chip->to_irq = gpio_rcar_to_irq; 358 gpio_chip->to_irq = gpio_rcar_to_irq;
311 gpio_chip->label = name; 359 gpio_chip->label = name;
360 gpio_chip->dev = &pdev->dev;
312 gpio_chip->owner = THIS_MODULE; 361 gpio_chip->owner = THIS_MODULE;
313 gpio_chip->base = p->config.gpio_base; 362 gpio_chip->base = p->config.gpio_base;
314 gpio_chip->ngpio = p->config.number_of_pins; 363 gpio_chip->ngpio = p->config.number_of_pins;
@@ -333,7 +382,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
333 } 382 }
334 383
335 if (devm_request_irq(&pdev->dev, irq->start, 384 if (devm_request_irq(&pdev->dev, irq->start,
336 gpio_rcar_irq_handler, 0, name, p)) { 385 gpio_rcar_irq_handler, IRQF_SHARED, name, p)) {
337 dev_err(&pdev->dev, "failed to request IRQ\n"); 386 dev_err(&pdev->dev, "failed to request IRQ\n");
338 ret = -ENOENT; 387 ret = -ENOENT;
339 goto err1; 388 goto err1;
@@ -355,10 +404,12 @@ static int gpio_rcar_probe(struct platform_device *pdev)
355 p->config.irq_base, ret); 404 p->config.irq_base, ret);
356 } 405 }
357 406
358 ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0, 407 if (p->config.pctl_name) {
359 gpio_chip->base, gpio_chip->ngpio); 408 ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0,
360 if (ret < 0) 409 gpio_chip->base, gpio_chip->ngpio);
361 dev_warn(&pdev->dev, "failed to add pin range\n"); 410 if (ret < 0)
411 dev_warn(&pdev->dev, "failed to add pin range\n");
412 }
362 413
363 return 0; 414 return 0;
364 415
@@ -381,11 +432,22 @@ static int gpio_rcar_remove(struct platform_device *pdev)
381 return 0; 432 return 0;
382} 433}
383 434
435#ifdef CONFIG_OF
436static const struct of_device_id gpio_rcar_of_table[] = {
437 {
438 .compatible = "renesas,gpio-rcar",
439 },
440};
441
442MODULE_DEVICE_TABLE(of, gpio_rcar_of_table);
443#endif
444
384static struct platform_driver gpio_rcar_device_driver = { 445static struct platform_driver gpio_rcar_device_driver = {
385 .probe = gpio_rcar_probe, 446 .probe = gpio_rcar_probe,
386 .remove = gpio_rcar_remove, 447 .remove = gpio_rcar_remove,
387 .driver = { 448 .driver = {
388 .name = "gpio_rcar", 449 .name = "gpio_rcar",
450 .of_match_table = of_match_ptr(gpio_rcar_of_table),
389 } 451 }
390}; 452};
391 453