GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / tty / serial / serial_mctrl_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Helpers for controlling modem lines via GPIO
4  *
5  * Copyright (C) 2014 Paratronic S.A.
6  */
7
8 #include <linux/err.h>
9 #include <linux/device.h>
10 #include <linux/irq.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/termios.h>
13 #include <linux/serial_core.h>
14 #include <linux/module.h>
15 #include <linux/property.h>
16
17 #include "serial_mctrl_gpio.h"
18
19 struct mctrl_gpios {
20         struct uart_port *port;
21         struct gpio_desc *gpio[UART_GPIO_MAX];
22         int irq[UART_GPIO_MAX];
23         unsigned int mctrl_prev;
24         bool mctrl_on;
25 };
26
27 static const struct {
28         const char *name;
29         unsigned int mctrl;
30         enum gpiod_flags flags;
31 } mctrl_gpios_desc[UART_GPIO_MAX] = {
32         { "cts", TIOCM_CTS, GPIOD_IN, },
33         { "dsr", TIOCM_DSR, GPIOD_IN, },
34         { "dcd", TIOCM_CD,  GPIOD_IN, },
35         { "rng", TIOCM_RNG, GPIOD_IN, },
36         { "rts", TIOCM_RTS, GPIOD_OUT_LOW, },
37         { "dtr", TIOCM_DTR, GPIOD_OUT_LOW, },
38 };
39
40 static bool mctrl_gpio_flags_is_dir_out(unsigned int idx)
41 {
42         return mctrl_gpios_desc[idx].flags & GPIOD_FLAGS_BIT_DIR_OUT;
43 }
44
45 /**
46  * mctrl_gpio_set - set gpios according to mctrl state
47  * @gpios: gpios to set
48  * @mctrl: state to set
49  *
50  * Set the gpios according to the mctrl state.
51  */
52 void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
53 {
54         enum mctrl_gpio_idx i;
55         struct gpio_desc *desc_array[UART_GPIO_MAX];
56         DECLARE_BITMAP(values, UART_GPIO_MAX);
57         unsigned int count = 0;
58
59         if (gpios == NULL)
60                 return;
61
62         for (i = 0; i < UART_GPIO_MAX; i++)
63                 if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
64                         desc_array[count] = gpios->gpio[i];
65                         __assign_bit(count, values,
66                                      mctrl & mctrl_gpios_desc[i].mctrl);
67                         count++;
68                 }
69         gpiod_set_array_value(count, desc_array, NULL, values);
70 }
71 EXPORT_SYMBOL_GPL(mctrl_gpio_set);
72
73 /**
74  * mctrl_gpio_to_gpiod - obtain gpio_desc of modem line index
75  * @gpios: gpios to look into
76  * @gidx: index of the modem line
77  * Returns: the gpio_desc structure associated to the modem line index
78  */
79 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
80                                       enum mctrl_gpio_idx gidx)
81 {
82         if (gpios == NULL)
83                 return NULL;
84
85         return gpios->gpio[gidx];
86 }
87 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
88
89 /**
90  * mctrl_gpio_get - update mctrl with the gpios values.
91  * @gpios: gpios to get the info from
92  * @mctrl: mctrl to set
93  * Returns: modified mctrl (the same value as in @mctrl)
94  *
95  * Update mctrl with the gpios values.
96  */
97 unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
98 {
99         enum mctrl_gpio_idx i;
100
101         if (gpios == NULL)
102                 return *mctrl;
103
104         for (i = 0; i < UART_GPIO_MAX; i++) {
105                 if (gpios->gpio[i] && !mctrl_gpio_flags_is_dir_out(i)) {
106                         if (gpiod_get_value(gpios->gpio[i]))
107                                 *mctrl |= mctrl_gpios_desc[i].mctrl;
108                         else
109                                 *mctrl &= ~mctrl_gpios_desc[i].mctrl;
110                 }
111         }
112
113         return *mctrl;
114 }
115 EXPORT_SYMBOL_GPL(mctrl_gpio_get);
116
117 unsigned int
118 mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
119 {
120         enum mctrl_gpio_idx i;
121
122         if (gpios == NULL)
123                 return *mctrl;
124
125         for (i = 0; i < UART_GPIO_MAX; i++) {
126                 if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
127                         if (gpiod_get_value(gpios->gpio[i]))
128                                 *mctrl |= mctrl_gpios_desc[i].mctrl;
129                         else
130                                 *mctrl &= ~mctrl_gpios_desc[i].mctrl;
131                 }
132         }
133
134         return *mctrl;
135 }
136 EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs);
137
138 struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
139 {
140         struct mctrl_gpios *gpios;
141         enum mctrl_gpio_idx i;
142
143         gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL);
144         if (!gpios)
145                 return ERR_PTR(-ENOMEM);
146
147         for (i = 0; i < UART_GPIO_MAX; i++) {
148                 char *gpio_str;
149                 bool present;
150
151                 /* Check if GPIO property exists and continue if not */
152                 gpio_str = kasprintf(GFP_KERNEL, "%s-gpios",
153                                      mctrl_gpios_desc[i].name);
154                 if (!gpio_str)
155                         continue;
156
157                 present = device_property_present(dev, gpio_str);
158                 kfree(gpio_str);
159                 if (!present)
160                         continue;
161
162                 gpios->gpio[i] =
163                         devm_gpiod_get_index_optional(dev,
164                                                       mctrl_gpios_desc[i].name,
165                                                       idx,
166                                                       mctrl_gpios_desc[i].flags);
167
168                 if (IS_ERR(gpios->gpio[i]))
169                         return ERR_CAST(gpios->gpio[i]);
170         }
171
172         return gpios;
173 }
174 EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto);
175
176 #define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
177 static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context)
178 {
179         struct mctrl_gpios *gpios = context;
180         struct uart_port *port = gpios->port;
181         u32 mctrl = gpios->mctrl_prev;
182         u32 mctrl_diff;
183         unsigned long flags;
184
185         mctrl_gpio_get(gpios, &mctrl);
186
187         uart_port_lock_irqsave(port, &flags);
188
189         mctrl_diff = mctrl ^ gpios->mctrl_prev;
190         gpios->mctrl_prev = mctrl;
191
192         if (mctrl_diff & MCTRL_ANY_DELTA && port->state != NULL) {
193                 if ((mctrl_diff & mctrl) & TIOCM_RI)
194                         port->icount.rng++;
195
196                 if ((mctrl_diff & mctrl) & TIOCM_DSR)
197                         port->icount.dsr++;
198
199                 if (mctrl_diff & TIOCM_CD)
200                         uart_handle_dcd_change(port, mctrl & TIOCM_CD);
201
202                 if (mctrl_diff & TIOCM_CTS)
203                         uart_handle_cts_change(port, mctrl & TIOCM_CTS);
204
205                 wake_up_interruptible(&port->state->port.delta_msr_wait);
206         }
207
208         uart_port_unlock_irqrestore(port, flags);
209
210         return IRQ_HANDLED;
211 }
212
213 /**
214  * mctrl_gpio_init - initialize uart gpios
215  * @port: port to initialize gpios for
216  * @idx: index of the gpio in the @port's device
217  *
218  * This will get the {cts,rts,...}-gpios from device tree if they are present
219  * and request them, set direction etc, and return an allocated structure.
220  * `devm_*` functions are used, so there's no need to call mctrl_gpio_free().
221  * As this sets up the irq handling, make sure to not handle changes to the
222  * gpio input lines in your driver, too.
223  */
224 struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
225 {
226         struct mctrl_gpios *gpios;
227         enum mctrl_gpio_idx i;
228
229         gpios = mctrl_gpio_init_noauto(port->dev, idx);
230         if (IS_ERR(gpios))
231                 return gpios;
232
233         gpios->port = port;
234
235         for (i = 0; i < UART_GPIO_MAX; ++i) {
236                 int ret;
237
238                 if (!gpios->gpio[i] || mctrl_gpio_flags_is_dir_out(i))
239                         continue;
240
241                 ret = gpiod_to_irq(gpios->gpio[i]);
242                 if (ret < 0) {
243                         dev_err(port->dev,
244                                 "failed to find corresponding irq for %s (idx=%d, err=%d)\n",
245                                 mctrl_gpios_desc[i].name, idx, ret);
246                         return ERR_PTR(ret);
247                 }
248                 gpios->irq[i] = ret;
249
250                 /* irqs should only be enabled in .enable_ms */
251                 irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN);
252
253                 ret = devm_request_irq(port->dev, gpios->irq[i],
254                                        mctrl_gpio_irq_handle,
255                                        IRQ_TYPE_EDGE_BOTH, dev_name(port->dev),
256                                        gpios);
257                 if (ret) {
258                         /* alternatively implement polling */
259                         dev_err(port->dev,
260                                 "failed to request irq for %s (idx=%d, err=%d)\n",
261                                 mctrl_gpios_desc[i].name, idx, ret);
262                         return ERR_PTR(ret);
263                 }
264         }
265
266         return gpios;
267 }
268 EXPORT_SYMBOL_GPL(mctrl_gpio_init);
269
270 /**
271  * mctrl_gpio_free - explicitly free uart gpios
272  * @dev: uart port's device
273  * @gpios: gpios structure to be freed
274  *
275  * This will free the requested gpios in mctrl_gpio_init(). As `devm_*`
276  * functions are used, there's generally no need to call this function.
277  */
278 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
279 {
280         enum mctrl_gpio_idx i;
281
282         if (gpios == NULL)
283                 return;
284
285         for (i = 0; i < UART_GPIO_MAX; i++) {
286                 if (gpios->irq[i])
287                         devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
288
289                 if (gpios->gpio[i])
290                         devm_gpiod_put(dev, gpios->gpio[i]);
291         }
292         devm_kfree(dev, gpios);
293 }
294 EXPORT_SYMBOL_GPL(mctrl_gpio_free);
295
296 /**
297  * mctrl_gpio_enable_ms - enable irqs and handling of changes to the ms lines
298  * @gpios: gpios to enable
299  */
300 void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
301 {
302         enum mctrl_gpio_idx i;
303
304         if (gpios == NULL)
305                 return;
306
307         /* .enable_ms may be called multiple times */
308         if (gpios->mctrl_on)
309                 return;
310
311         gpios->mctrl_on = true;
312
313         /* get initial status of modem lines GPIOs */
314         mctrl_gpio_get(gpios, &gpios->mctrl_prev);
315
316         for (i = 0; i < UART_GPIO_MAX; ++i) {
317                 if (!gpios->irq[i])
318                         continue;
319
320                 enable_irq(gpios->irq[i]);
321         }
322 }
323 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms);
324
325 /**
326  * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines
327  * @gpios: gpios to disable
328  */
329 void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
330 {
331         enum mctrl_gpio_idx i;
332
333         if (gpios == NULL)
334                 return;
335
336         if (!gpios->mctrl_on)
337                 return;
338
339         gpios->mctrl_on = false;
340
341         for (i = 0; i < UART_GPIO_MAX; ++i) {
342                 if (!gpios->irq[i])
343                         continue;
344
345                 disable_irq(gpios->irq[i]);
346         }
347 }
348 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);
349
350 void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios)
351 {
352         enum mctrl_gpio_idx i;
353
354         if (!gpios)
355                 return;
356
357         if (!gpios->mctrl_on)
358                 return;
359
360         for (i = 0; i < UART_GPIO_MAX; ++i) {
361                 if (!gpios->irq[i])
362                         continue;
363
364                 enable_irq_wake(gpios->irq[i]);
365         }
366 }
367 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_irq_wake);
368
369 void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios)
370 {
371         enum mctrl_gpio_idx i;
372
373         if (!gpios)
374                 return;
375
376         if (!gpios->mctrl_on)
377                 return;
378
379         for (i = 0; i < UART_GPIO_MAX; ++i) {
380                 if (!gpios->irq[i])
381                         continue;
382
383                 disable_irq_wake(gpios->irq[i]);
384         }
385 }
386 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_irq_wake);
387
388 MODULE_LICENSE("GPL");