]>
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 RG |
51 | for (i = 0; i < UART_GPIO_MAX; i++) |
52 | if (!IS_ERR_OR_NULL(gpios->gpio[i]) && | |
834296a3 RI |
53 | mctrl_gpios_desc[i].dir_out) { |
54 | desc_array[count] = gpios->gpio[i]; | |
55 | value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl); | |
56 | count++; | |
57 | } | |
3fff99bc | 58 | gpiod_set_array_value(count, desc_array, value_array); |
84130aac RG |
59 | } |
60 | EXPORT_SYMBOL_GPL(mctrl_gpio_set); | |
61 | ||
62 | struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, | |
63 | enum mctrl_gpio_idx gidx) | |
64 | { | |
9e9f079c | 65 | return gpios->gpio[gidx]; |
84130aac RG |
66 | } |
67 | EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod); | |
68 | ||
69 | unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl) | |
70 | { | |
71 | enum mctrl_gpio_idx i; | |
72 | ||
84130aac | 73 | for (i = 0; i < UART_GPIO_MAX; i++) { |
9e9f079c | 74 | if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) { |
84130aac RG |
75 | if (gpiod_get_value(gpios->gpio[i])) |
76 | *mctrl |= mctrl_gpios_desc[i].mctrl; | |
77 | else | |
78 | *mctrl &= ~mctrl_gpios_desc[i].mctrl; | |
79 | } | |
80 | } | |
81 | ||
82 | return *mctrl; | |
83 | } | |
84 | EXPORT_SYMBOL_GPL(mctrl_gpio_get); | |
85 | ||
86 | struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx) | |
87 | { | |
88 | struct mctrl_gpios *gpios; | |
89 | enum mctrl_gpio_idx i; | |
84130aac RG |
90 | |
91 | gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); | |
92 | if (!gpios) | |
93 | return ERR_PTR(-ENOMEM); | |
94 | ||
95 | for (i = 0; i < UART_GPIO_MAX; i++) { | |
1d267ea6 | 96 | enum gpiod_flags flags; |
84130aac RG |
97 | |
98 | if (mctrl_gpios_desc[i].dir_out) | |
1d267ea6 | 99 | flags = GPIOD_OUT_LOW; |
84130aac | 100 | else |
1d267ea6 UKK |
101 | flags = GPIOD_IN; |
102 | ||
103 | gpios->gpio[i] = | |
104 | devm_gpiod_get_index_optional(dev, | |
105 | mctrl_gpios_desc[i].name, | |
106 | idx, flags); | |
107 | ||
108 | if (IS_ERR(gpios->gpio[i])) | |
13bc2bb9 | 109 | return ERR_CAST(gpios->gpio[i]); |
84130aac RG |
110 | } |
111 | ||
112 | return gpios; | |
113 | } | |
114 | EXPORT_SYMBOL_GPL(mctrl_gpio_init); | |
115 | ||
116 | void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) | |
117 | { | |
118 | enum mctrl_gpio_idx i; | |
119 | ||
84130aac RG |
120 | for (i = 0; i < UART_GPIO_MAX; i++) |
121 | if (!IS_ERR_OR_NULL(gpios->gpio[i])) | |
122 | devm_gpiod_put(dev, gpios->gpio[i]); | |
123 | devm_kfree(dev, gpios); | |
124 | } | |
125 | EXPORT_SYMBOL_GPL(mctrl_gpio_free); |