0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/err.h>
0009 #include <linux/device.h>
0010 #include <linux/irq.h>
0011 #include <linux/gpio/consumer.h>
0012 #include <linux/termios.h>
0013 #include <linux/serial_core.h>
0014 #include <linux/module.h>
0015 #include <linux/property.h>
0016
0017 #include "serial_mctrl_gpio.h"
0018
0019 struct mctrl_gpios {
0020 struct uart_port *port;
0021 struct gpio_desc *gpio[UART_GPIO_MAX];
0022 int irq[UART_GPIO_MAX];
0023 unsigned int mctrl_prev;
0024 bool mctrl_on;
0025 };
0026
0027 static const struct {
0028 const char *name;
0029 unsigned int mctrl;
0030 enum gpiod_flags flags;
0031 } mctrl_gpios_desc[UART_GPIO_MAX] = {
0032 { "cts", TIOCM_CTS, GPIOD_IN, },
0033 { "dsr", TIOCM_DSR, GPIOD_IN, },
0034 { "dcd", TIOCM_CD, GPIOD_IN, },
0035 { "rng", TIOCM_RNG, GPIOD_IN, },
0036 { "rts", TIOCM_RTS, GPIOD_OUT_LOW, },
0037 { "dtr", TIOCM_DTR, GPIOD_OUT_LOW, },
0038 };
0039
0040 static bool mctrl_gpio_flags_is_dir_out(unsigned int idx)
0041 {
0042 return mctrl_gpios_desc[idx].flags & GPIOD_FLAGS_BIT_DIR_OUT;
0043 }
0044
0045
0046
0047
0048
0049
0050
0051
0052 void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
0053 {
0054 enum mctrl_gpio_idx i;
0055 struct gpio_desc *desc_array[UART_GPIO_MAX];
0056 DECLARE_BITMAP(values, UART_GPIO_MAX);
0057 unsigned int count = 0;
0058
0059 if (gpios == NULL)
0060 return;
0061
0062 for (i = 0; i < UART_GPIO_MAX; i++)
0063 if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
0064 desc_array[count] = gpios->gpio[i];
0065 __assign_bit(count, values,
0066 mctrl & mctrl_gpios_desc[i].mctrl);
0067 count++;
0068 }
0069 gpiod_set_array_value(count, desc_array, NULL, values);
0070 }
0071 EXPORT_SYMBOL_GPL(mctrl_gpio_set);
0072
0073
0074
0075
0076
0077
0078
0079 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
0080 enum mctrl_gpio_idx gidx)
0081 {
0082 if (gpios == NULL)
0083 return NULL;
0084
0085 return gpios->gpio[gidx];
0086 }
0087 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
0098 {
0099 enum mctrl_gpio_idx i;
0100
0101 if (gpios == NULL)
0102 return *mctrl;
0103
0104 for (i = 0; i < UART_GPIO_MAX; i++) {
0105 if (gpios->gpio[i] && !mctrl_gpio_flags_is_dir_out(i)) {
0106 if (gpiod_get_value(gpios->gpio[i]))
0107 *mctrl |= mctrl_gpios_desc[i].mctrl;
0108 else
0109 *mctrl &= ~mctrl_gpios_desc[i].mctrl;
0110 }
0111 }
0112
0113 return *mctrl;
0114 }
0115 EXPORT_SYMBOL_GPL(mctrl_gpio_get);
0116
0117 unsigned int
0118 mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl)
0119 {
0120 enum mctrl_gpio_idx i;
0121
0122 if (gpios == NULL)
0123 return *mctrl;
0124
0125 for (i = 0; i < UART_GPIO_MAX; i++) {
0126 if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
0127 if (gpiod_get_value(gpios->gpio[i]))
0128 *mctrl |= mctrl_gpios_desc[i].mctrl;
0129 else
0130 *mctrl &= ~mctrl_gpios_desc[i].mctrl;
0131 }
0132 }
0133
0134 return *mctrl;
0135 }
0136 EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs);
0137
0138 struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
0139 {
0140 struct mctrl_gpios *gpios;
0141 enum mctrl_gpio_idx i;
0142
0143 gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL);
0144 if (!gpios)
0145 return ERR_PTR(-ENOMEM);
0146
0147 for (i = 0; i < UART_GPIO_MAX; i++) {
0148 char *gpio_str;
0149 bool present;
0150
0151
0152 gpio_str = kasprintf(GFP_KERNEL, "%s-gpios",
0153 mctrl_gpios_desc[i].name);
0154 if (!gpio_str)
0155 continue;
0156
0157 present = device_property_present(dev, gpio_str);
0158 kfree(gpio_str);
0159 if (!present)
0160 continue;
0161
0162 gpios->gpio[i] =
0163 devm_gpiod_get_index_optional(dev,
0164 mctrl_gpios_desc[i].name,
0165 idx,
0166 mctrl_gpios_desc[i].flags);
0167
0168 if (IS_ERR(gpios->gpio[i]))
0169 return ERR_CAST(gpios->gpio[i]);
0170 }
0171
0172 return gpios;
0173 }
0174 EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto);
0175
0176 #define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
0177 static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context)
0178 {
0179 struct mctrl_gpios *gpios = context;
0180 struct uart_port *port = gpios->port;
0181 u32 mctrl = gpios->mctrl_prev;
0182 u32 mctrl_diff;
0183 unsigned long flags;
0184
0185 mctrl_gpio_get(gpios, &mctrl);
0186
0187 spin_lock_irqsave(&port->lock, flags);
0188
0189 mctrl_diff = mctrl ^ gpios->mctrl_prev;
0190 gpios->mctrl_prev = mctrl;
0191
0192 if (mctrl_diff & MCTRL_ANY_DELTA && port->state != NULL) {
0193 if ((mctrl_diff & mctrl) & TIOCM_RI)
0194 port->icount.rng++;
0195
0196 if ((mctrl_diff & mctrl) & TIOCM_DSR)
0197 port->icount.dsr++;
0198
0199 if (mctrl_diff & TIOCM_CD)
0200 uart_handle_dcd_change(port, mctrl & TIOCM_CD);
0201
0202 if (mctrl_diff & TIOCM_CTS)
0203 uart_handle_cts_change(port, mctrl & TIOCM_CTS);
0204
0205 wake_up_interruptible(&port->state->port.delta_msr_wait);
0206 }
0207
0208 spin_unlock_irqrestore(&port->lock, flags);
0209
0210 return IRQ_HANDLED;
0211 }
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
0225 {
0226 struct mctrl_gpios *gpios;
0227 enum mctrl_gpio_idx i;
0228
0229 gpios = mctrl_gpio_init_noauto(port->dev, idx);
0230 if (IS_ERR(gpios))
0231 return gpios;
0232
0233 gpios->port = port;
0234
0235 for (i = 0; i < UART_GPIO_MAX; ++i) {
0236 int ret;
0237
0238 if (!gpios->gpio[i] || mctrl_gpio_flags_is_dir_out(i))
0239 continue;
0240
0241 ret = gpiod_to_irq(gpios->gpio[i]);
0242 if (ret < 0) {
0243 dev_err(port->dev,
0244 "failed to find corresponding irq for %s (idx=%d, err=%d)\n",
0245 mctrl_gpios_desc[i].name, idx, ret);
0246 return ERR_PTR(ret);
0247 }
0248 gpios->irq[i] = ret;
0249
0250
0251 irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN);
0252
0253 ret = devm_request_irq(port->dev, gpios->irq[i],
0254 mctrl_gpio_irq_handle,
0255 IRQ_TYPE_EDGE_BOTH, dev_name(port->dev),
0256 gpios);
0257 if (ret) {
0258
0259 dev_err(port->dev,
0260 "failed to request irq for %s (idx=%d, err=%d)\n",
0261 mctrl_gpios_desc[i].name, idx, ret);
0262 return ERR_PTR(ret);
0263 }
0264 }
0265
0266 return gpios;
0267 }
0268 EXPORT_SYMBOL_GPL(mctrl_gpio_init);
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
0279 {
0280 enum mctrl_gpio_idx i;
0281
0282 if (gpios == NULL)
0283 return;
0284
0285 for (i = 0; i < UART_GPIO_MAX; i++) {
0286 if (gpios->irq[i])
0287 devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
0288
0289 if (gpios->gpio[i])
0290 devm_gpiod_put(dev, gpios->gpio[i]);
0291 }
0292 devm_kfree(dev, gpios);
0293 }
0294 EXPORT_SYMBOL_GPL(mctrl_gpio_free);
0295
0296
0297
0298
0299
0300 void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
0301 {
0302 enum mctrl_gpio_idx i;
0303
0304 if (gpios == NULL)
0305 return;
0306
0307
0308 if (gpios->mctrl_on)
0309 return;
0310
0311 gpios->mctrl_on = true;
0312
0313
0314 mctrl_gpio_get(gpios, &gpios->mctrl_prev);
0315
0316 for (i = 0; i < UART_GPIO_MAX; ++i) {
0317 if (!gpios->irq[i])
0318 continue;
0319
0320 enable_irq(gpios->irq[i]);
0321 }
0322 }
0323 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms);
0324
0325
0326
0327
0328
0329 void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
0330 {
0331 enum mctrl_gpio_idx i;
0332
0333 if (gpios == NULL)
0334 return;
0335
0336 if (!gpios->mctrl_on)
0337 return;
0338
0339 gpios->mctrl_on = false;
0340
0341 for (i = 0; i < UART_GPIO_MAX; ++i) {
0342 if (!gpios->irq[i])
0343 continue;
0344
0345 disable_irq(gpios->irq[i]);
0346 }
0347 }
0348 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);
0349
0350 void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios)
0351 {
0352 enum mctrl_gpio_idx i;
0353
0354 if (!gpios)
0355 return;
0356
0357 if (!gpios->mctrl_on)
0358 return;
0359
0360 for (i = 0; i < UART_GPIO_MAX; ++i) {
0361 if (!gpios->irq[i])
0362 continue;
0363
0364 enable_irq_wake(gpios->irq[i]);
0365 }
0366 }
0367 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_irq_wake);
0368
0369 void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios)
0370 {
0371 enum mctrl_gpio_idx i;
0372
0373 if (!gpios)
0374 return;
0375
0376 if (!gpios->mctrl_on)
0377 return;
0378
0379 for (i = 0; i < UART_GPIO_MAX; ++i) {
0380 if (!gpios->irq[i])
0381 continue;
0382
0383 disable_irq_wake(gpios->irq[i]);
0384 }
0385 }
0386 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_irq_wake);
0387
0388 MODULE_LICENSE("GPL");