rename packages/ to recipes/ per earlier agreement
[openembedded.git] / recipes / linux / linux-2.6.24 / ts72xx / ts72xx-rs485.patch
1 RS485 auto mode support ported from 2.4 (diff against 2.6.19-rc6-git10)
2
3 Signed-off-by: Petr Stetiar <ynezz@true.cz>
4
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
9 @@ -50,6 +50,7 @@
10  #include <linux/amba/serial.h>
11  
12  #include <asm/io.h>
13 +#include <asm/hardware.h>
14  
15  #define UART_NR                8
16  
17 @@ -65,6 +66,11 @@
18  #define UART_DUMMY_RSR_RX      256
19  #define UART_PORT_SIZE         64
20  
21 +#ifdef CONFIG_MACH_TS72XX
22 +static void __iomem *ts_rs485_data9_register;
23 +static void __iomem *ts_rs485_control_register;
24 +#endif
25 +
26  /*
27   * We wrap our port structure around the generic uart_port.
28   */
29 @@ -487,6 +493,107 @@ static int pl010_verify_port(struct uart
30         return ret;
31  }
32  
33 +#ifdef CONFIG_MACH_TS72XX
34 +static int ts72xx_rs485_init(void)
35 +{
36 +       ts_rs485_data9_register = ioremap(TS72XX_RS485_DATA9_PHYS_BASE, 4096);
37 +       if (ts_rs485_data9_register == NULL) {
38 +               return -1;
39 +       }
40 +
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);
44 +               return -1;
45 +       }
46 +
47 +       return 0;
48 +}
49 +
50 +static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
51 +{
52 +       int baud, cflag, mode;
53 +       int datalength;
54 +
55 +       mode = (int)*arg;
56 +       if (!is_rs485_installed()) {
57 +               printk("amba-pl010.c: this board does not support RS485 auto mode\n");
58 +               return -EINVAL;
59 +       }
60 +
61 +       if (port->line != 1) {
62 +               printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
63 +               return -EINVAL;
64 +       }
65 +
66 +       datalength = 8;
67 +       cflag = port->info->tty->termios->c_cflag ;
68 +       if (cflag & PARENB)
69 +               datalength++;
70 +
71 +       if (cflag & CSTOPB)
72 +               datalength++;
73 +
74 +       baud = tty_get_baud_rate(port->info->tty);
75 +
76 +       switch (cmd) {
77 +               case TIOC_SBCC485:
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);
82 +                       }
83 +                       break;
84 +               case TIOC_SBCS485:
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);
88 +                               if (datalength > 8)
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");
92 +                               switch (baud) {
93 +                                       case 9600:
94 +                                               __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
95 +                                               break;
96 +                                       case 19200:
97 +                                               __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
98 +                                               break;
99 +                                       case 57600:
100 +                                               __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
101 +                                               break;
102 +                                       case 115200:
103 +                                               __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
104 +                                               break;
105 +                                       default:
106 +                                       printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
107 +                                       return -1;
108 +                               }
109 +                               if (datalength > 8)
110 +                                       __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
111 +                       }
112 +                       break;
113 +       }
114 +
115 +       return 0;
116 +}
117 +#endif
118 +
119 +int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
120 +{
121 +#ifdef CONFIG_MACH_TS72XX
122 +       switch (cmd) {
123 +               case TIOC_SBCC485:
124 +               case TIOC_SBCS485:
125 +                       return ts72xx_auto485(port, cmd, (unsigned long *)arg);
126 +                       break;
127 +               default:
128 +                       return -ENOIOCTLCMD;
129 +       }
130 +#endif
131 +       return -ENOIOCTLCMD;
132 +}
133 +
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,
142  };
143  
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);
147         if (ret == 0) {
148                 ret = amba_driver_register(&pl010_driver);
149 +#ifdef CONFIG_MACH_TS72XX
150 +               if (!ret && is_rs485_installed()) {
151 +                       ret = ts72xx_rs485_init();
152 +                       if (ret)
153 +                               printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
154 +                       else
155 +                               printk("amba-pl010.c: auto RS485 mode initialized\n");
156 +               }
157 +#endif
158                 if (ret)
159                         uart_unregister_driver(&amba_reg);
160         }
161 @@ -756,6 +873,10 @@ static void __exit pl010_exit(void)
162  {
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);
168 +#endif
169  }
170  
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
176 @@ -68,6 +68,16 @@
177  #define TS72XX_RTC_DATA_PHYS_BASE      0x11700000
178  #define TS72XX_RTC_DATA_SIZE           0x00001000
179  
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
190  
191  #ifndef __ASSEMBLY__
192  #include <asm/io.h>
193 @@ -87,6 +100,12 @@ static inline int board_is_ts7260(void)
194         return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
195  }
196  
197 +static inline int is_rs485_installed(void)
198 +{
199 +       return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
200 +                                       TS72XX_OPTIONS_COM2_RS485);
201 +}
202 +
203  static inline int is_max197_installed(void)
204  {
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
210 @@ -66,6 +66,9 @@
211  #define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
212  #define FIOQSIZE       0x545E
213  
214 +#define TIOC_SBCC485   0x545F /* TS72xx RTS/485 mode clear */
215 +#define TIOC_SBCS485   0x5460 /* TS72xx RTS/485 mode set */
216 +
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)
221
222 Signed-off-by: Petr Stetiar <ynezz@true.cz>
223
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
228 @@ -50,6 +50,7 @@
229  #include <linux/amba/serial.h>
230  
231  #include <asm/io.h>
232 +#include <asm/hardware.h>
233  
234  #define UART_NR                8
235  
236 @@ -65,6 +66,11 @@
237  #define UART_DUMMY_RSR_RX      256
238  #define UART_PORT_SIZE         64
239  
240 +#ifdef CONFIG_MACH_TS72XX
241 +static void __iomem *ts_rs485_data9_register;
242 +static void __iomem *ts_rs485_control_register;
243 +#endif
244 +
245  /*
246   * We wrap our port structure around the generic uart_port.
247   */
248 @@ -487,6 +493,107 @@ static int pl010_verify_port(struct uart
249         return ret;
250  }
251  
252 +#ifdef CONFIG_MACH_TS72XX
253 +static int ts72xx_rs485_init(void)
254 +{
255 +       ts_rs485_data9_register = ioremap(TS72XX_RS485_DATA9_PHYS_BASE, 4096);
256 +       if (ts_rs485_data9_register == NULL) {
257 +               return -1;
258 +       }
259 +
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);
263 +               return -1;
264 +       }
265 +
266 +       return 0;
267 +}
268 +
269 +static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
270 +{
271 +       int baud, cflag, mode;
272 +       int datalength;
273 +
274 +       mode = (int)*arg;
275 +       if (!is_rs485_installed()) {
276 +               printk("amba-pl010.c: this board does not support RS485 auto mode\n");
277 +               return -EINVAL;
278 +       }
279 +
280 +       if (port->line != 1) {
281 +               printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
282 +               return -EINVAL;
283 +       }
284 +
285 +       datalength = 8;
286 +       cflag = port->info->tty->termios->c_cflag ;
287 +       if (cflag & PARENB)
288 +               datalength++;
289 +
290 +       if (cflag & CSTOPB)
291 +               datalength++;
292 +
293 +       baud = tty_get_baud_rate(port->info->tty);
294 +
295 +       switch (cmd) {
296 +               case TIOC_SBCC485:
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);
301 +                       }
302 +                       break;
303 +               case TIOC_SBCS485:
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");
311 +                               switch (baud) {
312 +                                       case 9600:
313 +                                               __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
314 +                                               break;
315 +                                       case 19200:
316 +                                               __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
317 +                                               break;
318 +                                       case 57600:
319 +                                               __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
320 +                                               break;
321 +                                       case 115200:
322 +                                               __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
323 +                                               break;
324 +                                       default:
325 +                                       printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
326 +                                       return -1;
327 +                               }
328 +                               if (datalength > 8)
329 +                                       __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
330 +                       }
331 +                       break;
332 +       }
333 +
334 +       return 0;
335 +}
336 +#endif
337 +
338 +int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
339 +{
340 +#ifdef CONFIG_MACH_TS72XX
341 +       switch (cmd) {
342 +               case TIOC_SBCC485:
343 +               case TIOC_SBCS485:
344 +                       return ts72xx_auto485(port, cmd, (unsigned long *)arg);
345 +                       break;
346 +               default:
347 +                       return -ENOIOCTLCMD;
348 +       }
349 +#endif
350 +       return -ENOIOCTLCMD;
351 +}
352 +
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,
361  };
362  
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);
366         if (ret == 0) {
367                 ret = amba_driver_register(&pl010_driver);
368 +#ifdef CONFIG_MACH_TS72XX
369 +               if (!ret && is_rs485_installed()) {
370 +                       ret = ts72xx_rs485_init();
371 +                       if (ret)
372 +                               printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
373 +                       else
374 +                               printk("amba-pl010.c: auto RS485 mode initialized\n");
375 +               }
376 +#endif
377                 if (ret)
378                         uart_unregister_driver(&amba_reg);
379         }
380 @@ -756,6 +873,10 @@ static void __exit pl010_exit(void)
381  {
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);
387 +#endif
388  }
389  
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
395 @@ -68,6 +68,16 @@
396  #define TS72XX_RTC_DATA_PHYS_BASE      0x11700000
397  #define TS72XX_RTC_DATA_SIZE           0x00001000
398  
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
409  
410  #ifndef __ASSEMBLY__
411  #include <asm/io.h>
412 @@ -87,6 +100,12 @@ static inline int board_is_ts7260(void)
413         return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
414  }
415  
416 +static inline int is_rs485_installed(void)
417 +{
418 +       return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
419 +                                       TS72XX_OPTIONS_COM2_RS485);
420 +}
421 +
422  static inline int is_max197_installed(void)
423  {
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
429 @@ -66,6 +66,9 @@
430  #define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
431  #define FIOQSIZE       0x545E
432  
433 +#define TIOC_SBCC485   0x545F /* TS72xx RTS/485 mode clear */
434 +#define TIOC_SBCS485   0x5460 /* TS72xx RTS/485 mode set */
435 +
436  /* Used for packet mode */
437  #define TIOCPKT_DATA            0
438  #define TIOCPKT_FLUSHREAD       1