2 * Helpers for controlling modem lines via GPIO
4 * Copyright (C) 2014 Paratronic S.A.
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.
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.
17 #include <linux/err.h>
18 #include <linux/device.h>
19 #include <linux/irq.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/termios.h>
22 #include <linux/serial_core.h>
23 #include <linux/module.h>
25 #include "serial_mctrl_gpio.h"
28 struct uart_port
*port
;
29 struct gpio_desc
*gpio
[UART_GPIO_MAX
];
30 int irq
[UART_GPIO_MAX
];
31 unsigned int mctrl_prev
;
39 } mctrl_gpios_desc
[UART_GPIO_MAX
] = {
40 { "cts", TIOCM_CTS
, false, },
41 { "dsr", TIOCM_DSR
, false, },
42 { "dcd", TIOCM_CD
, false, },
43 { "rng", TIOCM_RNG
, false, },
44 { "rts", TIOCM_RTS
, true, },
45 { "dtr", TIOCM_DTR
, true, },
48 void mctrl_gpio_set(struct mctrl_gpios
*gpios
, unsigned int mctrl
)
50 enum mctrl_gpio_idx i
;
51 struct gpio_desc
*desc_array
[UART_GPIO_MAX
];
52 int value_array
[UART_GPIO_MAX
];
53 unsigned int count
= 0;
58 for (i
= 0; i
< UART_GPIO_MAX
; i
++)
59 if (gpios
->gpio
[i
] && mctrl_gpios_desc
[i
].dir_out
) {
60 desc_array
[count
] = gpios
->gpio
[i
];
61 value_array
[count
] = !!(mctrl
& mctrl_gpios_desc
[i
].mctrl
);
64 gpiod_set_array_value(count
, desc_array
, value_array
);
66 EXPORT_SYMBOL_GPL(mctrl_gpio_set
);
68 struct gpio_desc
*mctrl_gpio_to_gpiod(struct mctrl_gpios
*gpios
,
69 enum mctrl_gpio_idx gidx
)
71 return gpios
->gpio
[gidx
];
73 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod
);
75 unsigned int mctrl_gpio_get(struct mctrl_gpios
*gpios
, unsigned int *mctrl
)
77 enum mctrl_gpio_idx i
;
82 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
83 if (gpios
->gpio
[i
] && !mctrl_gpios_desc
[i
].dir_out
) {
84 if (gpiod_get_value(gpios
->gpio
[i
]))
85 *mctrl
|= mctrl_gpios_desc
[i
].mctrl
;
87 *mctrl
&= ~mctrl_gpios_desc
[i
].mctrl
;
93 EXPORT_SYMBOL_GPL(mctrl_gpio_get
);
96 mctrl_gpio_get_outputs(struct mctrl_gpios
*gpios
, unsigned int *mctrl
)
98 enum mctrl_gpio_idx i
;
103 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
104 if (gpios
->gpio
[i
] && mctrl_gpios_desc
[i
].dir_out
) {
105 if (gpiod_get_value(gpios
->gpio
[i
]))
106 *mctrl
|= mctrl_gpios_desc
[i
].mctrl
;
108 *mctrl
&= ~mctrl_gpios_desc
[i
].mctrl
;
114 EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs
);
116 struct mctrl_gpios
*mctrl_gpio_init_noauto(struct device
*dev
, unsigned int idx
)
118 struct mctrl_gpios
*gpios
;
119 enum mctrl_gpio_idx i
;
121 gpios
= devm_kzalloc(dev
, sizeof(*gpios
), GFP_KERNEL
);
123 return ERR_PTR(-ENOMEM
);
125 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
126 enum gpiod_flags flags
;
128 if (mctrl_gpios_desc
[i
].dir_out
)
129 flags
= GPIOD_OUT_LOW
;
134 devm_gpiod_get_index_optional(dev
,
135 mctrl_gpios_desc
[i
].name
,
138 if (IS_ERR(gpios
->gpio
[i
]))
139 return ERR_CAST(gpios
->gpio
[i
]);
144 EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto
);
146 #define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
147 static irqreturn_t
mctrl_gpio_irq_handle(int irq
, void *context
)
149 struct mctrl_gpios
*gpios
= context
;
150 struct uart_port
*port
= gpios
->port
;
151 u32 mctrl
= gpios
->mctrl_prev
;
155 mctrl_gpio_get(gpios
, &mctrl
);
157 spin_lock_irqsave(&port
->lock
, flags
);
159 mctrl_diff
= mctrl
^ gpios
->mctrl_prev
;
160 gpios
->mctrl_prev
= mctrl
;
162 if (mctrl_diff
& MCTRL_ANY_DELTA
&& port
->state
!= NULL
) {
163 if ((mctrl_diff
& mctrl
) & TIOCM_RI
)
166 if ((mctrl_diff
& mctrl
) & TIOCM_DSR
)
169 if (mctrl_diff
& TIOCM_CD
)
170 uart_handle_dcd_change(port
, mctrl
& TIOCM_CD
);
172 if (mctrl_diff
& TIOCM_CTS
)
173 uart_handle_cts_change(port
, mctrl
& TIOCM_CTS
);
175 wake_up_interruptible(&port
->state
->port
.delta_msr_wait
);
178 spin_unlock_irqrestore(&port
->lock
, flags
);
183 struct mctrl_gpios
*mctrl_gpio_init(struct uart_port
*port
, unsigned int idx
)
185 struct mctrl_gpios
*gpios
;
186 enum mctrl_gpio_idx i
;
188 gpios
= mctrl_gpio_init_noauto(port
->dev
, idx
);
194 for (i
= 0; i
< UART_GPIO_MAX
; ++i
) {
197 if (!gpios
->gpio
[i
] || mctrl_gpios_desc
[i
].dir_out
)
200 ret
= gpiod_to_irq(gpios
->gpio
[i
]);
203 "failed to find corresponding irq for %s (idx=%d, err=%d)\n",
204 mctrl_gpios_desc
[i
].name
, idx
, ret
);
209 /* irqs should only be enabled in .enable_ms */
210 irq_set_status_flags(gpios
->irq
[i
], IRQ_NOAUTOEN
);
212 ret
= devm_request_irq(port
->dev
, gpios
->irq
[i
],
213 mctrl_gpio_irq_handle
,
214 IRQ_TYPE_EDGE_BOTH
, dev_name(port
->dev
),
217 /* alternatively implement polling */
219 "failed to request irq for %s (idx=%d, err=%d)\n",
220 mctrl_gpios_desc
[i
].name
, idx
, ret
);
227 EXPORT_SYMBOL_GPL(mctrl_gpio_init
);
229 void mctrl_gpio_free(struct device
*dev
, struct mctrl_gpios
*gpios
)
231 enum mctrl_gpio_idx i
;
236 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
238 devm_free_irq(gpios
->port
->dev
, gpios
->irq
[i
], gpios
);
241 devm_gpiod_put(dev
, gpios
->gpio
[i
]);
243 devm_kfree(dev
, gpios
);
245 EXPORT_SYMBOL_GPL(mctrl_gpio_free
);
247 void mctrl_gpio_enable_ms(struct mctrl_gpios
*gpios
)
249 enum mctrl_gpio_idx i
;
254 /* .enable_ms may be called multiple times */
258 gpios
->mctrl_on
= true;
260 /* get initial status of modem lines GPIOs */
261 mctrl_gpio_get(gpios
, &gpios
->mctrl_prev
);
263 for (i
= 0; i
< UART_GPIO_MAX
; ++i
) {
267 enable_irq(gpios
->irq
[i
]);
270 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms
);
272 void mctrl_gpio_disable_ms(struct mctrl_gpios
*gpios
)
274 enum mctrl_gpio_idx i
;
279 if (!gpios
->mctrl_on
)
282 gpios
->mctrl_on
= false;
284 for (i
= 0; i
< UART_GPIO_MAX
; ++i
) {
288 disable_irq(gpios
->irq
[i
]);
291 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms
);
293 MODULE_LICENSE("GPL");