Merge remote-tracking branch 'drm/drm-next' into drm-misc-next
[sfrench/cifs-2.6.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
13 #include <linux/io.h>
14 #include <asm/coldfire.h>
15 #include <asm/mcfsim.h>
16 #include <asm/mcfgpio.h>
17
18 int __mcfgpio_get_value(unsigned gpio)
19 {
20         return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
21 }
22 EXPORT_SYMBOL(__mcfgpio_get_value);
23
24 void __mcfgpio_set_value(unsigned gpio, int value)
25 {
26         if (gpio < MCFGPIO_SCR_START) {
27                 unsigned long flags;
28                 MCFGPIO_PORTTYPE data;
29
30                 local_irq_save(flags);
31                 data = mcfgpio_read(__mcfgpio_podr(gpio));
32                 if (value)
33                         data |= mcfgpio_bit(gpio);
34                 else
35                         data &= ~mcfgpio_bit(gpio);
36                 mcfgpio_write(data, __mcfgpio_podr(gpio));
37                 local_irq_restore(flags);
38         } else {
39                 if (value)
40                         mcfgpio_write(mcfgpio_bit(gpio),
41                                         MCFGPIO_SETR_PORT(gpio));
42                 else
43                         mcfgpio_write(~mcfgpio_bit(gpio),
44                                         MCFGPIO_CLRR_PORT(gpio));
45         }
46 }
47 EXPORT_SYMBOL(__mcfgpio_set_value);
48
49 int __mcfgpio_direction_input(unsigned gpio)
50 {
51         unsigned long flags;
52         MCFGPIO_PORTTYPE dir;
53
54         local_irq_save(flags);
55         dir = mcfgpio_read(__mcfgpio_pddr(gpio));
56         dir &= ~mcfgpio_bit(gpio);
57         mcfgpio_write(dir, __mcfgpio_pddr(gpio));
58         local_irq_restore(flags);
59
60         return 0;
61 }
62 EXPORT_SYMBOL(__mcfgpio_direction_input);
63
64 int __mcfgpio_direction_output(unsigned gpio, int value)
65 {
66         unsigned long flags;
67         MCFGPIO_PORTTYPE data;
68
69         local_irq_save(flags);
70         data = mcfgpio_read(__mcfgpio_pddr(gpio));
71         data |= mcfgpio_bit(gpio);
72         mcfgpio_write(data, __mcfgpio_pddr(gpio));
73
74         /* now set the data to output */
75         if (gpio < MCFGPIO_SCR_START) {
76                 data = mcfgpio_read(__mcfgpio_podr(gpio));
77                 if (value)
78                         data |= mcfgpio_bit(gpio);
79                 else
80                         data &= ~mcfgpio_bit(gpio);
81                 mcfgpio_write(data, __mcfgpio_podr(gpio));
82         } else {
83                  if (value)
84                         mcfgpio_write(mcfgpio_bit(gpio),
85                                         MCFGPIO_SETR_PORT(gpio));
86                  else
87                          mcfgpio_write(~mcfgpio_bit(gpio),
88                                          MCFGPIO_CLRR_PORT(gpio));
89         }
90         local_irq_restore(flags);
91         return 0;
92 }
93 EXPORT_SYMBOL(__mcfgpio_direction_output);
94
95 int __mcfgpio_request(unsigned gpio)
96 {
97         return 0;
98 }
99 EXPORT_SYMBOL(__mcfgpio_request);
100
101 void __mcfgpio_free(unsigned gpio)
102 {
103         __mcfgpio_direction_input(gpio);
104 }
105 EXPORT_SYMBOL(__mcfgpio_free);
106
107 #ifdef CONFIG_GPIOLIB
108
109 static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
110 {
111         return __mcfgpio_direction_input(offset);
112 }
113
114 static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
115 {
116         return !!__mcfgpio_get_value(offset);
117 }
118
119 static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
120                                     int value)
121 {
122         return __mcfgpio_direction_output(offset, value);
123 }
124
125 static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
126                               int value)
127 {
128         __mcfgpio_set_value(offset, value);
129 }
130
131 static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
132 {
133         return __mcfgpio_request(offset);
134 }
135
136 static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
137 {
138         __mcfgpio_free(offset);
139 }
140
141 static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
142 {
143 #if defined(MCFGPIO_IRQ_MIN)
144         if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
145 #else
146         if (offset < MCFGPIO_IRQ_MAX)
147 #endif
148                 return MCFGPIO_IRQ_VECBASE + offset;
149         else
150                 return -EINVAL;
151 }
152
153 static struct gpio_chip mcfgpio_chip = {
154         .label                  = "mcfgpio",
155         .request                = mcfgpio_request,
156         .free                   = mcfgpio_free,
157         .direction_input        = mcfgpio_direction_input,
158         .direction_output       = mcfgpio_direction_output,
159         .get                    = mcfgpio_get_value,
160         .set                    = mcfgpio_set_value,
161         .to_irq                 = mcfgpio_to_irq,
162         .base                   = 0,
163         .ngpio                  = MCFGPIO_PIN_MAX,
164 };
165
166 static int __init mcfgpio_sysinit(void)
167 {
168         return gpiochip_add_data(&mcfgpio_chip, NULL);
169 }
170
171 core_initcall(mcfgpio_sysinit);
172 #endif