gpio.c (94bd217e2d683719ab21a4ac117d8a1b91cbedc9) | gpio.c (b98b35815f40f01337e25e3f0d10d57b7cec5126) |
---|---|
1/* 2 * arch/sh/boards/mach-x3proto/gpio.c 3 * 4 * Renesas SH-X3 Prototype Baseboard GPIO Support. 5 * | 1/* 2 * arch/sh/boards/mach-x3proto/gpio.c 3 * 4 * Renesas SH-X3 Prototype Baseboard GPIO Support. 5 * |
6 * Copyright (C) 2010 Paul Mundt | 6 * Copyright (C) 2010 - 2012 Paul Mundt |
7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14#include <linux/init.h> 15#include <linux/interrupt.h> 16#include <linux/gpio.h> 17#include <linux/irq.h> 18#include <linux/kernel.h> 19#include <linux/spinlock.h> | 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14#include <linux/init.h> 15#include <linux/interrupt.h> 16#include <linux/gpio.h> 17#include <linux/irq.h> 18#include <linux/kernel.h> 19#include <linux/spinlock.h> |
20#include <linux/irqdomain.h> |
|
20#include <linux/io.h> 21#include <mach/ilsel.h> 22#include <mach/hardware.h> 23 24#define KEYCTLR 0xb81c0000 25#define KEYOUTR 0xb81c0002 26#define KEYDETR 0xb81c0004 27 28static DEFINE_SPINLOCK(x3proto_gpio_lock); | 21#include <linux/io.h> 22#include <mach/ilsel.h> 23#include <mach/hardware.h> 24 25#define KEYCTLR 0xb81c0000 26#define KEYOUTR 0xb81c0002 27#define KEYDETR 0xb81c0004 28 29static DEFINE_SPINLOCK(x3proto_gpio_lock); |
29static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, }; | 30static struct irq_domain *x3proto_irq_domain; |
30 31static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) 32{ 33 unsigned long flags; 34 unsigned int data; 35 36 spin_lock_irqsave(&x3proto_gpio_lock, flags); 37 data = __raw_readw(KEYCTLR); --- 6 unchanged lines hidden (view full) --- 44 45static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio) 46{ 47 return !!(__raw_readw(KEYDETR) & (1 << gpio)); 48} 49 50static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) 51{ | 31 32static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) 33{ 34 unsigned long flags; 35 unsigned int data; 36 37 spin_lock_irqsave(&x3proto_gpio_lock, flags); 38 data = __raw_readw(KEYCTLR); --- 6 unchanged lines hidden (view full) --- 45 46static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio) 47{ 48 return !!(__raw_readw(KEYDETR) & (1 << gpio)); 49} 50 51static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) 52{ |
52 return x3proto_gpio_irq_map[gpio]; | 53 int virq; 54 55 if (gpio < chip->ngpio) 56 virq = irq_create_mapping(x3proto_irq_domain, gpio); 57 else 58 virq = -ENXIO; 59 60 return virq; |
53} 54 55static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 56{ 57 struct irq_data *data = irq_get_irq_data(irq); 58 struct irq_chip *chip = irq_data_get_irq_chip(data); 59 unsigned long mask; 60 int pin; 61 62 chip->irq_mask_ack(data); 63 64 mask = __raw_readw(KEYDETR); | 61} 62 63static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 64{ 65 struct irq_data *data = irq_get_irq_data(irq); 66 struct irq_chip *chip = irq_data_get_irq_chip(data); 67 unsigned long mask; 68 int pin; 69 70 chip->irq_mask_ack(data); 71 72 mask = __raw_readw(KEYDETR); |
65 | |
66 for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) | 73 for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) |
67 generic_handle_irq(x3proto_gpio_to_irq(NULL, pin)); | 74 generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin)); |
68 69 chip->irq_unmask(data); 70} 71 72struct gpio_chip x3proto_gpio_chip = { 73 .label = "x3proto-gpio", 74 .direction_input = x3proto_gpio_direction_input, 75 .get = x3proto_gpio_get, 76 .to_irq = x3proto_gpio_to_irq, 77 .base = -1, 78 .ngpio = NR_BASEBOARD_GPIOS, 79}; 80 | 75 76 chip->irq_unmask(data); 77} 78 79struct gpio_chip x3proto_gpio_chip = { 80 .label = "x3proto-gpio", 81 .direction_input = x3proto_gpio_direction_input, 82 .get = x3proto_gpio_get, 83 .to_irq = x3proto_gpio_to_irq, 84 .base = -1, 85 .ngpio = NR_BASEBOARD_GPIOS, 86}; 87 |
88static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq, 89 irq_hw_number_t hwirq) 90{ 91 irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq, 92 "gpio"); 93 94 return 0; 95} 96 97static struct irq_domain_ops x3proto_gpio_irq_ops = { 98 .map = x3proto_gpio_irq_map, 99 .xlate = irq_domain_xlate_twocell, 100}; 101 |
|
81int __init x3proto_gpio_setup(void) 82{ | 102int __init x3proto_gpio_setup(void) 103{ |
83 int ilsel; 84 int ret, i; | 104 int ilsel, ret; |
85 86 ilsel = ilsel_enable(ILSEL_KEY); 87 if (unlikely(ilsel < 0)) 88 return ilsel; 89 90 ret = gpiochip_add(&x3proto_gpio_chip); 91 if (unlikely(ret)) 92 goto err_gpio; 93 | 105 106 ilsel = ilsel_enable(ILSEL_KEY); 107 if (unlikely(ilsel < 0)) 108 return ilsel; 109 110 ret = gpiochip_add(&x3proto_gpio_chip); 111 if (unlikely(ret)) 112 goto err_gpio; 113 |
94 for (i = 0; i < NR_BASEBOARD_GPIOS; i++) { 95 unsigned long flags; 96 int irq = create_irq(); | 114 x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS, 115 &x3proto_gpio_irq_ops, NULL); 116 if (unlikely(!x3proto_irq_domain)) 117 goto err_irq; |
97 | 118 |
98 if (unlikely(irq < 0)) { 99 ret = -EINVAL; 100 goto err_irq; 101 } 102 103 spin_lock_irqsave(&x3proto_gpio_lock, flags); 104 x3proto_gpio_irq_map[i] = irq; 105 irq_set_chip_and_handler_name(irq, &dummy_irq_chip, 106 handle_simple_irq, "gpio"); 107 spin_unlock_irqrestore(&x3proto_gpio_lock, flags); 108 } 109 | |
110 pr_info("registering '%s' support, handling GPIOs %u -> %u, " 111 "bound to IRQ %u\n", 112 x3proto_gpio_chip.label, x3proto_gpio_chip.base, 113 x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio, 114 ilsel); 115 116 irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler); 117 irq_set_irq_wake(ilsel, 1); 118 119 return 0; 120 121err_irq: | 119 pr_info("registering '%s' support, handling GPIOs %u -> %u, " 120 "bound to IRQ %u\n", 121 x3proto_gpio_chip.label, x3proto_gpio_chip.base, 122 x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio, 123 ilsel); 124 125 irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler); 126 irq_set_irq_wake(ilsel, 1); 127 128 return 0; 129 130err_irq: |
122 for (; i >= 0; --i) 123 if (x3proto_gpio_irq_map[i]) 124 destroy_irq(x3proto_gpio_irq_map[i]); 125 | |
126 ret = gpiochip_remove(&x3proto_gpio_chip); 127 if (unlikely(ret)) 128 pr_err("Failed deregistering GPIO\n"); 129 130err_gpio: 131 synchronize_irq(ilsel); 132 133 ilsel_disable(ILSEL_KEY); 134 135 return ret; 136} | 131 ret = gpiochip_remove(&x3proto_gpio_chip); 132 if (unlikely(ret)) 133 pr_err("Failed deregistering GPIO\n"); 134 135err_gpio: 136 synchronize_irq(ilsel); 137 138 ilsel_disable(ILSEL_KEY); 139 140 return ret; 141} |