aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorsfking@fdwdc.com <sfking@fdwdc.com>2009-06-19 21:11:00 -0400
committerGreg Ungerer <gerg@uclinux.org>2009-09-09 22:01:22 -0400
commitaf39bb8b07af83b579c90c09ba3943123cdb4132 (patch)
tree8c1965a7a7d6ba09344549410e3ee476af8ffb1d /arch
parent74fca6a42863ffacaf7ba6f1936a9f228950f657 (diff)
core generic GPIO support for Freescale Coldfire processors.
This adds the basic infrastructure used by all of the different Coldfire CPUs. Signed-off-by: Steven King <sfking@fdwdc.com> Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/m68k/include/asm/gpio.h238
-rw-r--r--arch/m68k/include/asm/mcfgpio.h40
-rw-r--r--arch/m68k/include/asm/pinmux.h30
-rw-r--r--arch/m68knommu/Kconfig6
-rw-r--r--arch/m68knommu/platform/coldfire/Makefile1
-rw-r--r--arch/m68knommu/platform/coldfire/gpio.c127
-rw-r--r--arch/m68knommu/platform/coldfire/pinmux.c28
7 files changed, 470 insertions, 0 deletions
diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h
new file mode 100644
index 000000000000..283214dc65a7
--- /dev/null
+++ b/arch/m68k/include/asm/gpio.h
@@ -0,0 +1,238 @@
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#ifndef coldfire_gpio_h
17#define coldfire_gpio_h
18
19#include <linux/io.h>
20#include <asm-generic/gpio.h>
21#include <asm/coldfire.h>
22#include <asm/mcfsim.h>
23
24/*
25 * The Freescale Coldfire family is quite varied in how they implement GPIO.
26 * Some parts have 8 bit ports, some have 16bit and some have 32bit; some have
27 * only one port, others have multiple ports; some have a single data latch
28 * for both input and output, others have a separate pin data register to read
29 * input; some require a read-modify-write access to change an output, others
30 * have set and clear registers for some of the outputs; Some have all the
31 * GPIOs in a single control area, others have some GPIOs implemented in
32 * different modules.
33 *
34 * This implementation attempts accomodate the differences while presenting
35 * a generic interface that will optimize to as few instructions as possible.
36 */
37#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
38 defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
39 defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
40
41/* These parts have GPIO organized by 8 bit ports */
42
43#define MCFGPIO_PORTTYPE u8
44#define MCFGPIO_PORTSIZE 8
45#define mcfgpio_read(port) __raw_readb(port)
46#define mcfgpio_write(data, port) __raw_writeb(data, port)
47
48#elif defined(CONFIG_M5307) || defined(CONFIG_M5407) || defined(CONFIG_M5272)
49
50/* These parts have GPIO organized by 16 bit ports */
51
52#define MCFGPIO_PORTTYPE u16
53#define MCFGPIO_PORTSIZE 16
54#define mcfgpio_read(port) __raw_readw(port)
55#define mcfgpio_write(data, port) __raw_writew(data, port)
56
57#elif defined(CONFIG_M5249)
58
59/* These parts have GPIO organized by 32 bit ports */
60
61#define MCFGPIO_PORTTYPE u32
62#define MCFGPIO_PORTSIZE 32
63#define mcfgpio_read(port) __raw_readl(port)
64#define mcfgpio_write(data, port) __raw_writel(data, port)
65
66#endif
67
68#define mcfgpio_bit(gpio) (1 << ((gpio) % MCFGPIO_PORTSIZE))
69#define mcfgpio_port(gpio) ((gpio) / MCFGPIO_PORTSIZE)
70
71#if defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
72 defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
73/*
74 * These parts have an 'Edge' Port module (external interrupt/GPIO) which uses
75 * read-modify-write to change an output and a GPIO module which has separate
76 * set/clr registers to directly change outputs with a single write access.
77 */
78#if defined(CONFIG_M528x)
79/*
80 * The 528x also has GPIOs in other modules (GPT, QADC) which use
81 * read-modify-write as well as those controlled by the EPORT and GPIO modules.
82 */
83#define MCFGPIO_SCR_START 40
84#else
85#define MCFGPIO_SCR_START 8
86#endif
87
88#define MCFGPIO_SETR_PORT(gpio) (MCFGPIO_SETR + \
89 mcfgpio_port(gpio - MCFGPIO_SCR_START))
90
91#define MCFGPIO_CLRR_PORT(gpio) (MCFGPIO_CLRR + \
92 mcfgpio_port(gpio - MCFGPIO_SCR_START))
93#else
94
95#define MCFGPIO_SCR_START MCFGPIO_PIN_MAX
96/* with MCFGPIO_SCR == MCFGPIO_PIN_MAX, these will be optimized away */
97#define MCFGPIO_SETR_PORT(gpio) 0
98#define MCFGPIO_CLRR_PORT(gpio) 0
99
100#endif
101/*
102 * Coldfire specific helper functions
103 */
104
105/* return the port pin data register for a gpio */
106static inline u32 __mcf_gpio_ppdr(unsigned gpio)
107{
108#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
109 defined(CONFIG_M5307) || defined(CONFIG_M5407)
110 return MCFSIM_PADAT;
111#elif defined(CONFIG_M5272)
112 if (gpio < 16)
113 return MCFSIM_PADAT;
114 else if (gpio < 32)
115 return MCFSIM_PBDAT;
116 else
117 return MCFSIM_PCDAT;
118#elif defined(CONFIG_M5249)
119 if (gpio < 32)
120 return MCFSIM2_GPIOREAD;
121 else
122 return MCFSIM2_GPIO1READ;
123#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
124 defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
125 if (gpio < 8)
126 return MCFEPORT_EPPDR;
127#if defined(CONFIG_M528x)
128 else if (gpio < 16)
129 return MCFGPTA_GPTPORT;
130 else if (gpio < 24)
131 return MCFGPTB_GPTPORT;
132 else if (gpio < 32)
133 return MCFQADC_PORTQA;
134 else if (gpio < 40)
135 return MCFQADC_PORTQB;
136#endif
137 else
138 return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
139#endif
140}
141
142/* return the port output data register for a gpio */
143static inline u32 __mcf_gpio_podr(unsigned gpio)
144{
145#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
146 defined(CONFIG_M5307) || defined(CONFIG_M5407)
147 return MCFSIM_PADAT;
148#elif defined(CONFIG_M5272)
149 if (gpio < 16)
150 return MCFSIM_PADAT;
151 else if (gpio < 32)
152 return MCFSIM_PBDAT;
153 else
154 return MCFSIM_PCDAT;
155#elif defined(CONFIG_M5249)
156 if (gpio < 32)
157 return MCFSIM2_GPIOWRITE;
158 else
159 return MCFSIM2_GPIO1WRITE;
160#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
161 defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
162 if (gpio < 8)
163 return MCFEPORT_EPDR;
164#if defined(CONFIG_M528x)
165 else if (gpio < 16)
166 return MCFGPTA_GPTPORT;
167 else if (gpio < 24)
168 return MCFGPTB_GPTPORT;
169 else if (gpio < 32)
170 return MCFQADC_PORTQA;
171 else if (gpio < 40)
172 return MCFQADC_PORTQB;
173#endif
174 else
175 return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
176#endif
177}
178
179/*
180 * The Generic GPIO functions
181 *
182 * If the gpio is a compile time constant and is one of the Coldfire gpios,
183 * use the inline version, otherwise dispatch thru gpiolib.
184 */
185
186static inline int gpio_get_value(unsigned gpio)
187{
188 if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX)
189 return mcfgpio_read(__mcf_gpio_ppdr(gpio)) & mcfgpio_bit(gpio);
190 else
191 return __gpio_get_value(gpio);
192}
193
194static inline void gpio_set_value(unsigned gpio, int value)
195{
196 if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) {
197 if (gpio < MCFGPIO_SCR_START) {
198 unsigned long flags;
199 MCFGPIO_PORTTYPE data;
200
201 local_irq_save(flags);
202 data = mcfgpio_read(__mcf_gpio_podr(gpio));
203 if (value)
204 data |= mcfgpio_bit(gpio);
205 else
206 data &= ~mcfgpio_bit(gpio);
207 mcfgpio_write(data, __mcf_gpio_podr(gpio));
208 local_irq_restore(flags);
209 } else {
210 if (value)
211 mcfgpio_write(mcfgpio_bit(gpio),
212 MCFGPIO_SETR_PORT(gpio));
213 else
214 mcfgpio_write(~mcfgpio_bit(gpio),
215 MCFGPIO_CLRR_PORT(gpio));
216 }
217 } else
218 __gpio_set_value(gpio, value);
219}
220
221static inline int gpio_to_irq(unsigned gpio)
222{
223 return (gpio < MCFGPIO_IRQ_MAX) ? gpio + MCFGPIO_IRQ_VECBASE : -EINVAL;
224}
225
226static inline int irq_to_gpio(unsigned irq)
227{
228 return (irq >= MCFGPIO_IRQ_VECBASE &&
229 irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) ?
230 irq - MCFGPIO_IRQ_VECBASE : -ENXIO;
231}
232
233static inline int gpio_cansleep(unsigned gpio)
234{
235 return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio);
236}
237
238#endif
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h
new file mode 100644
index 000000000000..ee5e4ccce89e
--- /dev/null
+++ b/arch/m68k/include/asm/mcfgpio.h
@@ -0,0 +1,40 @@
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#ifndef mcfgpio_h
17#define mcfgpio_h
18
19#include <linux/io.h>
20#include <asm-generic/gpio.h>
21
22struct mcf_gpio_chip {
23 struct gpio_chip gpio_chip;
24 void __iomem *pddr;
25 void __iomem *podr;
26 void __iomem *ppdr;
27 void __iomem *setr;
28 void __iomem *clrr;
29 const u8 *gpio_to_pinmux;
30};
31
32int mcf_gpio_direction_input(struct gpio_chip *, unsigned);
33int mcf_gpio_get_value(struct gpio_chip *, unsigned);
34int mcf_gpio_direction_output(struct gpio_chip *, unsigned, int);
35void mcf_gpio_set_value(struct gpio_chip *, unsigned, int);
36void mcf_gpio_set_value_fast(struct gpio_chip *, unsigned, int);
37int mcf_gpio_request(struct gpio_chip *, unsigned);
38void mcf_gpio_free(struct gpio_chip *, unsigned);
39
40#endif
diff --git a/arch/m68k/include/asm/pinmux.h b/arch/m68k/include/asm/pinmux.h
new file mode 100644
index 000000000000..119ee686dbd1
--- /dev/null
+++ b/arch/m68k/include/asm/pinmux.h
@@ -0,0 +1,30 @@
1/*
2 * Coldfire generic GPIO pinmux 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#ifndef pinmux_h
17#define pinmux_h
18
19#define MCFPINMUX_NONE -1
20
21extern int mcf_pinmux_request(unsigned, unsigned);
22extern void mcf_pinmux_release(unsigned, unsigned);
23
24static inline int mcf_pinmux_is_valid(unsigned pinmux)
25{
26 return pinmux != MCFPINMUX_NONE;
27}
28
29#endif
30
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 534376299a99..e2201b90aa22 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -47,6 +47,10 @@ config GENERIC_FIND_NEXT_BIT
47 bool 47 bool
48 default y 48 default y
49 49
50config GENERIC_GPIO
51 bool
52 default n
53
50config GENERIC_HWEIGHT 54config GENERIC_HWEIGHT
51 bool 55 bool
52 default y 56 default y
@@ -182,6 +186,8 @@ config M527x
182config COLDFIRE 186config COLDFIRE
183 bool 187 bool
184 depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407) 188 depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407)
189 select GENERIC_GPIO
190 select ARCH_REQUIRE_GPIOLIB
185 default y 191 default y
186 192
187config CLOCK_SET 193config CLOCK_SET
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile
index 1bcb9372353f..2667323c7fee 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -27,4 +27,5 @@ obj-$(CONFIG_M5307) += timers.o
27obj-$(CONFIG_M532x) += timers.o 27obj-$(CONFIG_M532x) += timers.o
28obj-$(CONFIG_M5407) += timers.o 28obj-$(CONFIG_M5407) += timers.o
29 29
30obj-y += pinmux.o gpio.o
30extra-y := head.o 31extra-y := head.o
diff --git a/arch/m68knommu/platform/coldfire/gpio.c b/arch/m68knommu/platform/coldfire/gpio.c
new file mode 100644
index 000000000000..ff0045793450
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/gpio.c
@@ -0,0 +1,127 @@
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/init.h>
18#include <linux/sysdev.h>
19
20#include <asm/gpio.h>
21#include <asm/pinmux.h>
22#include <asm/mcfgpio.h>
23
24#define MCF_CHIP(chip) container_of(chip, struct mcf_gpio_chip, gpio_chip)
25
26int mcf_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
27{
28 unsigned long flags;
29 MCFGPIO_PORTTYPE dir;
30 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
31
32 local_irq_save(flags);
33 dir = mcfgpio_read(mcf_chip->pddr);
34 dir &= ~mcfgpio_bit(chip->base + offset);
35 mcfgpio_write(dir, mcf_chip->pddr);
36 local_irq_restore(flags);
37
38 return 0;
39}
40
41int mcf_gpio_get_value(struct gpio_chip *chip, unsigned offset)
42{
43 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
44
45 return mcfgpio_read(mcf_chip->ppdr) & mcfgpio_bit(chip->base + offset);
46}
47
48int mcf_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
49 int value)
50{
51 unsigned long flags;
52 MCFGPIO_PORTTYPE data;
53 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
54
55 local_irq_save(flags);
56 /* write the value to the output latch */
57 data = mcfgpio_read(mcf_chip->podr);
58 if (value)
59 data |= mcfgpio_bit(chip->base + offset);
60 else
61 data &= ~mcfgpio_bit(chip->base + offset);
62 mcfgpio_write(data, mcf_chip->podr);
63
64 /* now set the direction to output */
65 data = mcfgpio_read(mcf_chip->pddr);
66 data |= mcfgpio_bit(chip->base + offset);
67 mcfgpio_write(data, mcf_chip->pddr);
68 local_irq_restore(flags);
69
70 return 0;
71}
72
73void mcf_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
74{
75 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
76
77 unsigned long flags;
78 MCFGPIO_PORTTYPE data;
79
80 local_irq_save(flags);
81 data = mcfgpio_read(mcf_chip->podr);
82 if (value)
83 data |= mcfgpio_bit(chip->base + offset);
84 else
85 data &= ~mcfgpio_bit(chip->base + offset);
86 mcfgpio_write(data, mcf_chip->podr);
87 local_irq_restore(flags);
88}
89
90void mcf_gpio_set_value_fast(struct gpio_chip *chip, unsigned offset, int value)
91{
92 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
93
94 if (value)
95 mcfgpio_write(mcfgpio_bit(chip->base + offset), mcf_chip->setr);
96 else
97 mcfgpio_write(~mcfgpio_bit(chip->base + offset), mcf_chip->clrr);
98}
99
100int mcf_gpio_request(struct gpio_chip *chip, unsigned offset)
101{
102 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
103
104 return mcf_chip->gpio_to_pinmux ?
105 mcf_pinmux_request(mcf_chip->gpio_to_pinmux[offset], 0) : 0;
106}
107
108void mcf_gpio_free(struct gpio_chip *chip, unsigned offset)
109{
110 struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
111
112 mcf_gpio_direction_input(chip, offset);
113
114 if (mcf_chip->gpio_to_pinmux)
115 mcf_pinmux_release(mcf_chip->gpio_to_pinmux[offset], 0);
116}
117
118struct sysdev_class mcf_gpio_sysclass = {
119 .name = "gpio",
120};
121
122static int __init mcf_gpio_sysinit(void)
123{
124 return sysdev_class_register(&mcf_gpio_sysclass);
125}
126
127core_initcall(mcf_gpio_sysinit);
diff --git a/arch/m68knommu/platform/coldfire/pinmux.c b/arch/m68knommu/platform/coldfire/pinmux.c
new file mode 100644
index 000000000000..8c62b825939f
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/pinmux.c
@@ -0,0 +1,28 @@
1/*
2 * Coldfire generic GPIO pinmux 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
17#include <linux/kernel.h>
18
19#include <asm/pinmux.h>
20
21int mcf_pinmux_request(unsigned pinmux, unsigned func)
22{
23 return 0;
24}
25
26void mcf_pinmux_release(unsigned pinmux, unsigned func)
27{
28}