Linux 6.7-rc7
[linux-modified.git] / arch / m68k / coldfire / gpio.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Coldfire generic GPIO support.
4  *
5  * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/device.h>
12 #include <linux/gpio/driver.h>
13
14 #include <linux/io.h>
15 #include <asm/coldfire.h>
16 #include <asm/mcfsim.h>
17 #include <asm/mcfgpio.h>
18
19 int __mcfgpio_get_value(unsigned gpio)
20 {
21         return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
22 }
23 EXPORT_SYMBOL(__mcfgpio_get_value);
24
25 void __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 }
48 EXPORT_SYMBOL(__mcfgpio_set_value);
49
50 int __mcfgpio_direction_input(unsigned gpio)
51 {
52         unsigned long flags;
53         MCFGPIO_PORTTYPE dir;
54
55         local_irq_save(flags);
56         dir = mcfgpio_read(__mcfgpio_pddr(gpio));
57         dir &= ~mcfgpio_bit(gpio);
58         mcfgpio_write(dir, __mcfgpio_pddr(gpio));
59         local_irq_restore(flags);
60
61         return 0;
62 }
63 EXPORT_SYMBOL(__mcfgpio_direction_input);
64
65 int __mcfgpio_direction_output(unsigned gpio, int value)
66 {
67         unsigned long flags;
68         MCFGPIO_PORTTYPE data;
69
70         local_irq_save(flags);
71         data = mcfgpio_read(__mcfgpio_pddr(gpio));
72         data |= mcfgpio_bit(gpio);
73         mcfgpio_write(data, __mcfgpio_pddr(gpio));
74
75         /* 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         }
91         local_irq_restore(flags);
92         return 0;
93 }
94 EXPORT_SYMBOL(__mcfgpio_direction_output);
95
96 int __mcfgpio_request(unsigned gpio)
97 {
98         return 0;
99 }
100 EXPORT_SYMBOL(__mcfgpio_request);
101
102 void __mcfgpio_free(unsigned gpio)
103 {
104         __mcfgpio_direction_input(gpio);
105 }
106 EXPORT_SYMBOL(__mcfgpio_free);
107
108 #ifdef CONFIG_GPIOLIB
109
110 static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
111 {
112         return __mcfgpio_direction_input(offset);
113 }
114
115 static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
116 {
117         return !!__mcfgpio_get_value(offset);
118 }
119
120 static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
121                                     int value)
122 {
123         return __mcfgpio_direction_output(offset, value);
124 }
125
126 static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
127                               int value)
128 {
129         __mcfgpio_set_value(offset, value);
130 }
131
132 static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
133 {
134         return __mcfgpio_request(offset);
135 }
136
137 static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
138 {
139         __mcfgpio_free(offset);
140 }
141
142 static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
143 {
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
154 static 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,
162         .to_irq                 = mcfgpio_to_irq,
163         .base                   = 0,
164         .ngpio                  = MCFGPIO_PIN_MAX,
165 };
166
167 static int __init mcfgpio_sysinit(void)
168 {
169         return gpiochip_add_data(&mcfgpio_chip, NULL);
170 }
171
172 core_initcall(mcfgpio_sysinit);
173 #endif