Commit | Line | Data |
---|---|---|
84130aac RG |
1 | /* |
2 | * Helpers for controlling modem lines via GPIO | |
3 | * | |
4 | * Copyright (C) 2014 Paratronic S.A. | |
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; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | */ | |
17 | ||
18 | #include <linux/err.h> | |
19 | #include <linux/device.h> | |
20 | #include <linux/gpio/consumer.h> | |
93b88774 | 21 | #include <linux/termios.h> |
84130aac RG |
22 | |
23 | #include "serial_mctrl_gpio.h" | |
24 | ||
25 | struct mctrl_gpios { | |
26 | struct gpio_desc *gpio[UART_GPIO_MAX]; | |
27 | }; | |
28 | ||
29 | static const struct { | |
30 | const char *name; | |
31 | unsigned int mctrl; | |
32 | bool dir_out; | |
33 | } mctrl_gpios_desc[UART_GPIO_MAX] = { | |
34 | { "cts", TIOCM_CTS, false, }, | |
35 | { "dsr", TIOCM_DSR, false, }, | |
36 | { "dcd", TIOCM_CD, false, }, | |
37 | { "rng", TIOCM_RNG, false, }, | |
38 | { "rts", TIOCM_RTS, true, }, | |
39 | { "dtr", TIOCM_DTR, true, }, | |
40 | { "out1", TIOCM_OUT1, true, }, | |
41 | { "out2", TIOCM_OUT2, true, }, | |
42 | }; | |
43 | ||
44 | void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) | |
45 | { | |
46 | enum mctrl_gpio_idx i; | |
834296a3 RI |
47 | struct gpio_desc *desc_array[UART_GPIO_MAX]; |
48 | int value_array[UART_GPIO_MAX]; | |
49 | unsigned int count = 0; | |
84130aac | 50 | |
84130aac | 51 | for (i = 0; i < UART_GPIO_MAX; i++) |
445df7ff | 52 | if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) { |
834296a3 RI |
53 | desc_array[count] = gpios->gpio[i]; |
54 | value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl); | |
55 | count++; | |
56 | } | |
3fff99bc | 57 | gpiod_set_array_value(count, desc_array, value_array); |
84130aac RG |
58 | } |
59 | EXPORT_SYMBOL_GPL(mctrl_gpio_set); | |
60 | ||
61 | struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, | |
62 | enum mctrl_gpio_idx gidx) | |
63 | { | |
9e9f079c | 64 | return gpios->gpio[gidx]; |
84130aac RG |
65 | } |
66 | EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod); | |
67 | ||
68 | unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl) | |
69 | { | |
70 | enum mctrl_gpio_idx i; | |
71 | ||
84130aac | 72 | for (i = 0; i < UART_GPIO_MAX; i++) { |
9e9f079c | 73 | if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) { |
84130aac RG |
74 | if (gpiod_get_value(gpios->gpio[i])) |
75 | *mctrl |= mctrl_gpios_desc[i].mctrl; | |
76 | else | |
77 | *mctrl &= ~mctrl_gpios_desc[i].mctrl; | |
78 | } | |
79 | } | |
80 | ||
81 | return *mctrl; | |
82 | } | |
83 | EXPORT_SYMBOL_GPL(mctrl_gpio_get); | |
84 | ||
7d8c70d8 | 85 | struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx) |
84130aac RG |
86 | { |
87 | struct mctrl_gpios *gpios; | |
88 | enum mctrl_gpio_idx i; | |
84130aac RG |
89 | |
90 | gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); | |
91 | if (!gpios) | |
92 | return ERR_PTR(-ENOMEM); | |
93 | ||
94 | for (i = 0; i < UART_GPIO_MAX; i++) { | |
1d267ea6 | 95 | enum gpiod_flags flags; |
84130aac RG |
96 | |
97 | if (mctrl_gpios_desc[i].dir_out) | |
1d267ea6 | 98 | flags = GPIOD_OUT_LOW; |
84130aac | 99 | else |
1d267ea6 UKK |
100 | flags = GPIOD_IN; |
101 | ||
102 | gpios->gpio[i] = | |
103 | devm_gpiod_get_index_optional(dev, | |
104 | mctrl_gpios_desc[i].name, | |
105 | idx, flags); | |
106 | ||
107 | if (IS_ERR(gpios->gpio[i])) | |
13bc2bb9 | 108 | return ERR_CAST(gpios->gpio[i]); |
84130aac RG |
109 | } |
110 | ||
111 | return gpios; | |
112 | } | |
7d8c70d8 | 113 | EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto); |
84130aac RG |
114 | |
115 | void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) | |
116 | { | |
117 | enum mctrl_gpio_idx i; | |
118 | ||
84130aac | 119 | for (i = 0; i < UART_GPIO_MAX; i++) |
445df7ff | 120 | if (gpios->gpio[i]) |
84130aac RG |
121 | devm_gpiod_put(dev, gpios->gpio[i]); |
122 | devm_kfree(dev, gpios); | |
123 | } | |
124 | EXPORT_SYMBOL_GPL(mctrl_gpio_free); |