blob: e6139943ba2506586c768e923efb66497c9f7bc5 [file] [log] [blame]
wdenk507bbe32004-04-18 21:13:41 +00001/*
Michal Simek49a23e42011-09-25 21:03:08 +00002 * (C) Copyright 2008-2011 Michal Simek <monstr@monstr.eu>
Michal Simek53ea9812008-07-11 10:10:31 +02003 * Clean driver and add xilinx constant from header file
wdenk507bbe32004-04-18 21:13:41 +00004 *
Michal Simek53ea9812008-07-11 10:10:31 +02005 * (C) Copyright 2004 Atmark Techno, Inc.
wdenk507bbe32004-04-18 21:13:41 +00006 * Yasushi SHOJI <yashi@atmark-techno.com>
7 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenk507bbe32004-04-18 21:13:41 +00009 */
10
11#include <config.h>
Michal Simek49a23e42011-09-25 21:03:08 +000012#include <common.h>
Michal Simek53ea9812008-07-11 10:10:31 +020013#include <asm/io.h>
Michal Simek49a23e42011-09-25 21:03:08 +000014#include <linux/compiler.h>
15#include <serial.h>
wdenk507bbe32004-04-18 21:13:41 +000016
Michal Simek53ea9812008-07-11 10:10:31 +020017#define SR_TX_FIFO_FULL 0x08 /* transmit FIFO full */
18#define SR_RX_FIFO_VALID_DATA 0x01 /* data in receive FIFO */
19#define SR_RX_FIFO_FULL 0x02 /* receive FIFO full */
wdenk507bbe32004-04-18 21:13:41 +000020
Michal Simek49a23e42011-09-25 21:03:08 +000021struct uartlite {
22 unsigned int rx_fifo;
23 unsigned int tx_fifo;
24 unsigned int status;
25};
wdenk507bbe32004-04-18 21:13:41 +000026
Michal Simek8cb9b232011-10-18 00:22:10 +000027static struct uartlite *userial_ports[4] = {
Michal Simek49a23e42011-09-25 21:03:08 +000028#ifdef XILINX_UARTLITE_BASEADDR
29 [0] = (struct uartlite *)XILINX_UARTLITE_BASEADDR,
30#endif
31#ifdef XILINX_UARTLITE_BASEADDR1
32 [1] = (struct uartlite *)XILINX_UARTLITE_BASEADDR1,
33#endif
34#ifdef XILINX_UARTLITE_BASEADDR2
35 [2] = (struct uartlite *)XILINX_UARTLITE_BASEADDR2,
36#endif
37#ifdef XILINX_UARTLITE_BASEADDR3
38 [3] = (struct uartlite *)XILINX_UARTLITE_BASEADDR3
39#endif
40};
41
Axel Lin212d7da2013-10-16 09:45:56 +080042static void uartlite_serial_putc(const char c, const int port)
Michal Simek49a23e42011-09-25 21:03:08 +000043{
44 struct uartlite *regs = userial_ports[port];
45
46 if (c == '\n')
47 uartlite_serial_putc('\r', port);
48
49 while (in_be32(&regs->status) & SR_TX_FIFO_FULL)
50 ;
51 out_be32(&regs->tx_fifo, c & 0xff);
52}
53
Axel Lin212d7da2013-10-16 09:45:56 +080054static void uartlite_serial_puts(const char *s, const int port)
Michal Simek49a23e42011-09-25 21:03:08 +000055{
56 while (*s)
57 uartlite_serial_putc(*s++, port);
58}
59
Axel Lin212d7da2013-10-16 09:45:56 +080060static int uartlite_serial_getc(const int port)
Michal Simek49a23e42011-09-25 21:03:08 +000061{
62 struct uartlite *regs = userial_ports[port];
63
64 while (!(in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA))
65 ;
66 return in_be32(&regs->rx_fifo) & 0xff;
67}
68
Axel Lin212d7da2013-10-16 09:45:56 +080069static int uartlite_serial_tstc(const int port)
Michal Simek49a23e42011-09-25 21:03:08 +000070{
71 struct uartlite *regs = userial_ports[port];
72
73 return in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA;
74}
75
Michal Simek25239e12012-07-02 10:32:18 +020076static int uartlite_serial_init(const int port)
77{
78 if (userial_ports[port])
79 return 0;
80 return -1;
81}
82
Michal Simek49a23e42011-09-25 21:03:08 +000083/* Multi serial device functions */
84#define DECLARE_ESERIAL_FUNCTIONS(port) \
Axel Lin212d7da2013-10-16 09:45:56 +080085 static int userial##port##_init(void) \
Michal Simek25239e12012-07-02 10:32:18 +020086 { return uartlite_serial_init(port); } \
Axel Lin212d7da2013-10-16 09:45:56 +080087 static void userial##port##_setbrg(void) {} \
88 static int userial##port##_getc(void) \
Michal Simek49a23e42011-09-25 21:03:08 +000089 { return uartlite_serial_getc(port); } \
Axel Lin212d7da2013-10-16 09:45:56 +080090 static int userial##port##_tstc(void) \
Michal Simek49a23e42011-09-25 21:03:08 +000091 { return uartlite_serial_tstc(port); } \
Axel Lin212d7da2013-10-16 09:45:56 +080092 static void userial##port##_putc(const char c) \
Michal Simek49a23e42011-09-25 21:03:08 +000093 { uartlite_serial_putc(c, port); } \
Axel Lin212d7da2013-10-16 09:45:56 +080094 static void userial##port##_puts(const char *s) \
Michal Simek49a23e42011-09-25 21:03:08 +000095 { uartlite_serial_puts(s, port); }
96
97/* Serial device descriptor */
Marek Vasut90bad892012-09-09 18:48:28 +020098#define INIT_ESERIAL_STRUCTURE(port, __name) { \
99 .name = __name, \
100 .start = userial##port##_init, \
101 .stop = NULL, \
102 .setbrg = userial##port##_setbrg, \
103 .getc = userial##port##_getc, \
104 .tstc = userial##port##_tstc, \
105 .putc = userial##port##_putc, \
106 .puts = userial##port##_puts, \
107}
Michal Simek49a23e42011-09-25 21:03:08 +0000108
109DECLARE_ESERIAL_FUNCTIONS(0);
110struct serial_device uartlite_serial0_device =
111 INIT_ESERIAL_STRUCTURE(0, "ttyUL0");
112DECLARE_ESERIAL_FUNCTIONS(1);
113struct serial_device uartlite_serial1_device =
114 INIT_ESERIAL_STRUCTURE(1, "ttyUL1");
115DECLARE_ESERIAL_FUNCTIONS(2);
116struct serial_device uartlite_serial2_device =
117 INIT_ESERIAL_STRUCTURE(2, "ttyUL2");
118DECLARE_ESERIAL_FUNCTIONS(3);
119struct serial_device uartlite_serial3_device =
120 INIT_ESERIAL_STRUCTURE(3, "ttyUL3");
121
122__weak struct serial_device *default_serial_console(void)
123{
Michal Simek25239e12012-07-02 10:32:18 +0200124 if (userial_ports[0])
125 return &uartlite_serial0_device;
126 if (userial_ports[1])
127 return &uartlite_serial1_device;
128 if (userial_ports[2])
129 return &uartlite_serial2_device;
130 if (userial_ports[3])
131 return &uartlite_serial3_device;
132
133 return NULL;
Michal Simek49a23e42011-09-25 21:03:08 +0000134}
Marek Vasut87d69222012-09-12 19:45:58 +0200135
136void uartlite_serial_initialize(void)
137{
138#ifdef XILINX_UARTLITE_BASEADDR
139 serial_register(&uartlite_serial0_device);
140#endif /* XILINX_UARTLITE_BASEADDR */
141#ifdef XILINX_UARTLITE_BASEADDR1
142 serial_register(&uartlite_serial1_device);
143#endif /* XILINX_UARTLITE_BASEADDR1 */
144#ifdef XILINX_UARTLITE_BASEADDR2
145 serial_register(&uartlite_serial2_device);
146#endif /* XILINX_UARTLITE_BASEADDR2 */
147#ifdef XILINX_UARTLITE_BASEADDR3
148 serial_register(&uartlite_serial3_device);
149#endif /* XILINX_UARTLITE_BASEADDR3 */
150}