GNU Linux-libre 4.9.318-gnu1
[releases.git] / arch / arm / mach-w90x900 / gpio.c
1 /*
2  * linux/arch/arm/mach-w90x900/gpio.c
3  *
4  * Generic nuc900 GPIO handling
5  *
6  *  Wan ZongShun <mcuos.com@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/clk.h>
14 #include <linux/errno.h>
15 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <linux/debugfs.h>
18 #include <linux/seq_file.h>
19 #include <linux/kernel.h>
20 #include <linux/list.h>
21 #include <linux/module.h>
22 #include <linux/io.h>
23 #include <linux/gpio/driver.h>
24
25 #include <mach/hardware.h>
26
27 #define GPIO_BASE               (W90X900_VA_GPIO)
28 #define GPIO_DIR                (0x04)
29 #define GPIO_OUT                (0x08)
30 #define GPIO_IN                 (0x0C)
31 #define GROUPINERV              (0x10)
32 #define GPIO_GPIO(Nb)           (0x00000001 << (Nb))
33
34 #define NUC900_GPIO_CHIP(name, base_gpio, nr_gpio)                      \
35         {                                                               \
36                 .chip = {                                               \
37                         .label            = name,                       \
38                         .direction_input  = nuc900_dir_input,           \
39                         .direction_output = nuc900_dir_output,          \
40                         .get              = nuc900_gpio_get,            \
41                         .set              = nuc900_gpio_set,            \
42                         .base             = base_gpio,                  \
43                         .ngpio            = nr_gpio,                    \
44                 }                                                       \
45         }
46
47 struct nuc900_gpio_chip {
48         struct gpio_chip        chip;
49         void __iomem            *regbase;       /* Base of group register*/
50         spinlock_t              gpio_lock;
51 };
52
53 static int nuc900_gpio_get(struct gpio_chip *chip, unsigned offset)
54 {
55         struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
56         void __iomem *pio = nuc900_gpio->regbase + GPIO_IN;
57         unsigned int regval;
58
59         regval = __raw_readl(pio);
60         regval &= GPIO_GPIO(offset);
61
62         return (regval != 0);
63 }
64
65 static void nuc900_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
66 {
67         struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
68         void __iomem *pio = nuc900_gpio->regbase + GPIO_OUT;
69         unsigned int regval;
70         unsigned long flags;
71
72         spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
73
74         regval = __raw_readl(pio);
75
76         if (val)
77                 regval |= GPIO_GPIO(offset);
78         else
79                 regval &= ~GPIO_GPIO(offset);
80
81         __raw_writel(regval, pio);
82
83         spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
84 }
85
86 static int nuc900_dir_input(struct gpio_chip *chip, unsigned offset)
87 {
88         struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
89         void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
90         unsigned int regval;
91         unsigned long flags;
92
93         spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
94
95         regval = __raw_readl(pio);
96         regval &= ~GPIO_GPIO(offset);
97         __raw_writel(regval, pio);
98
99         spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
100
101         return 0;
102 }
103
104 static int nuc900_dir_output(struct gpio_chip *chip, unsigned offset, int val)
105 {
106         struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
107         void __iomem *outreg = nuc900_gpio->regbase + GPIO_OUT;
108         void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
109         unsigned int regval;
110         unsigned long flags;
111
112         spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
113
114         regval = __raw_readl(pio);
115         regval |= GPIO_GPIO(offset);
116         __raw_writel(regval, pio);
117
118         regval = __raw_readl(outreg);
119
120         if (val)
121                 regval |= GPIO_GPIO(offset);
122         else
123                 regval &= ~GPIO_GPIO(offset);
124
125         __raw_writel(regval, outreg);
126
127         spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
128
129         return 0;
130 }
131
132 static struct nuc900_gpio_chip nuc900_gpio[] = {
133         NUC900_GPIO_CHIP("GROUPC", 0, 16),
134         NUC900_GPIO_CHIP("GROUPD", 16, 10),
135         NUC900_GPIO_CHIP("GROUPE", 26, 14),
136         NUC900_GPIO_CHIP("GROUPF", 40, 10),
137         NUC900_GPIO_CHIP("GROUPG", 50, 17),
138         NUC900_GPIO_CHIP("GROUPH", 67, 8),
139         NUC900_GPIO_CHIP("GROUPI", 75, 17),
140 };
141
142 void __init nuc900_init_gpio(int nr_group)
143 {
144         unsigned        i;
145         struct nuc900_gpio_chip *gpio_chip;
146
147         for (i = 0; i < nr_group; i++) {
148                 gpio_chip = &nuc900_gpio[i];
149                 spin_lock_init(&gpio_chip->gpio_lock);
150                 gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
151                 gpiochip_add_data(&gpio_chip->chip, gpio_chip);
152         }
153 }