1 // SPDX-License-Identifier: GPL-2.0+
3 * Helpers for controlling modem lines via GPIO
5 * Copyright (C) 2014 Paratronic S.A.
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>
17 #include "serial_mctrl_gpio.h"
20 struct uart_port
*port
;
21 struct gpio_desc
*gpio
[UART_GPIO_MAX
];
22 int irq
[UART_GPIO_MAX
];
23 unsigned int mctrl_prev
;
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
, },
40 static bool mctrl_gpio_flags_is_dir_out(unsigned int idx
)
42 return mctrl_gpios_desc
[idx
].flags
& GPIOD_FLAGS_BIT_DIR_OUT
;
45 void mctrl_gpio_set(struct mctrl_gpios
*gpios
, unsigned int mctrl
)
47 enum mctrl_gpio_idx i
;
48 struct gpio_desc
*desc_array
[UART_GPIO_MAX
];
49 DECLARE_BITMAP(values
, UART_GPIO_MAX
);
50 unsigned int count
= 0;
55 for (i
= 0; i
< UART_GPIO_MAX
; i
++)
56 if (gpios
->gpio
[i
] && mctrl_gpio_flags_is_dir_out(i
)) {
57 desc_array
[count
] = gpios
->gpio
[i
];
58 __assign_bit(count
, values
,
59 mctrl
& mctrl_gpios_desc
[i
].mctrl
);
62 gpiod_set_array_value(count
, desc_array
, NULL
, values
);
64 EXPORT_SYMBOL_GPL(mctrl_gpio_set
);
66 struct gpio_desc
*mctrl_gpio_to_gpiod(struct mctrl_gpios
*gpios
,
67 enum mctrl_gpio_idx gidx
)
72 return gpios
->gpio
[gidx
];
74 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod
);
76 unsigned int mctrl_gpio_get(struct mctrl_gpios
*gpios
, unsigned int *mctrl
)
78 enum mctrl_gpio_idx i
;
83 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
84 if (gpios
->gpio
[i
] && !mctrl_gpio_flags_is_dir_out(i
)) {
85 if (gpiod_get_value(gpios
->gpio
[i
]))
86 *mctrl
|= mctrl_gpios_desc
[i
].mctrl
;
88 *mctrl
&= ~mctrl_gpios_desc
[i
].mctrl
;
94 EXPORT_SYMBOL_GPL(mctrl_gpio_get
);
97 mctrl_gpio_get_outputs(struct mctrl_gpios
*gpios
, unsigned int *mctrl
)
99 enum mctrl_gpio_idx i
;
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
;
109 *mctrl
&= ~mctrl_gpios_desc
[i
].mctrl
;
115 EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs
);
117 struct mctrl_gpios
*mctrl_gpio_init_noauto(struct device
*dev
, unsigned int idx
)
119 struct mctrl_gpios
*gpios
;
120 enum mctrl_gpio_idx i
;
122 gpios
= devm_kzalloc(dev
, sizeof(*gpios
), GFP_KERNEL
);
124 return ERR_PTR(-ENOMEM
);
126 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
130 /* Check if GPIO property exists and continue if not */
131 gpio_str
= kasprintf(GFP_KERNEL
, "%s-gpios",
132 mctrl_gpios_desc
[i
].name
);
136 present
= device_property_present(dev
, gpio_str
);
142 devm_gpiod_get_index_optional(dev
,
143 mctrl_gpios_desc
[i
].name
,
145 mctrl_gpios_desc
[i
].flags
);
147 if (IS_ERR(gpios
->gpio
[i
]))
148 return ERR_CAST(gpios
->gpio
[i
]);
153 EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto
);
155 #define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
156 static irqreturn_t
mctrl_gpio_irq_handle(int irq
, void *context
)
158 struct mctrl_gpios
*gpios
= context
;
159 struct uart_port
*port
= gpios
->port
;
160 u32 mctrl
= gpios
->mctrl_prev
;
164 mctrl_gpio_get(gpios
, &mctrl
);
166 spin_lock_irqsave(&port
->lock
, flags
);
168 mctrl_diff
= mctrl
^ gpios
->mctrl_prev
;
169 gpios
->mctrl_prev
= mctrl
;
171 if (mctrl_diff
& MCTRL_ANY_DELTA
&& port
->state
!= NULL
) {
172 if ((mctrl_diff
& mctrl
) & TIOCM_RI
)
175 if ((mctrl_diff
& mctrl
) & TIOCM_DSR
)
178 if (mctrl_diff
& TIOCM_CD
)
179 uart_handle_dcd_change(port
, mctrl
& TIOCM_CD
);
181 if (mctrl_diff
& TIOCM_CTS
)
182 uart_handle_cts_change(port
, mctrl
& TIOCM_CTS
);
184 wake_up_interruptible(&port
->state
->port
.delta_msr_wait
);
187 spin_unlock_irqrestore(&port
->lock
, flags
);
192 struct mctrl_gpios
*mctrl_gpio_init(struct uart_port
*port
, unsigned int idx
)
194 struct mctrl_gpios
*gpios
;
195 enum mctrl_gpio_idx i
;
197 gpios
= mctrl_gpio_init_noauto(port
->dev
, idx
);
203 for (i
= 0; i
< UART_GPIO_MAX
; ++i
) {
206 if (!gpios
->gpio
[i
] || mctrl_gpio_flags_is_dir_out(i
))
209 ret
= gpiod_to_irq(gpios
->gpio
[i
]);
212 "failed to find corresponding irq for %s (idx=%d, err=%d)\n",
213 mctrl_gpios_desc
[i
].name
, idx
, ret
);
218 /* irqs should only be enabled in .enable_ms */
219 irq_set_status_flags(gpios
->irq
[i
], IRQ_NOAUTOEN
);
221 ret
= devm_request_irq(port
->dev
, gpios
->irq
[i
],
222 mctrl_gpio_irq_handle
,
223 IRQ_TYPE_EDGE_BOTH
, dev_name(port
->dev
),
226 /* alternatively implement polling */
228 "failed to request irq for %s (idx=%d, err=%d)\n",
229 mctrl_gpios_desc
[i
].name
, idx
, ret
);
236 EXPORT_SYMBOL_GPL(mctrl_gpio_init
);
238 void mctrl_gpio_free(struct device
*dev
, struct mctrl_gpios
*gpios
)
240 enum mctrl_gpio_idx i
;
245 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
247 devm_free_irq(gpios
->port
->dev
, gpios
->irq
[i
], gpios
);
250 devm_gpiod_put(dev
, gpios
->gpio
[i
]);
252 devm_kfree(dev
, gpios
);
254 EXPORT_SYMBOL_GPL(mctrl_gpio_free
);
256 void mctrl_gpio_enable_ms(struct mctrl_gpios
*gpios
)
258 enum mctrl_gpio_idx i
;
263 /* .enable_ms may be called multiple times */
267 gpios
->mctrl_on
= true;
269 /* get initial status of modem lines GPIOs */
270 mctrl_gpio_get(gpios
, &gpios
->mctrl_prev
);
272 for (i
= 0; i
< UART_GPIO_MAX
; ++i
) {
276 enable_irq(gpios
->irq
[i
]);
279 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms
);
281 void mctrl_gpio_disable_ms(struct mctrl_gpios
*gpios
)
283 enum mctrl_gpio_idx i
;
288 if (!gpios
->mctrl_on
)
291 gpios
->mctrl_on
= false;
293 for (i
= 0; i
< UART_GPIO_MAX
; ++i
) {
297 disable_irq(gpios
->irq
[i
]);
300 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms
);
302 MODULE_LICENSE("GPL");