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 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/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 28 static DEFINE_SPINLOCK(x3proto_gpio_lock); 29 static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, }; 30 31 static 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); 38 data |= (1 << gpio); 39 __raw_writew(data, KEYCTLR); 40 spin_unlock_irqrestore(&x3proto_gpio_lock, flags); 41 42 return 0; 43 } 44 45 static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio) 46 { 47 return !!(__raw_readw(KEYDETR) & (1 << gpio)); 48 } 49 50 static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) 51 { 52 return x3proto_gpio_irq_map[gpio]; 53 } 54 55 static 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); 65 66 for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) 67 generic_handle_irq(x3proto_gpio_to_irq(NULL, pin)); 68 69 chip->irq_unmask(data); 70 } 71 72 struct 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 81 int __init x3proto_gpio_setup(void) 82 { 83 int ilsel; 84 int ret, i; 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 94 for (i = 0; i < NR_BASEBOARD_GPIOS; i++) { 95 unsigned long flags; 96 int irq = create_irq(); 97 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 121 err_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 130 err_gpio: 131 synchronize_irq(ilsel); 132 133 ilsel_disable(ILSEL_KEY); 134 135 return ret; 136 } 137