1 RS485 auto mode support ported from 2.4 (diff against 2.6.19-rc6-git10)
3 Signed-off-by: Petr Stetiar <ynezz@true.cz>
5 diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
6 index 4213fab..5b3c5ff 100644
7 --- a/drivers/serial/amba-pl010.c
8 +++ b/drivers/serial/amba-pl010.c
10 #include <linux/amba/serial.h>
13 +#include <asm/hardware.h>
18 #define UART_DUMMY_RSR_RX 256
19 #define UART_PORT_SIZE 64
21 +#ifdef CONFIG_MACH_TS72XX
22 +static void __iomem *ts_rs485_data9_register;
23 +static void __iomem *ts_rs485_control_register;
27 * We wrap our port structure around the generic uart_port.
29 @@ -487,6 +493,107 @@ static int pl010_verify_port(struct uart
33 +#ifdef CONFIG_MACH_TS72XX
34 +static int ts72xx_rs485_init(void)
36 + ts_rs485_data9_register = ioremap(TS72XX_RS485_DATA9_PHYS_BASE, 4096);
37 + if (ts_rs485_data9_register == NULL) {
41 + ts_rs485_control_register = ioremap(TS72XX_RS485_CONTROL_PHYS_BASE, 4096);
42 + if (ts_rs485_control_register == NULL) {
43 + iounmap(ts_rs485_data9_register);
50 +static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
52 + int baud, cflag, mode;
56 + if (!is_rs485_installed()) {
57 + printk("amba-pl010.c: this board does not support RS485 auto mode\n");
61 + if (port->line != 1) {
62 + printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
67 + cflag = port->info->tty->termios->c_cflag ;
74 + baud = tty_get_baud_rate(port->info->tty);
78 + if ((mode & TS72XX_RS485_AUTO485FD) || (mode & TS72XX_RS485_AUTO485HD)) {
79 + printk("amba-pl010.c: unsetting auto RS485 mode\n");
80 + __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_control_register);
81 + __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_data9_register);
85 + if (mode & TS72XX_RS485_AUTO485FD) {
86 + printk ("amba-pl010.c: setting FULL duplex auto RS485 mode\n");
87 + __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_control_register);
89 + __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
90 + } else if (mode & TS72XX_RS485_AUTO485HD) {
91 + printk("amba-pl010.c: setting HALF DUPLEX auto RS485 mode\n");
94 + __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
97 + __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
100 + __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
103 + __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
106 + printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
109 + if (datalength > 8)
110 + __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
119 +int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
121 +#ifdef CONFIG_MACH_TS72XX
125 + return ts72xx_auto485(port, cmd, (unsigned long *)arg);
128 + return -ENOIOCTLCMD;
131 + return -ENOIOCTLCMD;
134 static struct uart_ops amba_pl010_pops = {
135 .tx_empty = pl010_tx_empty,
136 .set_mctrl = pl010_set_mctrl,
137 @@ -504,6 +611,7 @@ static struct uart_ops amba_pl010_pops =
138 .request_port = pl010_request_port,
139 .config_port = pl010_config_port,
140 .verify_port = pl010_verify_port,
141 + .ioctl = pl010_ioctl,
144 static struct uart_amba_port *amba_ports[UART_NR];
145 @@ -746,6 +854,15 @@ static int __init pl010_init(void)
146 ret = uart_register_driver(&amba_reg);
148 ret = amba_driver_register(&pl010_driver);
149 +#ifdef CONFIG_MACH_TS72XX
150 + if (!ret && is_rs485_installed()) {
151 + ret = ts72xx_rs485_init();
153 + printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
155 + printk("amba-pl010.c: auto RS485 mode initialized\n");
159 uart_unregister_driver(&amba_reg);
161 @@ -756,6 +873,10 @@ static void __exit pl010_exit(void)
163 amba_driver_unregister(&pl010_driver);
164 uart_unregister_driver(&amba_reg);
165 +#ifdef CONFIG_MACH_TS72XX
166 + iounmap(ts_rs485_data9_register);
167 + iounmap(ts_rs485_control_register);
171 module_init(pl010_init);
172 diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
173 index a94f63f..4c9396b 100644
174 --- a/include/asm-arm/arch-ep93xx/ts72xx.h
175 +++ b/include/asm-arm/arch-ep93xx/ts72xx.h
177 #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000
178 #define TS72XX_RTC_DATA_SIZE 0x00001000
180 +#define TS72XX_RS485_CONTROL_PHYS_BASE 0x22C00000
181 +#define TS72XX_RS485_DATA9_PHYS_BASE 0x23000000
182 +#define TS72XX_RS485_AUTO485FD 1
183 +#define TS72XX_RS485_AUTO485HD 2
184 +#define TS72XX_RS485_MODE_RS232 0x00
185 +#define TS72XX_RS485_MODE_FD 0x01
186 +#define TS72XX_RS485_MODE_9600_HD 0x04
187 +#define TS72XX_RS485_MODE_19200_HD 0x05
188 +#define TS72XX_RS485_MODE_57600_HD 0x06
189 +#define TS72XX_RS485_MODE_115200_HD 0x07
193 @@ -87,6 +100,12 @@ static inline int board_is_ts7260(void)
194 return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
197 +static inline int is_rs485_installed(void)
199 + return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
200 + TS72XX_OPTIONS_COM2_RS485);
203 static inline int is_max197_installed(void)
205 return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
206 diff --git a/include/asm-arm/ioctls.h b/include/asm-arm/ioctls.h
207 index bb9a7aa..4d7dad1 100644
208 --- a/include/asm-arm/ioctls.h
209 +++ b/include/asm-arm/ioctls.h
211 #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
212 #define FIOQSIZE 0x545E
214 +#define TIOC_SBCC485 0x545F /* TS72xx RTS/485 mode clear */
215 +#define TIOC_SBCS485 0x5460 /* TS72xx RTS/485 mode set */
217 /* Used for packet mode */
218 #define TIOCPKT_DATA 0
219 #define TIOCPKT_FLUSHREAD 1
220 RS485 auto mode support ported from 2.4 (diff against 2.6.19-rc6-git10)
222 Signed-off-by: Petr Stetiar <ynezz@true.cz>
224 diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
225 index 4213fab..5b3c5ff 100644
226 --- a/drivers/serial/amba-pl010.c
227 +++ b/drivers/serial/amba-pl010.c
229 #include <linux/amba/serial.h>
232 +#include <asm/hardware.h>
237 #define UART_DUMMY_RSR_RX 256
238 #define UART_PORT_SIZE 64
240 +#ifdef CONFIG_MACH_TS72XX
241 +static void __iomem *ts_rs485_data9_register;
242 +static void __iomem *ts_rs485_control_register;
246 * We wrap our port structure around the generic uart_port.
248 @@ -487,6 +493,107 @@ static int pl010_verify_port(struct uart
252 +#ifdef CONFIG_MACH_TS72XX
253 +static int ts72xx_rs485_init(void)
255 + ts_rs485_data9_register = ioremap(TS72XX_RS485_DATA9_PHYS_BASE, 4096);
256 + if (ts_rs485_data9_register == NULL) {
260 + ts_rs485_control_register = ioremap(TS72XX_RS485_CONTROL_PHYS_BASE, 4096);
261 + if (ts_rs485_control_register == NULL) {
262 + iounmap(ts_rs485_data9_register);
269 +static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
271 + int baud, cflag, mode;
275 + if (!is_rs485_installed()) {
276 + printk("amba-pl010.c: this board does not support RS485 auto mode\n");
280 + if (port->line != 1) {
281 + printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
286 + cflag = port->info->tty->termios->c_cflag ;
287 + if (cflag & PARENB)
290 + if (cflag & CSTOPB)
293 + baud = tty_get_baud_rate(port->info->tty);
297 + if ((mode & TS72XX_RS485_AUTO485FD) || (mode & TS72XX_RS485_AUTO485HD)) {
298 + printk("amba-pl010.c: unsetting auto RS485 mode\n");
299 + __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_control_register);
300 + __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_data9_register);
304 + if (mode & TS72XX_RS485_AUTO485FD) {
305 + printk ("amba-pl010.c: setting FULL duplex auto RS485 mode\n");
306 + __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_control_register);
307 + if (datalength > 8)
308 + __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
309 + } else if (mode & TS72XX_RS485_AUTO485HD) {
310 + printk("amba-pl010.c: setting HALF DUPLEX auto RS485 mode\n");
313 + __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
316 + __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
319 + __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
322 + __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
325 + printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
328 + if (datalength > 8)
329 + __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
338 +int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
340 +#ifdef CONFIG_MACH_TS72XX
344 + return ts72xx_auto485(port, cmd, (unsigned long *)arg);
347 + return -ENOIOCTLCMD;
350 + return -ENOIOCTLCMD;
353 static struct uart_ops amba_pl010_pops = {
354 .tx_empty = pl010_tx_empty,
355 .set_mctrl = pl010_set_mctrl,
356 @@ -504,6 +611,7 @@ static struct uart_ops amba_pl010_pops =
357 .request_port = pl010_request_port,
358 .config_port = pl010_config_port,
359 .verify_port = pl010_verify_port,
360 + .ioctl = pl010_ioctl,
363 static struct uart_amba_port *amba_ports[UART_NR];
364 @@ -746,6 +854,15 @@ static int __init pl010_init(void)
365 ret = uart_register_driver(&amba_reg);
367 ret = amba_driver_register(&pl010_driver);
368 +#ifdef CONFIG_MACH_TS72XX
369 + if (!ret && is_rs485_installed()) {
370 + ret = ts72xx_rs485_init();
372 + printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
374 + printk("amba-pl010.c: auto RS485 mode initialized\n");
378 uart_unregister_driver(&amba_reg);
380 @@ -756,6 +873,10 @@ static void __exit pl010_exit(void)
382 amba_driver_unregister(&pl010_driver);
383 uart_unregister_driver(&amba_reg);
384 +#ifdef CONFIG_MACH_TS72XX
385 + iounmap(ts_rs485_data9_register);
386 + iounmap(ts_rs485_control_register);
390 module_init(pl010_init);
391 diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
392 index a94f63f..4c9396b 100644
393 --- a/include/asm-arm/arch-ep93xx/ts72xx.h
394 +++ b/include/asm-arm/arch-ep93xx/ts72xx.h
396 #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000
397 #define TS72XX_RTC_DATA_SIZE 0x00001000
399 +#define TS72XX_RS485_CONTROL_PHYS_BASE 0x22C00000
400 +#define TS72XX_RS485_DATA9_PHYS_BASE 0x23000000
401 +#define TS72XX_RS485_AUTO485FD 1
402 +#define TS72XX_RS485_AUTO485HD 2
403 +#define TS72XX_RS485_MODE_RS232 0x00
404 +#define TS72XX_RS485_MODE_FD 0x01
405 +#define TS72XX_RS485_MODE_9600_HD 0x04
406 +#define TS72XX_RS485_MODE_19200_HD 0x05
407 +#define TS72XX_RS485_MODE_57600_HD 0x06
408 +#define TS72XX_RS485_MODE_115200_HD 0x07
412 @@ -87,6 +100,12 @@ static inline int board_is_ts7260(void)
413 return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
416 +static inline int is_rs485_installed(void)
418 + return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
419 + TS72XX_OPTIONS_COM2_RS485);
422 static inline int is_max197_installed(void)
424 return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
425 diff --git a/include/asm-arm/ioctls.h b/include/asm-arm/ioctls.h
426 index bb9a7aa..4d7dad1 100644
427 --- a/include/asm-arm/ioctls.h
428 +++ b/include/asm-arm/ioctls.h
430 #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
431 #define FIOQSIZE 0x545E
433 +#define TIOC_SBCC485 0x545F /* TS72xx RTS/485 mode clear */
434 +#define TIOC_SBCS485 0x5460 /* TS72xx RTS/485 mode set */
436 /* Used for packet mode */
437 #define TIOCPKT_DATA 0
438 #define TIOCPKT_FLUSHREAD 1