Merge tag 'please-pull-pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl...
[sfrench/cifs-2.6.git] / arch / m68k / coldfire / gpio.c
1 /*
2  * Coldfire generic GPIO support.
3  *
4  * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/device.h>
20
21 #include <linux/io.h>
22 #include <asm/coldfire.h>
23 #include <asm/mcfsim.h>
24 #include <asm/mcfgpio.h>
25
26 int __mcfgpio_get_value(unsigned gpio)
27 {
28         return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
29 }
30 EXPORT_SYMBOL(__mcfgpio_get_value);
31
32 void __mcfgpio_set_value(unsigned gpio, int value)
33 {
34         if (gpio < MCFGPIO_SCR_START) {
35                 unsigned long flags;
36                 MCFGPIO_PORTTYPE data;
37
38                 local_irq_save(flags);
39                 data = mcfgpio_read(__mcfgpio_podr(gpio));
40                 if (value)
41                         data |= mcfgpio_bit(gpio);
42                 else
43                         data &= ~mcfgpio_bit(gpio);
44                 mcfgpio_write(data, __mcfgpio_podr(gpio));
45                 local_irq_restore(flags);
46         } else {
47                 if (value)
48                         mcfgpio_write(mcfgpio_bit(gpio),
49                                         MCFGPIO_SETR_PORT(gpio));
50                 else
51                         mcfgpio_write(~mcfgpio_bit(gpio),
52                                         MCFGPIO_CLRR_PORT(gpio));
53         }
54 }
55 EXPORT_SYMBOL(__mcfgpio_set_value);
56
57 int __mcfgpio_direction_input(unsigned gpio)
58 {
59         unsigned long flags;
60         MCFGPIO_PORTTYPE dir;
61
62         local_irq_save(flags);
63         dir = mcfgpio_read(__mcfgpio_pddr(gpio));
64         dir &= ~mcfgpio_bit(gpio);
65         mcfgpio_write(dir, __mcfgpio_pddr(gpio));
66         local_irq_restore(flags);
67
68         return 0;
69 }
70 EXPORT_SYMBOL(__mcfgpio_direction_input);
71
72 int __mcfgpio_direction_output(unsigned gpio, int value)
73 {
74         unsigned long flags;
75         MCFGPIO_PORTTYPE data;
76
77         local_irq_save(flags);
78         data = mcfgpio_read(__mcfgpio_pddr(gpio));
79         data |= mcfgpio_bit(gpio);
80         mcfgpio_write(data, __mcfgpio_pddr(gpio));
81
82         /* now set the data to output */
83         if (gpio < MCFGPIO_SCR_START) {
84                 data = mcfgpio_read(__mcfgpio_podr(gpio));
85                 if (value)
86                         data |= mcfgpio_bit(gpio);
87                 else
88                         data &= ~mcfgpio_bit(gpio);
89                 mcfgpio_write(data, __mcfgpio_podr(gpio));
90         } else {
91                  if (value)
92                         mcfgpio_write(mcfgpio_bit(gpio),
93                                         MCFGPIO_SETR_PORT(gpio));
94                  else
95                          mcfgpio_write(~mcfgpio_bit(gpio),
96                                          MCFGPIO_CLRR_PORT(gpio));
97         }
98         local_irq_restore(flags);
99         return 0;
100 }
101 EXPORT_SYMBOL(__mcfgpio_direction_output);
102
103 int __mcfgpio_request(unsigned gpio)
104 {
105         return 0;
106 }
107 EXPORT_SYMBOL(__mcfgpio_request);
108
109 void __mcfgpio_free(unsigned gpio)
110 {
111         __mcfgpio_direction_input(gpio);
112 }
113 EXPORT_SYMBOL(__mcfgpio_free);
114
115 #ifdef CONFIG_GPIOLIB
116
117 static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
118 {
119         return __mcfgpio_direction_input(offset);
120 }
121
122 static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
123 {
124         return __mcfgpio_get_value(offset);
125 }
126
127 static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
128                                     int value)
129 {
130         return __mcfgpio_direction_output(offset, value);
131 }
132
133 static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
134                               int value)
135 {
136         __mcfgpio_set_value(offset, value);
137 }
138
139 static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
140 {
141         return __mcfgpio_request(offset);
142 }
143
144 static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
145 {
146         __mcfgpio_free(offset);
147 }
148
149 static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
150 {
151 #if defined(MCFGPIO_IRQ_MIN)
152         if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
153 #else
154         if (offset < MCFGPIO_IRQ_MAX)
155 #endif
156                 return MCFGPIO_IRQ_VECBASE + offset;
157         else
158                 return -EINVAL;
159 }
160
161 static struct bus_type mcfgpio_subsys = {
162         .name           = "gpio",
163         .dev_name       = "gpio",
164 };
165
166 static struct gpio_chip mcfgpio_chip = {
167         .label                  = "mcfgpio",
168         .request                = mcfgpio_request,
169         .free                   = mcfgpio_free,
170         .direction_input        = mcfgpio_direction_input,
171         .direction_output       = mcfgpio_direction_output,
172         .get                    = mcfgpio_get_value,
173         .set                    = mcfgpio_set_value,
174         .to_irq                 = mcfgpio_to_irq,
175         .base                   = 0,
176         .ngpio                  = MCFGPIO_PIN_MAX,
177 };
178
179 static int __init mcfgpio_sysinit(void)
180 {
181         gpiochip_add(&mcfgpio_chip);
182         return subsys_system_register(&mcfgpio_subsys, NULL);
183 }
184
185 core_initcall(mcfgpio_sysinit);
186 #endif