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.
18 #include <linux/err.h>
19 #include <linux/device.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/termios.h>
23 #include "serial_mctrl_gpio.h"
26 struct gpio_desc
*gpio
[UART_GPIO_MAX
];
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, },
44 void mctrl_gpio_set(struct mctrl_gpios
*gpios
, unsigned int mctrl
)
46 enum mctrl_gpio_idx i
;
47 struct gpio_desc
*desc_array
[UART_GPIO_MAX
];
48 int value_array
[UART_GPIO_MAX
];
49 unsigned int count
= 0;
51 if (IS_ERR_OR_NULL(gpios
))
54 for (i
= 0; i
< UART_GPIO_MAX
; i
++)
55 if (!IS_ERR_OR_NULL(gpios
->gpio
[i
]) &&
56 mctrl_gpios_desc
[i
].dir_out
) {
57 desc_array
[count
] = gpios
->gpio
[i
];
58 value_array
[count
] = !!(mctrl
& mctrl_gpios_desc
[i
].mctrl
);
61 gpiod_set_array(count
, desc_array
, value_array
);
63 EXPORT_SYMBOL_GPL(mctrl_gpio_set
);
65 struct gpio_desc
*mctrl_gpio_to_gpiod(struct mctrl_gpios
*gpios
,
66 enum mctrl_gpio_idx gidx
)
68 if (!IS_ERR_OR_NULL(gpios
) && !IS_ERR_OR_NULL(gpios
->gpio
[gidx
]))
69 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
;
80 * return it unchanged if the structure is not allocated
82 if (IS_ERR_OR_NULL(gpios
))
85 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
86 if (!IS_ERR_OR_NULL(gpios
->gpio
[i
]) &&
87 !mctrl_gpios_desc
[i
].dir_out
) {
88 if (gpiod_get_value(gpios
->gpio
[i
]))
89 *mctrl
|= mctrl_gpios_desc
[i
].mctrl
;
91 *mctrl
&= ~mctrl_gpios_desc
[i
].mctrl
;
97 EXPORT_SYMBOL_GPL(mctrl_gpio_get
);
99 struct mctrl_gpios
*mctrl_gpio_init(struct device
*dev
, unsigned int idx
)
101 struct mctrl_gpios
*gpios
;
102 enum mctrl_gpio_idx i
;
105 gpios
= devm_kzalloc(dev
, sizeof(*gpios
), GFP_KERNEL
);
107 return ERR_PTR(-ENOMEM
);
109 for (i
= 0; i
< UART_GPIO_MAX
; i
++) {
110 gpios
->gpio
[i
] = devm_gpiod_get_index(dev
,
111 mctrl_gpios_desc
[i
].name
,
115 * The GPIOs are maybe not all filled,
116 * this is not an error.
118 if (IS_ERR_OR_NULL(gpios
->gpio
[i
]))
121 if (mctrl_gpios_desc
[i
].dir_out
)
122 err
= gpiod_direction_output(gpios
->gpio
[i
], 0);
124 err
= gpiod_direction_input(gpios
->gpio
[i
]);
126 dev_dbg(dev
, "Unable to set direction for %s GPIO",
127 mctrl_gpios_desc
[i
].name
);
128 devm_gpiod_put(dev
, gpios
->gpio
[i
]);
129 gpios
->gpio
[i
] = NULL
;
135 EXPORT_SYMBOL_GPL(mctrl_gpio_init
);
137 void mctrl_gpio_free(struct device
*dev
, struct mctrl_gpios
*gpios
)
139 enum mctrl_gpio_idx i
;
141 if (IS_ERR_OR_NULL(gpios
))
144 for (i
= 0; i
< UART_GPIO_MAX
; i
++)
145 if (!IS_ERR_OR_NULL(gpios
->gpio
[i
]))
146 devm_gpiod_put(dev
, gpios
->gpio
[i
]);
147 devm_kfree(dev
, gpios
);
149 EXPORT_SYMBOL_GPL(mctrl_gpio_free
);