blob: ca26de257871d608c4aecfc1264a6ac46560662e [file] [log] [blame]
Thomas Gleixner8e8e69d2019-05-29 07:17:59 -07001// SPDX-License-Identifier: GPL-2.0-only
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -07002/*
3 * Coldfire generic GPIO support.
4 *
5 * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -07006 */
7
8#include <linux/kernel.h>
Steven Kingeac57942012-05-21 13:10:19 -07009#include <linux/module.h>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070010#include <linux/init.h>
Kay Sieversa6ec0c02011-12-21 15:09:54 -080011#include <linux/device.h>
Linus Walleij372ea262019-08-21 09:09:23 +020012#include <linux/gpio/driver.h>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070013
Steven Kingeac57942012-05-21 13:10:19 -070014#include <linux/io.h>
15#include <asm/coldfire.h>
16#include <asm/mcfsim.h>
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070017#include <asm/mcfgpio.h>
18
Steven Kingeac57942012-05-21 13:10:19 -070019int __mcfgpio_get_value(unsigned gpio)
20{
21 return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
22}
23EXPORT_SYMBOL(__mcfgpio_get_value);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070024
Steven Kingeac57942012-05-21 13:10:19 -070025void __mcfgpio_set_value(unsigned gpio, int value)
26{
27 if (gpio < MCFGPIO_SCR_START) {
28 unsigned long flags;
29 MCFGPIO_PORTTYPE data;
30
31 local_irq_save(flags);
32 data = mcfgpio_read(__mcfgpio_podr(gpio));
33 if (value)
34 data |= mcfgpio_bit(gpio);
35 else
36 data &= ~mcfgpio_bit(gpio);
37 mcfgpio_write(data, __mcfgpio_podr(gpio));
38 local_irq_restore(flags);
39 } else {
40 if (value)
41 mcfgpio_write(mcfgpio_bit(gpio),
42 MCFGPIO_SETR_PORT(gpio));
43 else
44 mcfgpio_write(~mcfgpio_bit(gpio),
45 MCFGPIO_CLRR_PORT(gpio));
46 }
47}
48EXPORT_SYMBOL(__mcfgpio_set_value);
49
50int __mcfgpio_direction_input(unsigned gpio)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070051{
52 unsigned long flags;
53 MCFGPIO_PORTTYPE dir;
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070054
55 local_irq_save(flags);
Steven Kingeac57942012-05-21 13:10:19 -070056 dir = mcfgpio_read(__mcfgpio_pddr(gpio));
57 dir &= ~mcfgpio_bit(gpio);
58 mcfgpio_write(dir, __mcfgpio_pddr(gpio));
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070059 local_irq_restore(flags);
60
61 return 0;
62}
Steven Kingeac57942012-05-21 13:10:19 -070063EXPORT_SYMBOL(__mcfgpio_direction_input);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070064
Steven Kingeac57942012-05-21 13:10:19 -070065int __mcfgpio_direction_output(unsigned gpio, int value)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070066{
67 unsigned long flags;
68 MCFGPIO_PORTTYPE data;
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070069
70 local_irq_save(flags);
Steven Kingeac57942012-05-21 13:10:19 -070071 data = mcfgpio_read(__mcfgpio_pddr(gpio));
Steven Kingffca5af2014-05-21 16:00:31 -070072 data |= mcfgpio_bit(gpio);
Steven Kingeac57942012-05-21 13:10:19 -070073 mcfgpio_write(data, __mcfgpio_pddr(gpio));
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070074
Steven Kingeac57942012-05-21 13:10:19 -070075 /* now set the data to output */
76 if (gpio < MCFGPIO_SCR_START) {
77 data = mcfgpio_read(__mcfgpio_podr(gpio));
78 if (value)
79 data |= mcfgpio_bit(gpio);
80 else
81 data &= ~mcfgpio_bit(gpio);
82 mcfgpio_write(data, __mcfgpio_podr(gpio));
83 } else {
84 if (value)
85 mcfgpio_write(mcfgpio_bit(gpio),
86 MCFGPIO_SETR_PORT(gpio));
87 else
88 mcfgpio_write(~mcfgpio_bit(gpio),
89 MCFGPIO_CLRR_PORT(gpio));
90 }
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070091 local_irq_restore(flags);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070092 return 0;
93}
Steven Kingeac57942012-05-21 13:10:19 -070094EXPORT_SYMBOL(__mcfgpio_direction_output);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070095
Steven Kingeac57942012-05-21 13:10:19 -070096int __mcfgpio_request(unsigned gpio)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -070097{
Steven Kingeac57942012-05-21 13:10:19 -070098 return 0;
99}
100EXPORT_SYMBOL(__mcfgpio_request);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700101
Steven Kingeac57942012-05-21 13:10:19 -0700102void __mcfgpio_free(unsigned gpio)
103{
104 __mcfgpio_direction_input(gpio);
105}
106EXPORT_SYMBOL(__mcfgpio_free);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700107
Steven Kingeac57942012-05-21 13:10:19 -0700108#ifdef CONFIG_GPIOLIB
109
Steven Kingec9f8482014-05-21 16:00:32 -0700110static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
Steven Kingeac57942012-05-21 13:10:19 -0700111{
112 return __mcfgpio_direction_input(offset);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700113}
114
Steven Kingec9f8482014-05-21 16:00:32 -0700115static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700116{
Linus Walleij4693c242015-12-22 15:39:05 +0100117 return !!__mcfgpio_get_value(offset);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700118}
119
Steven Kingec9f8482014-05-21 16:00:32 -0700120static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
121 int value)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700122{
Steven Kingeac57942012-05-21 13:10:19 -0700123 return __mcfgpio_direction_output(offset, value);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700124}
125
Steven Kingec9f8482014-05-21 16:00:32 -0700126static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
127 int value)
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700128{
Steven Kingeac57942012-05-21 13:10:19 -0700129 __mcfgpio_set_value(offset, value);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700130}
131
Steven Kingec9f8482014-05-21 16:00:32 -0700132static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
Steven Kingeac57942012-05-21 13:10:19 -0700133{
134 return __mcfgpio_request(offset);
135}
136
Steven Kingec9f8482014-05-21 16:00:32 -0700137static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
Steven Kingeac57942012-05-21 13:10:19 -0700138{
139 __mcfgpio_free(offset);
140}
141
Steven Kingec9f8482014-05-21 16:00:32 -0700142static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
Steven King60fc65f2014-05-21 16:00:30 -0700143{
144#if defined(MCFGPIO_IRQ_MIN)
145 if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
146#else
147 if (offset < MCFGPIO_IRQ_MAX)
148#endif
149 return MCFGPIO_IRQ_VECBASE + offset;
150 else
151 return -EINVAL;
152}
153
Steven Kingeac57942012-05-21 13:10:19 -0700154static struct gpio_chip mcfgpio_chip = {
155 .label = "mcfgpio",
156 .request = mcfgpio_request,
157 .free = mcfgpio_free,
158 .direction_input = mcfgpio_direction_input,
159 .direction_output = mcfgpio_direction_output,
160 .get = mcfgpio_get_value,
161 .set = mcfgpio_set_value,
Steven King60fc65f2014-05-21 16:00:30 -0700162 .to_irq = mcfgpio_to_irq,
Steven Kingeac57942012-05-21 13:10:19 -0700163 .base = 0,
164 .ngpio = MCFGPIO_PIN_MAX,
165};
Greg Ungererf23c1442012-04-17 13:25:38 +1000166
Steven Kingeac57942012-05-21 13:10:19 -0700167static int __init mcfgpio_sysinit(void)
168{
Greg Ungerer2763ee62016-04-07 05:26:26 +1000169 return gpiochip_add_data(&mcfgpio_chip, NULL);
sfking@fdwdc.comaf39bb82009-06-19 18:11:00 -0700170}
171
Steven Kingeac57942012-05-21 13:10:19 -0700172core_initcall(mcfgpio_sysinit);
173#endif