blob: e7e428681ec56b3c32866264cc95eba1df4ac099 [file] [log] [blame]
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -07001/*
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>
Steven Kingeac57942012-05-21 13:10:19 -070017#include <linux/module.h>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070018#include <linux/init.h>
Kay Sieversa6ec0c02011-12-21 15:09:54 -080019#include <linux/device.h>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070020
Steven Kingeac57942012-05-21 13:10:19 -070021#include <linux/io.h>
22#include <asm/coldfire.h>
23#include <asm/mcfsim.h>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070024#include <asm/mcfgpio.h>
25
Steven Kingeac57942012-05-21 13:10:19 -070026int __mcfgpio_get_value(unsigned gpio)
27{
28 return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
29}
30EXPORT_SYMBOL(__mcfgpio_get_value);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070031
Steven Kingeac57942012-05-21 13:10:19 -070032void __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}
55EXPORT_SYMBOL(__mcfgpio_set_value);
56
57int __mcfgpio_direction_input(unsigned gpio)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070058{
59 unsigned long flags;
60 MCFGPIO_PORTTYPE dir;
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070061
62 local_irq_save(flags);
Steven Kingeac57942012-05-21 13:10:19 -070063 dir = mcfgpio_read(__mcfgpio_pddr(gpio));
64 dir &= ~mcfgpio_bit(gpio);
65 mcfgpio_write(dir, __mcfgpio_pddr(gpio));
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070066 local_irq_restore(flags);
67
68 return 0;
69}
Steven Kingeac57942012-05-21 13:10:19 -070070EXPORT_SYMBOL(__mcfgpio_direction_input);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070071
Steven Kingeac57942012-05-21 13:10:19 -070072int __mcfgpio_direction_output(unsigned gpio, int value)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070073{
74 unsigned long flags;
75 MCFGPIO_PORTTYPE data;
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070076
77 local_irq_save(flags);
Steven Kingeac57942012-05-21 13:10:19 -070078 data = mcfgpio_read(__mcfgpio_pddr(gpio));
Steven Kingffca5af2014-05-21 16:00:31 -070079 data |= mcfgpio_bit(gpio);
Steven Kingeac57942012-05-21 13:10:19 -070080 mcfgpio_write(data, __mcfgpio_pddr(gpio));
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070081
Steven Kingeac57942012-05-21 13:10:19 -070082 /* 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 }
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070098 local_irq_restore(flags);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070099 return 0;
100}
Steven Kingeac57942012-05-21 13:10:19 -0700101EXPORT_SYMBOL(__mcfgpio_direction_output);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700102
Steven Kingeac57942012-05-21 13:10:19 -0700103int __mcfgpio_request(unsigned gpio)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700104{
Steven Kingeac57942012-05-21 13:10:19 -0700105 return 0;
106}
107EXPORT_SYMBOL(__mcfgpio_request);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700108
Steven Kingeac57942012-05-21 13:10:19 -0700109void __mcfgpio_free(unsigned gpio)
110{
111 __mcfgpio_direction_input(gpio);
112}
113EXPORT_SYMBOL(__mcfgpio_free);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700114
Steven Kingeac57942012-05-21 13:10:19 -0700115#ifdef CONFIG_GPIOLIB
116
Steven Kingec9f8482014-05-21 16:00:32 -0700117static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
Steven Kingeac57942012-05-21 13:10:19 -0700118{
119 return __mcfgpio_direction_input(offset);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700120}
121
Steven Kingec9f8482014-05-21 16:00:32 -0700122static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700123{
Steven Kingeac57942012-05-21 13:10:19 -0700124 return __mcfgpio_get_value(offset);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700125}
126
Steven Kingec9f8482014-05-21 16:00:32 -0700127static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
128 int value)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700129{
Steven Kingeac57942012-05-21 13:10:19 -0700130 return __mcfgpio_direction_output(offset, value);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700131}
132
Steven Kingec9f8482014-05-21 16:00:32 -0700133static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
134 int value)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700135{
Steven Kingeac57942012-05-21 13:10:19 -0700136 __mcfgpio_set_value(offset, value);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700137}
138
Steven Kingec9f8482014-05-21 16:00:32 -0700139static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
Steven Kingeac57942012-05-21 13:10:19 -0700140{
141 return __mcfgpio_request(offset);
142}
143
Steven Kingec9f8482014-05-21 16:00:32 -0700144static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
Steven Kingeac57942012-05-21 13:10:19 -0700145{
146 __mcfgpio_free(offset);
147}
148
Steven Kingec9f8482014-05-21 16:00:32 -0700149static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
Steven King60fc65f2014-05-21 16:00:30 -0700150{
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
Steven Kingec9f8482014-05-21 16:00:32 -0700161static struct bus_type mcfgpio_subsys = {
Kay Sieversa6ec0c02011-12-21 15:09:54 -0800162 .name = "gpio",
163 .dev_name = "gpio",
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700164};
165
Steven Kingeac57942012-05-21 13:10:19 -0700166static 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,
Steven King60fc65f2014-05-21 16:00:30 -0700174 .to_irq = mcfgpio_to_irq,
Steven Kingeac57942012-05-21 13:10:19 -0700175 .base = 0,
176 .ngpio = MCFGPIO_PIN_MAX,
177};
Greg Ungererf23c1442012-04-17 13:25:38 +1000178
Steven Kingeac57942012-05-21 13:10:19 -0700179static int __init mcfgpio_sysinit(void)
180{
181 gpiochip_add(&mcfgpio_chip);
182 return subsys_system_register(&mcfgpio_subsys, NULL);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700183}
184
Steven Kingeac57942012-05-21 13:10:19 -0700185core_initcall(mcfgpio_sysinit);
186#endif