Commit d9a3bec682f9756621615f4306718a356a3230e3
dm: ns16550: Add support for reg-offset property
reg-offset is the part of standard 8250 binding in the kernel. It is shifting start of address space by reg-offset. On Xilinx platform this offset is typically 0x1000. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Tom Rini <trini@konsulko.com>
Showing 2 changed files with 5 additions and 2 deletions Inline Diff
1 | /* | 1 | /* |
2 | * COM1 NS16550 support | 2 | * COM1 NS16550 support |
3 | * originally from linux source (arch/powerpc/boot/ns16550.c) | 3 | * originally from linux source (arch/powerpc/boot/ns16550.c) |
4 | * modified to use CONFIG_SYS_ISA_MEM and new defines | 4 | * modified to use CONFIG_SYS_ISA_MEM and new defines |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <common.h> | 7 | #include <common.h> |
8 | #include <dm.h> | 8 | #include <dm.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <fdtdec.h> | 10 | #include <fdtdec.h> |
11 | #include <ns16550.h> | 11 | #include <ns16550.h> |
12 | #include <serial.h> | 12 | #include <serial.h> |
13 | #include <watchdog.h> | 13 | #include <watchdog.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | 16 | ||
17 | DECLARE_GLOBAL_DATA_PTR; | 17 | DECLARE_GLOBAL_DATA_PTR; |
18 | 18 | ||
19 | #define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */ | 19 | #define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */ |
20 | #define UART_MCRVAL (UART_MCR_DTR | \ | 20 | #define UART_MCRVAL (UART_MCR_DTR | \ |
21 | UART_MCR_RTS) /* RTS/DTR */ | 21 | UART_MCR_RTS) /* RTS/DTR */ |
22 | #define UART_FCRVAL (UART_FCR_FIFO_EN | \ | 22 | #define UART_FCRVAL (UART_FCR_FIFO_EN | \ |
23 | UART_FCR_RXSR | \ | 23 | UART_FCR_RXSR | \ |
24 | UART_FCR_TXSR) /* Clear & enable FIFOs */ | 24 | UART_FCR_TXSR) /* Clear & enable FIFOs */ |
25 | 25 | ||
26 | #ifndef CONFIG_DM_SERIAL | 26 | #ifndef CONFIG_DM_SERIAL |
27 | #ifdef CONFIG_SYS_NS16550_PORT_MAPPED | 27 | #ifdef CONFIG_SYS_NS16550_PORT_MAPPED |
28 | #define serial_out(x, y) outb(x, (ulong)y) | 28 | #define serial_out(x, y) outb(x, (ulong)y) |
29 | #define serial_in(y) inb((ulong)y) | 29 | #define serial_in(y) inb((ulong)y) |
30 | #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0) | 30 | #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0) |
31 | #define serial_out(x, y) out_be32(y, x) | 31 | #define serial_out(x, y) out_be32(y, x) |
32 | #define serial_in(y) in_be32(y) | 32 | #define serial_in(y) in_be32(y) |
33 | #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0) | 33 | #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0) |
34 | #define serial_out(x, y) out_le32(y, x) | 34 | #define serial_out(x, y) out_le32(y, x) |
35 | #define serial_in(y) in_le32(y) | 35 | #define serial_in(y) in_le32(y) |
36 | #else | 36 | #else |
37 | #define serial_out(x, y) writeb(x, y) | 37 | #define serial_out(x, y) writeb(x, y) |
38 | #define serial_in(y) readb(y) | 38 | #define serial_in(y) readb(y) |
39 | #endif | 39 | #endif |
40 | #endif /* !CONFIG_DM_SERIAL */ | 40 | #endif /* !CONFIG_DM_SERIAL */ |
41 | 41 | ||
42 | #if defined(CONFIG_SOC_KEYSTONE) | 42 | #if defined(CONFIG_SOC_KEYSTONE) |
43 | #define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE 0 | 43 | #define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE 0 |
44 | #define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0)) | 44 | #define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0)) |
45 | #undef UART_MCRVAL | 45 | #undef UART_MCRVAL |
46 | #ifdef CONFIG_SERIAL_HW_FLOW_CONTROL | 46 | #ifdef CONFIG_SERIAL_HW_FLOW_CONTROL |
47 | #define UART_MCRVAL (UART_MCR_RTS | UART_MCR_AFE) | 47 | #define UART_MCRVAL (UART_MCR_RTS | UART_MCR_AFE) |
48 | #else | 48 | #else |
49 | #define UART_MCRVAL (UART_MCR_RTS) | 49 | #define UART_MCRVAL (UART_MCR_RTS) |
50 | #endif | 50 | #endif |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | #ifndef CONFIG_SYS_NS16550_IER | 53 | #ifndef CONFIG_SYS_NS16550_IER |
54 | #define CONFIG_SYS_NS16550_IER 0x00 | 54 | #define CONFIG_SYS_NS16550_IER 0x00 |
55 | #endif /* CONFIG_SYS_NS16550_IER */ | 55 | #endif /* CONFIG_SYS_NS16550_IER */ |
56 | 56 | ||
57 | #ifdef CONFIG_DM_SERIAL | 57 | #ifdef CONFIG_DM_SERIAL |
58 | 58 | ||
59 | #ifndef CONFIG_SYS_NS16550_CLK | 59 | #ifndef CONFIG_SYS_NS16550_CLK |
60 | #define CONFIG_SYS_NS16550_CLK 0 | 60 | #define CONFIG_SYS_NS16550_CLK 0 |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | static inline void serial_out_shift(void *addr, int shift, int value) | 63 | static inline void serial_out_shift(void *addr, int shift, int value) |
64 | { | 64 | { |
65 | #ifdef CONFIG_SYS_NS16550_PORT_MAPPED | 65 | #ifdef CONFIG_SYS_NS16550_PORT_MAPPED |
66 | outb(value, (ulong)addr); | 66 | outb(value, (ulong)addr); |
67 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) | 67 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) |
68 | out_le32(addr, value); | 68 | out_le32(addr, value); |
69 | #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) | 69 | #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) |
70 | out_be32(addr, value); | 70 | out_be32(addr, value); |
71 | #elif defined(CONFIG_SYS_NS16550_MEM32) | 71 | #elif defined(CONFIG_SYS_NS16550_MEM32) |
72 | writel(value, addr); | 72 | writel(value, addr); |
73 | #elif defined(CONFIG_SYS_BIG_ENDIAN) | 73 | #elif defined(CONFIG_SYS_BIG_ENDIAN) |
74 | writeb(value, addr + (1 << shift) - 1); | 74 | writeb(value, addr + (1 << shift) - 1); |
75 | #else | 75 | #else |
76 | writeb(value, addr); | 76 | writeb(value, addr); |
77 | #endif | 77 | #endif |
78 | } | 78 | } |
79 | 79 | ||
80 | static inline int serial_in_shift(void *addr, int shift) | 80 | static inline int serial_in_shift(void *addr, int shift) |
81 | { | 81 | { |
82 | #ifdef CONFIG_SYS_NS16550_PORT_MAPPED | 82 | #ifdef CONFIG_SYS_NS16550_PORT_MAPPED |
83 | return inb((ulong)addr); | 83 | return inb((ulong)addr); |
84 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) | 84 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) |
85 | return in_le32(addr); | 85 | return in_le32(addr); |
86 | #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) | 86 | #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) |
87 | return in_be32(addr); | 87 | return in_be32(addr); |
88 | #elif defined(CONFIG_SYS_NS16550_MEM32) | 88 | #elif defined(CONFIG_SYS_NS16550_MEM32) |
89 | return readl(addr); | 89 | return readl(addr); |
90 | #elif defined(CONFIG_SYS_BIG_ENDIAN) | 90 | #elif defined(CONFIG_SYS_BIG_ENDIAN) |
91 | return readb(addr + (1 << shift) - 1); | 91 | return readb(addr + (1 << shift) - 1); |
92 | #else | 92 | #else |
93 | return readb(addr); | 93 | return readb(addr); |
94 | #endif | 94 | #endif |
95 | } | 95 | } |
96 | 96 | ||
97 | static void ns16550_writeb(NS16550_t port, int offset, int value) | 97 | static void ns16550_writeb(NS16550_t port, int offset, int value) |
98 | { | 98 | { |
99 | struct ns16550_platdata *plat = port->plat; | 99 | struct ns16550_platdata *plat = port->plat; |
100 | unsigned char *addr; | 100 | unsigned char *addr; |
101 | 101 | ||
102 | offset *= 1 << plat->reg_shift; | 102 | offset *= 1 << plat->reg_shift; |
103 | addr = map_physmem(plat->base, 0, MAP_NOCACHE) + offset; | 103 | addr = map_physmem(plat->base, 0, MAP_NOCACHE) + offset; |
104 | /* | 104 | /* |
105 | * As far as we know it doesn't make sense to support selection of | 105 | * As far as we know it doesn't make sense to support selection of |
106 | * these options at run-time, so use the existing CONFIG options. | 106 | * these options at run-time, so use the existing CONFIG options. |
107 | */ | 107 | */ |
108 | serial_out_shift(addr, plat->reg_shift, value); | 108 | serial_out_shift(addr + plat->reg_offset, plat->reg_shift, value); |
109 | } | 109 | } |
110 | 110 | ||
111 | static int ns16550_readb(NS16550_t port, int offset) | 111 | static int ns16550_readb(NS16550_t port, int offset) |
112 | { | 112 | { |
113 | struct ns16550_platdata *plat = port->plat; | 113 | struct ns16550_platdata *plat = port->plat; |
114 | unsigned char *addr; | 114 | unsigned char *addr; |
115 | 115 | ||
116 | offset *= 1 << plat->reg_shift; | 116 | offset *= 1 << plat->reg_shift; |
117 | addr = map_physmem(plat->base, 0, MAP_NOCACHE) + offset; | 117 | addr = map_physmem(plat->base, 0, MAP_NOCACHE) + offset; |
118 | 118 | ||
119 | return serial_in_shift(addr, plat->reg_shift); | 119 | return serial_in_shift(addr + plat->reg_offset, plat->reg_shift); |
120 | } | 120 | } |
121 | 121 | ||
122 | /* We can clean these up once everything is moved to driver model */ | 122 | /* We can clean these up once everything is moved to driver model */ |
123 | #define serial_out(value, addr) \ | 123 | #define serial_out(value, addr) \ |
124 | ns16550_writeb(com_port, \ | 124 | ns16550_writeb(com_port, \ |
125 | (unsigned char *)addr - (unsigned char *)com_port, value) | 125 | (unsigned char *)addr - (unsigned char *)com_port, value) |
126 | #define serial_in(addr) \ | 126 | #define serial_in(addr) \ |
127 | ns16550_readb(com_port, \ | 127 | ns16550_readb(com_port, \ |
128 | (unsigned char *)addr - (unsigned char *)com_port) | 128 | (unsigned char *)addr - (unsigned char *)com_port) |
129 | #endif | 129 | #endif |
130 | 130 | ||
131 | static inline int calc_divisor(NS16550_t port, int clock, int baudrate) | 131 | static inline int calc_divisor(NS16550_t port, int clock, int baudrate) |
132 | { | 132 | { |
133 | const unsigned int mode_x_div = 16; | 133 | const unsigned int mode_x_div = 16; |
134 | 134 | ||
135 | return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); | 135 | return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); |
136 | } | 136 | } |
137 | 137 | ||
138 | int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) | 138 | int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) |
139 | { | 139 | { |
140 | #ifdef CONFIG_OMAP1510 | 140 | #ifdef CONFIG_OMAP1510 |
141 | /* If can't cleanly clock 115200 set div to 1 */ | 141 | /* If can't cleanly clock 115200 set div to 1 */ |
142 | if ((clock == 12000000) && (baudrate == 115200)) { | 142 | if ((clock == 12000000) && (baudrate == 115200)) { |
143 | port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */ | 143 | port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */ |
144 | return 1; /* return 1 for base divisor */ | 144 | return 1; /* return 1 for base divisor */ |
145 | } | 145 | } |
146 | port->osc_12m_sel = 0; /* clear if previsouly set */ | 146 | port->osc_12m_sel = 0; /* clear if previsouly set */ |
147 | #endif | 147 | #endif |
148 | 148 | ||
149 | return calc_divisor(port, clock, baudrate); | 149 | return calc_divisor(port, clock, baudrate); |
150 | } | 150 | } |
151 | 151 | ||
152 | static void NS16550_setbrg(NS16550_t com_port, int baud_divisor) | 152 | static void NS16550_setbrg(NS16550_t com_port, int baud_divisor) |
153 | { | 153 | { |
154 | serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr); | 154 | serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr); |
155 | serial_out(baud_divisor & 0xff, &com_port->dll); | 155 | serial_out(baud_divisor & 0xff, &com_port->dll); |
156 | serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); | 156 | serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); |
157 | serial_out(UART_LCRVAL, &com_port->lcr); | 157 | serial_out(UART_LCRVAL, &com_port->lcr); |
158 | } | 158 | } |
159 | 159 | ||
160 | void NS16550_init(NS16550_t com_port, int baud_divisor) | 160 | void NS16550_init(NS16550_t com_port, int baud_divisor) |
161 | { | 161 | { |
162 | #if (defined(CONFIG_SPL_BUILD) && \ | 162 | #if (defined(CONFIG_SPL_BUILD) && \ |
163 | (defined(CONFIG_OMAP34XX) || defined(CONFIG_OMAP44XX))) | 163 | (defined(CONFIG_OMAP34XX) || defined(CONFIG_OMAP44XX))) |
164 | /* | 164 | /* |
165 | * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode | 165 | * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode |
166 | * before SPL starts only THRE bit is set. We have to empty the | 166 | * before SPL starts only THRE bit is set. We have to empty the |
167 | * transmitter before initialization starts. | 167 | * transmitter before initialization starts. |
168 | */ | 168 | */ |
169 | if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE)) | 169 | if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE)) |
170 | == UART_LSR_THRE) { | 170 | == UART_LSR_THRE) { |
171 | if (baud_divisor != -1) | 171 | if (baud_divisor != -1) |
172 | NS16550_setbrg(com_port, baud_divisor); | 172 | NS16550_setbrg(com_port, baud_divisor); |
173 | serial_out(0, &com_port->mdr1); | 173 | serial_out(0, &com_port->mdr1); |
174 | } | 174 | } |
175 | #endif | 175 | #endif |
176 | 176 | ||
177 | while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT)) | 177 | while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT)) |
178 | ; | 178 | ; |
179 | 179 | ||
180 | serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); | 180 | serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); |
181 | #if defined(CONFIG_OMAP) || defined(CONFIG_AM33XX) || \ | 181 | #if defined(CONFIG_OMAP) || defined(CONFIG_AM33XX) || \ |
182 | defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) | 182 | defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) |
183 | serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/ | 183 | serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/ |
184 | #endif | 184 | #endif |
185 | serial_out(UART_MCRVAL, &com_port->mcr); | 185 | serial_out(UART_MCRVAL, &com_port->mcr); |
186 | serial_out(UART_FCRVAL, &com_port->fcr); | 186 | serial_out(UART_FCRVAL, &com_port->fcr); |
187 | if (baud_divisor != -1) | 187 | if (baud_divisor != -1) |
188 | NS16550_setbrg(com_port, baud_divisor); | 188 | NS16550_setbrg(com_port, baud_divisor); |
189 | #if defined(CONFIG_OMAP) || \ | 189 | #if defined(CONFIG_OMAP) || \ |
190 | defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \ | 190 | defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \ |
191 | defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) | 191 | defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) |
192 | 192 | ||
193 | /* /16 is proper to hit 115200 with 48MHz */ | 193 | /* /16 is proper to hit 115200 with 48MHz */ |
194 | serial_out(0, &com_port->mdr1); | 194 | serial_out(0, &com_port->mdr1); |
195 | #endif /* CONFIG_OMAP */ | 195 | #endif /* CONFIG_OMAP */ |
196 | #if defined(CONFIG_SOC_KEYSTONE) | 196 | #if defined(CONFIG_SOC_KEYSTONE) |
197 | serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC); | 197 | serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC); |
198 | #endif | 198 | #endif |
199 | } | 199 | } |
200 | 200 | ||
201 | #ifndef CONFIG_NS16550_MIN_FUNCTIONS | 201 | #ifndef CONFIG_NS16550_MIN_FUNCTIONS |
202 | void NS16550_reinit(NS16550_t com_port, int baud_divisor) | 202 | void NS16550_reinit(NS16550_t com_port, int baud_divisor) |
203 | { | 203 | { |
204 | serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); | 204 | serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); |
205 | NS16550_setbrg(com_port, 0); | 205 | NS16550_setbrg(com_port, 0); |
206 | serial_out(UART_MCRVAL, &com_port->mcr); | 206 | serial_out(UART_MCRVAL, &com_port->mcr); |
207 | serial_out(UART_FCRVAL, &com_port->fcr); | 207 | serial_out(UART_FCRVAL, &com_port->fcr); |
208 | NS16550_setbrg(com_port, baud_divisor); | 208 | NS16550_setbrg(com_port, baud_divisor); |
209 | } | 209 | } |
210 | #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ | 210 | #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ |
211 | 211 | ||
212 | void NS16550_putc(NS16550_t com_port, char c) | 212 | void NS16550_putc(NS16550_t com_port, char c) |
213 | { | 213 | { |
214 | while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0) | 214 | while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0) |
215 | ; | 215 | ; |
216 | serial_out(c, &com_port->thr); | 216 | serial_out(c, &com_port->thr); |
217 | 217 | ||
218 | /* | 218 | /* |
219 | * Call watchdog_reset() upon newline. This is done here in putc | 219 | * Call watchdog_reset() upon newline. This is done here in putc |
220 | * since the environment code uses a single puts() to print the complete | 220 | * since the environment code uses a single puts() to print the complete |
221 | * environment upon "printenv". So we can't put this watchdog call | 221 | * environment upon "printenv". So we can't put this watchdog call |
222 | * in puts(). | 222 | * in puts(). |
223 | */ | 223 | */ |
224 | if (c == '\n') | 224 | if (c == '\n') |
225 | WATCHDOG_RESET(); | 225 | WATCHDOG_RESET(); |
226 | } | 226 | } |
227 | 227 | ||
228 | #ifndef CONFIG_NS16550_MIN_FUNCTIONS | 228 | #ifndef CONFIG_NS16550_MIN_FUNCTIONS |
229 | char NS16550_getc(NS16550_t com_port) | 229 | char NS16550_getc(NS16550_t com_port) |
230 | { | 230 | { |
231 | while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { | 231 | while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { |
232 | #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY) | 232 | #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY) |
233 | extern void usbtty_poll(void); | 233 | extern void usbtty_poll(void); |
234 | usbtty_poll(); | 234 | usbtty_poll(); |
235 | #endif | 235 | #endif |
236 | WATCHDOG_RESET(); | 236 | WATCHDOG_RESET(); |
237 | } | 237 | } |
238 | return serial_in(&com_port->rbr); | 238 | return serial_in(&com_port->rbr); |
239 | } | 239 | } |
240 | 240 | ||
241 | int NS16550_tstc(NS16550_t com_port) | 241 | int NS16550_tstc(NS16550_t com_port) |
242 | { | 242 | { |
243 | return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0; | 243 | return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0; |
244 | } | 244 | } |
245 | 245 | ||
246 | #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ | 246 | #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ |
247 | 247 | ||
248 | #ifdef CONFIG_DEBUG_UART_NS16550 | 248 | #ifdef CONFIG_DEBUG_UART_NS16550 |
249 | 249 | ||
250 | #include <debug_uart.h> | 250 | #include <debug_uart.h> |
251 | 251 | ||
252 | #define serial_dout(reg, value) \ | 252 | #define serial_dout(reg, value) \ |
253 | serial_out_shift((char *)com_port + \ | 253 | serial_out_shift((char *)com_port + \ |
254 | ((char *)reg - (char *)com_port) * \ | 254 | ((char *)reg - (char *)com_port) * \ |
255 | (1 << CONFIG_DEBUG_UART_SHIFT), \ | 255 | (1 << CONFIG_DEBUG_UART_SHIFT), \ |
256 | CONFIG_DEBUG_UART_SHIFT, value) | 256 | CONFIG_DEBUG_UART_SHIFT, value) |
257 | #define serial_din(reg) \ | 257 | #define serial_din(reg) \ |
258 | serial_in_shift((char *)com_port + \ | 258 | serial_in_shift((char *)com_port + \ |
259 | ((char *)reg - (char *)com_port) * \ | 259 | ((char *)reg - (char *)com_port) * \ |
260 | (1 << CONFIG_DEBUG_UART_SHIFT), \ | 260 | (1 << CONFIG_DEBUG_UART_SHIFT), \ |
261 | CONFIG_DEBUG_UART_SHIFT) | 261 | CONFIG_DEBUG_UART_SHIFT) |
262 | 262 | ||
263 | static inline void _debug_uart_init(void) | 263 | static inline void _debug_uart_init(void) |
264 | { | 264 | { |
265 | struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; | 265 | struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; |
266 | int baud_divisor; | 266 | int baud_divisor; |
267 | 267 | ||
268 | /* | 268 | /* |
269 | * We copy the code from above because it is already horribly messy. | 269 | * We copy the code from above because it is already horribly messy. |
270 | * Trying to refactor to nicely remove the duplication doesn't seem | 270 | * Trying to refactor to nicely remove the duplication doesn't seem |
271 | * feasible. The better fix is to move all users of this driver to | 271 | * feasible. The better fix is to move all users of this driver to |
272 | * driver model. | 272 | * driver model. |
273 | */ | 273 | */ |
274 | baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, | 274 | baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, |
275 | CONFIG_BAUDRATE); | 275 | CONFIG_BAUDRATE); |
276 | serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER); | 276 | serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER); |
277 | serial_dout(&com_port->mcr, UART_MCRVAL); | 277 | serial_dout(&com_port->mcr, UART_MCRVAL); |
278 | serial_dout(&com_port->fcr, UART_FCRVAL); | 278 | serial_dout(&com_port->fcr, UART_FCRVAL); |
279 | 279 | ||
280 | serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); | 280 | serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); |
281 | serial_dout(&com_port->dll, baud_divisor & 0xff); | 281 | serial_dout(&com_port->dll, baud_divisor & 0xff); |
282 | serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff); | 282 | serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff); |
283 | serial_dout(&com_port->lcr, UART_LCRVAL); | 283 | serial_dout(&com_port->lcr, UART_LCRVAL); |
284 | } | 284 | } |
285 | 285 | ||
286 | static inline void _debug_uart_putc(int ch) | 286 | static inline void _debug_uart_putc(int ch) |
287 | { | 287 | { |
288 | struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; | 288 | struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; |
289 | 289 | ||
290 | while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) | 290 | while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) |
291 | ; | 291 | ; |
292 | serial_dout(&com_port->thr, ch); | 292 | serial_dout(&com_port->thr, ch); |
293 | } | 293 | } |
294 | 294 | ||
295 | DEBUG_UART_FUNCS | 295 | DEBUG_UART_FUNCS |
296 | 296 | ||
297 | #endif | 297 | #endif |
298 | 298 | ||
299 | #ifdef CONFIG_DM_SERIAL | 299 | #ifdef CONFIG_DM_SERIAL |
300 | static int ns16550_serial_putc(struct udevice *dev, const char ch) | 300 | static int ns16550_serial_putc(struct udevice *dev, const char ch) |
301 | { | 301 | { |
302 | struct NS16550 *const com_port = dev_get_priv(dev); | 302 | struct NS16550 *const com_port = dev_get_priv(dev); |
303 | 303 | ||
304 | if (!(serial_in(&com_port->lsr) & UART_LSR_THRE)) | 304 | if (!(serial_in(&com_port->lsr) & UART_LSR_THRE)) |
305 | return -EAGAIN; | 305 | return -EAGAIN; |
306 | serial_out(ch, &com_port->thr); | 306 | serial_out(ch, &com_port->thr); |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * Call watchdog_reset() upon newline. This is done here in putc | 309 | * Call watchdog_reset() upon newline. This is done here in putc |
310 | * since the environment code uses a single puts() to print the complete | 310 | * since the environment code uses a single puts() to print the complete |
311 | * environment upon "printenv". So we can't put this watchdog call | 311 | * environment upon "printenv". So we can't put this watchdog call |
312 | * in puts(). | 312 | * in puts(). |
313 | */ | 313 | */ |
314 | if (ch == '\n') | 314 | if (ch == '\n') |
315 | WATCHDOG_RESET(); | 315 | WATCHDOG_RESET(); |
316 | 316 | ||
317 | return 0; | 317 | return 0; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int ns16550_serial_pending(struct udevice *dev, bool input) | 320 | static int ns16550_serial_pending(struct udevice *dev, bool input) |
321 | { | 321 | { |
322 | struct NS16550 *const com_port = dev_get_priv(dev); | 322 | struct NS16550 *const com_port = dev_get_priv(dev); |
323 | 323 | ||
324 | if (input) | 324 | if (input) |
325 | return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0; | 325 | return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0; |
326 | else | 326 | else |
327 | return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1; | 327 | return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1; |
328 | } | 328 | } |
329 | 329 | ||
330 | static int ns16550_serial_getc(struct udevice *dev) | 330 | static int ns16550_serial_getc(struct udevice *dev) |
331 | { | 331 | { |
332 | struct NS16550 *const com_port = dev_get_priv(dev); | 332 | struct NS16550 *const com_port = dev_get_priv(dev); |
333 | 333 | ||
334 | if (!(serial_in(&com_port->lsr) & UART_LSR_DR)) | 334 | if (!(serial_in(&com_port->lsr) & UART_LSR_DR)) |
335 | return -EAGAIN; | 335 | return -EAGAIN; |
336 | 336 | ||
337 | return serial_in(&com_port->rbr); | 337 | return serial_in(&com_port->rbr); |
338 | } | 338 | } |
339 | 339 | ||
340 | static int ns16550_serial_setbrg(struct udevice *dev, int baudrate) | 340 | static int ns16550_serial_setbrg(struct udevice *dev, int baudrate) |
341 | { | 341 | { |
342 | struct NS16550 *const com_port = dev_get_priv(dev); | 342 | struct NS16550 *const com_port = dev_get_priv(dev); |
343 | struct ns16550_platdata *plat = com_port->plat; | 343 | struct ns16550_platdata *plat = com_port->plat; |
344 | int clock_divisor; | 344 | int clock_divisor; |
345 | 345 | ||
346 | clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate); | 346 | clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate); |
347 | 347 | ||
348 | NS16550_setbrg(com_port, clock_divisor); | 348 | NS16550_setbrg(com_port, clock_divisor); |
349 | 349 | ||
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | 352 | ||
353 | int ns16550_serial_probe(struct udevice *dev) | 353 | int ns16550_serial_probe(struct udevice *dev) |
354 | { | 354 | { |
355 | struct NS16550 *const com_port = dev_get_priv(dev); | 355 | struct NS16550 *const com_port = dev_get_priv(dev); |
356 | 356 | ||
357 | com_port->plat = dev_get_platdata(dev); | 357 | com_port->plat = dev_get_platdata(dev); |
358 | NS16550_init(com_port, -1); | 358 | NS16550_init(com_port, -1); |
359 | 359 | ||
360 | return 0; | 360 | return 0; |
361 | } | 361 | } |
362 | 362 | ||
363 | #if CONFIG_IS_ENABLED(OF_CONTROL) | 363 | #if CONFIG_IS_ENABLED(OF_CONTROL) |
364 | int ns16550_serial_ofdata_to_platdata(struct udevice *dev) | 364 | int ns16550_serial_ofdata_to_platdata(struct udevice *dev) |
365 | { | 365 | { |
366 | struct ns16550_platdata *plat = dev->platdata; | 366 | struct ns16550_platdata *plat = dev->platdata; |
367 | fdt_addr_t addr; | 367 | fdt_addr_t addr; |
368 | 368 | ||
369 | /* try Processor Local Bus device first */ | 369 | /* try Processor Local Bus device first */ |
370 | addr = dev_get_addr(dev); | 370 | addr = dev_get_addr(dev); |
371 | #if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI) | 371 | #if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI) |
372 | if (addr == FDT_ADDR_T_NONE) { | 372 | if (addr == FDT_ADDR_T_NONE) { |
373 | /* then try pci device */ | 373 | /* then try pci device */ |
374 | struct fdt_pci_addr pci_addr; | 374 | struct fdt_pci_addr pci_addr; |
375 | u32 bar; | 375 | u32 bar; |
376 | int ret; | 376 | int ret; |
377 | 377 | ||
378 | /* we prefer to use a memory-mapped register */ | 378 | /* we prefer to use a memory-mapped register */ |
379 | ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, | 379 | ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, |
380 | FDT_PCI_SPACE_MEM32, "reg", | 380 | FDT_PCI_SPACE_MEM32, "reg", |
381 | &pci_addr); | 381 | &pci_addr); |
382 | if (ret) { | 382 | if (ret) { |
383 | /* try if there is any i/o-mapped register */ | 383 | /* try if there is any i/o-mapped register */ |
384 | ret = fdtdec_get_pci_addr(gd->fdt_blob, | 384 | ret = fdtdec_get_pci_addr(gd->fdt_blob, |
385 | dev->of_offset, | 385 | dev->of_offset, |
386 | FDT_PCI_SPACE_IO, | 386 | FDT_PCI_SPACE_IO, |
387 | "reg", &pci_addr); | 387 | "reg", &pci_addr); |
388 | if (ret) | 388 | if (ret) |
389 | return ret; | 389 | return ret; |
390 | } | 390 | } |
391 | 391 | ||
392 | ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar); | 392 | ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar); |
393 | if (ret) | 393 | if (ret) |
394 | return ret; | 394 | return ret; |
395 | 395 | ||
396 | addr = bar; | 396 | addr = bar; |
397 | } | 397 | } |
398 | #endif | 398 | #endif |
399 | 399 | ||
400 | if (addr == FDT_ADDR_T_NONE) | 400 | if (addr == FDT_ADDR_T_NONE) |
401 | return -EINVAL; | 401 | return -EINVAL; |
402 | 402 | ||
403 | plat->base = addr; | 403 | plat->base = addr; |
404 | plat->reg_offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, | ||
405 | "reg-offset", 0); | ||
404 | plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset, | 406 | plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset, |
405 | "reg-shift", 0); | 407 | "reg-shift", 0); |
406 | plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, | 408 | plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, |
407 | "clock-frequency", | 409 | "clock-frequency", |
408 | CONFIG_SYS_NS16550_CLK); | 410 | CONFIG_SYS_NS16550_CLK); |
409 | if (!plat->clock) { | 411 | if (!plat->clock) { |
410 | debug("ns16550 clock not defined\n"); | 412 | debug("ns16550 clock not defined\n"); |
411 | return -EINVAL; | 413 | return -EINVAL; |
412 | } | 414 | } |
413 | 415 | ||
414 | return 0; | 416 | return 0; |
415 | } | 417 | } |
416 | #endif | 418 | #endif |
417 | 419 | ||
418 | const struct dm_serial_ops ns16550_serial_ops = { | 420 | const struct dm_serial_ops ns16550_serial_ops = { |
419 | .putc = ns16550_serial_putc, | 421 | .putc = ns16550_serial_putc, |
420 | .pending = ns16550_serial_pending, | 422 | .pending = ns16550_serial_pending, |
421 | .getc = ns16550_serial_getc, | 423 | .getc = ns16550_serial_getc, |
422 | .setbrg = ns16550_serial_setbrg, | 424 | .setbrg = ns16550_serial_setbrg, |
423 | }; | 425 | }; |
424 | 426 | ||
425 | #if CONFIG_IS_ENABLED(OF_CONTROL) | 427 | #if CONFIG_IS_ENABLED(OF_CONTROL) |
426 | /* | 428 | /* |
427 | * Please consider existing compatible strings before adding a new | 429 | * Please consider existing compatible strings before adding a new |
428 | * one to keep this table compact. Or you may add a generic "ns16550" | 430 | * one to keep this table compact. Or you may add a generic "ns16550" |
429 | * compatible string to your dts. | 431 | * compatible string to your dts. |
430 | */ | 432 | */ |
431 | static const struct udevice_id ns16550_serial_ids[] = { | 433 | static const struct udevice_id ns16550_serial_ids[] = { |
432 | { .compatible = "ns16550" }, | 434 | { .compatible = "ns16550" }, |
433 | { .compatible = "ns16550a" }, | 435 | { .compatible = "ns16550a" }, |
434 | { .compatible = "nvidia,tegra20-uart" }, | 436 | { .compatible = "nvidia,tegra20-uart" }, |
435 | { .compatible = "snps,dw-apb-uart" }, | 437 | { .compatible = "snps,dw-apb-uart" }, |
436 | { .compatible = "ti,omap2-uart" }, | 438 | { .compatible = "ti,omap2-uart" }, |
437 | { .compatible = "ti,omap3-uart" }, | 439 | { .compatible = "ti,omap3-uart" }, |
438 | { .compatible = "ti,omap4-uart" }, | 440 | { .compatible = "ti,omap4-uart" }, |
439 | { .compatible = "ti,am3352-uart" }, | 441 | { .compatible = "ti,am3352-uart" }, |
440 | { .compatible = "ti,am4372-uart" }, | 442 | { .compatible = "ti,am4372-uart" }, |
441 | { .compatible = "ti,dra742-uart" }, | 443 | { .compatible = "ti,dra742-uart" }, |
442 | {} | 444 | {} |
443 | }; | 445 | }; |
444 | #endif | 446 | #endif |
445 | 447 | ||
446 | #if CONFIG_IS_ENABLED(SERIAL_PRESENT) | 448 | #if CONFIG_IS_ENABLED(SERIAL_PRESENT) |
447 | U_BOOT_DRIVER(ns16550_serial) = { | 449 | U_BOOT_DRIVER(ns16550_serial) = { |
448 | .name = "ns16550_serial", | 450 | .name = "ns16550_serial", |
449 | .id = UCLASS_SERIAL, | 451 | .id = UCLASS_SERIAL, |
450 | #if CONFIG_IS_ENABLED(OF_CONTROL) | 452 | #if CONFIG_IS_ENABLED(OF_CONTROL) |
451 | .of_match = ns16550_serial_ids, | 453 | .of_match = ns16550_serial_ids, |
452 | .ofdata_to_platdata = ns16550_serial_ofdata_to_platdata, | 454 | .ofdata_to_platdata = ns16550_serial_ofdata_to_platdata, |
453 | .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), | 455 | .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), |
454 | #endif | 456 | #endif |
455 | .priv_auto_alloc_size = sizeof(struct NS16550), | 457 | .priv_auto_alloc_size = sizeof(struct NS16550), |
456 | .probe = ns16550_serial_probe, | 458 | .probe = ns16550_serial_probe, |
457 | .ops = &ns16550_serial_ops, | 459 | .ops = &ns16550_serial_ops, |
458 | .flags = DM_FLAG_PRE_RELOC, | 460 | .flags = DM_FLAG_PRE_RELOC, |
459 | }; | 461 | }; |
460 | #endif | 462 | #endif |
461 | #endif /* CONFIG_DM_SERIAL */ | 463 | #endif /* CONFIG_DM_SERIAL */ |
462 | 464 |
1 | /* | 1 | /* |
2 | * NS16550 Serial Port | 2 | * NS16550 Serial Port |
3 | * originally from linux source (arch/powerpc/boot/ns16550.h) | 3 | * originally from linux source (arch/powerpc/boot/ns16550.h) |
4 | * | 4 | * |
5 | * Cleanup and unification | 5 | * Cleanup and unification |
6 | * (C) 2009 by Detlev Zundel, DENX Software Engineering GmbH | 6 | * (C) 2009 by Detlev Zundel, DENX Software Engineering GmbH |
7 | * | 7 | * |
8 | * modified slightly to | 8 | * modified slightly to |
9 | * have addresses as offsets from CONFIG_SYS_ISA_BASE | 9 | * have addresses as offsets from CONFIG_SYS_ISA_BASE |
10 | * added a few more definitions | 10 | * added a few more definitions |
11 | * added prototypes for ns16550.c | 11 | * added prototypes for ns16550.c |
12 | * reduced no of com ports to 2 | 12 | * reduced no of com ports to 2 |
13 | * modifications (c) Rob Taylor, Flying Pig Systems. 2000. | 13 | * modifications (c) Rob Taylor, Flying Pig Systems. 2000. |
14 | * | 14 | * |
15 | * added support for port on 64-bit bus | 15 | * added support for port on 64-bit bus |
16 | * by Richard Danter (richard.danter@windriver.com), (C) 2005 Wind River Systems | 16 | * by Richard Danter (richard.danter@windriver.com), (C) 2005 Wind River Systems |
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * Note that the following macro magic uses the fact that the compiler | 20 | * Note that the following macro magic uses the fact that the compiler |
21 | * will not allocate storage for arrays of size 0 | 21 | * will not allocate storage for arrays of size 0 |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | 25 | ||
26 | #ifdef CONFIG_DM_SERIAL | 26 | #ifdef CONFIG_DM_SERIAL |
27 | /* | 27 | /* |
28 | * For driver model we always use one byte per register, and sort out the | 28 | * For driver model we always use one byte per register, and sort out the |
29 | * differences in the driver | 29 | * differences in the driver |
30 | */ | 30 | */ |
31 | #define CONFIG_SYS_NS16550_REG_SIZE (-1) | 31 | #define CONFIG_SYS_NS16550_REG_SIZE (-1) |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | #if !defined(CONFIG_SYS_NS16550_REG_SIZE) || (CONFIG_SYS_NS16550_REG_SIZE == 0) | 34 | #if !defined(CONFIG_SYS_NS16550_REG_SIZE) || (CONFIG_SYS_NS16550_REG_SIZE == 0) |
35 | #error "Please define NS16550 registers size." | 35 | #error "Please define NS16550 registers size." |
36 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_DM_SERIAL) | 36 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_DM_SERIAL) |
37 | #define UART_REG(x) u32 x | 37 | #define UART_REG(x) u32 x |
38 | #elif (CONFIG_SYS_NS16550_REG_SIZE > 0) | 38 | #elif (CONFIG_SYS_NS16550_REG_SIZE > 0) |
39 | #define UART_REG(x) \ | 39 | #define UART_REG(x) \ |
40 | unsigned char prepad_##x[CONFIG_SYS_NS16550_REG_SIZE - 1]; \ | 40 | unsigned char prepad_##x[CONFIG_SYS_NS16550_REG_SIZE - 1]; \ |
41 | unsigned char x; | 41 | unsigned char x; |
42 | #elif (CONFIG_SYS_NS16550_REG_SIZE < 0) | 42 | #elif (CONFIG_SYS_NS16550_REG_SIZE < 0) |
43 | #define UART_REG(x) \ | 43 | #define UART_REG(x) \ |
44 | unsigned char x; \ | 44 | unsigned char x; \ |
45 | unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1]; | 45 | unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1]; |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * struct ns16550_platdata - information about a NS16550 port | 49 | * struct ns16550_platdata - information about a NS16550 port |
50 | * | 50 | * |
51 | * @base: Base register address | 51 | * @base: Base register address |
52 | * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) | 52 | * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) |
53 | * @clock: UART base clock speed in Hz | 53 | * @clock: UART base clock speed in Hz |
54 | */ | 54 | */ |
55 | struct ns16550_platdata { | 55 | struct ns16550_platdata { |
56 | unsigned long base; | 56 | unsigned long base; |
57 | int reg_offset; | ||
57 | int reg_shift; | 58 | int reg_shift; |
58 | int clock; | 59 | int clock; |
59 | }; | 60 | }; |
60 | 61 | ||
61 | struct udevice; | 62 | struct udevice; |
62 | 63 | ||
63 | struct NS16550 { | 64 | struct NS16550 { |
64 | UART_REG(rbr); /* 0 */ | 65 | UART_REG(rbr); /* 0 */ |
65 | UART_REG(ier); /* 1 */ | 66 | UART_REG(ier); /* 1 */ |
66 | UART_REG(fcr); /* 2 */ | 67 | UART_REG(fcr); /* 2 */ |
67 | UART_REG(lcr); /* 3 */ | 68 | UART_REG(lcr); /* 3 */ |
68 | UART_REG(mcr); /* 4 */ | 69 | UART_REG(mcr); /* 4 */ |
69 | UART_REG(lsr); /* 5 */ | 70 | UART_REG(lsr); /* 5 */ |
70 | UART_REG(msr); /* 6 */ | 71 | UART_REG(msr); /* 6 */ |
71 | UART_REG(spr); /* 7 */ | 72 | UART_REG(spr); /* 7 */ |
72 | #ifdef CONFIG_SOC_DA8XX | 73 | #ifdef CONFIG_SOC_DA8XX |
73 | UART_REG(reg8); /* 8 */ | 74 | UART_REG(reg8); /* 8 */ |
74 | UART_REG(reg9); /* 9 */ | 75 | UART_REG(reg9); /* 9 */ |
75 | UART_REG(revid1); /* A */ | 76 | UART_REG(revid1); /* A */ |
76 | UART_REG(revid2); /* B */ | 77 | UART_REG(revid2); /* B */ |
77 | UART_REG(pwr_mgmt); /* C */ | 78 | UART_REG(pwr_mgmt); /* C */ |
78 | UART_REG(mdr1); /* D */ | 79 | UART_REG(mdr1); /* D */ |
79 | #else | 80 | #else |
80 | UART_REG(mdr1); /* 8 */ | 81 | UART_REG(mdr1); /* 8 */ |
81 | UART_REG(reg9); /* 9 */ | 82 | UART_REG(reg9); /* 9 */ |
82 | UART_REG(regA); /* A */ | 83 | UART_REG(regA); /* A */ |
83 | UART_REG(regB); /* B */ | 84 | UART_REG(regB); /* B */ |
84 | UART_REG(regC); /* C */ | 85 | UART_REG(regC); /* C */ |
85 | UART_REG(regD); /* D */ | 86 | UART_REG(regD); /* D */ |
86 | UART_REG(regE); /* E */ | 87 | UART_REG(regE); /* E */ |
87 | UART_REG(uasr); /* F */ | 88 | UART_REG(uasr); /* F */ |
88 | UART_REG(scr); /* 10*/ | 89 | UART_REG(scr); /* 10*/ |
89 | UART_REG(ssr); /* 11*/ | 90 | UART_REG(ssr); /* 11*/ |
90 | #endif | 91 | #endif |
91 | #ifdef CONFIG_DM_SERIAL | 92 | #ifdef CONFIG_DM_SERIAL |
92 | struct ns16550_platdata *plat; | 93 | struct ns16550_platdata *plat; |
93 | #endif | 94 | #endif |
94 | }; | 95 | }; |
95 | 96 | ||
96 | #define thr rbr | 97 | #define thr rbr |
97 | #define iir fcr | 98 | #define iir fcr |
98 | #define dll rbr | 99 | #define dll rbr |
99 | #define dlm ier | 100 | #define dlm ier |
100 | 101 | ||
101 | typedef struct NS16550 *NS16550_t; | 102 | typedef struct NS16550 *NS16550_t; |
102 | 103 | ||
103 | /* | 104 | /* |
104 | * These are the definitions for the FIFO Control Register | 105 | * These are the definitions for the FIFO Control Register |
105 | */ | 106 | */ |
106 | #define UART_FCR_FIFO_EN 0x01 /* Fifo enable */ | 107 | #define UART_FCR_FIFO_EN 0x01 /* Fifo enable */ |
107 | #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ | 108 | #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ |
108 | #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ | 109 | #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ |
109 | #define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ | 110 | #define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ |
110 | #define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ | 111 | #define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ |
111 | #define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ | 112 | #define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ |
112 | #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ | 113 | #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ |
113 | #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ | 114 | #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ |
114 | #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ | 115 | #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ |
115 | 116 | ||
116 | #define UART_FCR_RXSR 0x02 /* Receiver soft reset */ | 117 | #define UART_FCR_RXSR 0x02 /* Receiver soft reset */ |
117 | #define UART_FCR_TXSR 0x04 /* Transmitter soft reset */ | 118 | #define UART_FCR_TXSR 0x04 /* Transmitter soft reset */ |
118 | 119 | ||
119 | /* | 120 | /* |
120 | * These are the definitions for the Modem Control Register | 121 | * These are the definitions for the Modem Control Register |
121 | */ | 122 | */ |
122 | #define UART_MCR_DTR 0x01 /* DTR */ | 123 | #define UART_MCR_DTR 0x01 /* DTR */ |
123 | #define UART_MCR_RTS 0x02 /* RTS */ | 124 | #define UART_MCR_RTS 0x02 /* RTS */ |
124 | #define UART_MCR_OUT1 0x04 /* Out 1 */ | 125 | #define UART_MCR_OUT1 0x04 /* Out 1 */ |
125 | #define UART_MCR_OUT2 0x08 /* Out 2 */ | 126 | #define UART_MCR_OUT2 0x08 /* Out 2 */ |
126 | #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ | 127 | #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ |
127 | #define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS */ | 128 | #define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS */ |
128 | 129 | ||
129 | #define UART_MCR_DMA_EN 0x04 | 130 | #define UART_MCR_DMA_EN 0x04 |
130 | #define UART_MCR_TX_DFR 0x08 | 131 | #define UART_MCR_TX_DFR 0x08 |
131 | 132 | ||
132 | /* | 133 | /* |
133 | * These are the definitions for the Line Control Register | 134 | * These are the definitions for the Line Control Register |
134 | * | 135 | * |
135 | * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting | 136 | * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting |
136 | * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. | 137 | * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. |
137 | */ | 138 | */ |
138 | #define UART_LCR_WLS_MSK 0x03 /* character length select mask */ | 139 | #define UART_LCR_WLS_MSK 0x03 /* character length select mask */ |
139 | #define UART_LCR_WLS_5 0x00 /* 5 bit character length */ | 140 | #define UART_LCR_WLS_5 0x00 /* 5 bit character length */ |
140 | #define UART_LCR_WLS_6 0x01 /* 6 bit character length */ | 141 | #define UART_LCR_WLS_6 0x01 /* 6 bit character length */ |
141 | #define UART_LCR_WLS_7 0x02 /* 7 bit character length */ | 142 | #define UART_LCR_WLS_7 0x02 /* 7 bit character length */ |
142 | #define UART_LCR_WLS_8 0x03 /* 8 bit character length */ | 143 | #define UART_LCR_WLS_8 0x03 /* 8 bit character length */ |
143 | #define UART_LCR_STB 0x04 /* # stop Bits, off=1, on=1.5 or 2) */ | 144 | #define UART_LCR_STB 0x04 /* # stop Bits, off=1, on=1.5 or 2) */ |
144 | #define UART_LCR_PEN 0x08 /* Parity eneble */ | 145 | #define UART_LCR_PEN 0x08 /* Parity eneble */ |
145 | #define UART_LCR_EPS 0x10 /* Even Parity Select */ | 146 | #define UART_LCR_EPS 0x10 /* Even Parity Select */ |
146 | #define UART_LCR_STKP 0x20 /* Stick Parity */ | 147 | #define UART_LCR_STKP 0x20 /* Stick Parity */ |
147 | #define UART_LCR_SBRK 0x40 /* Set Break */ | 148 | #define UART_LCR_SBRK 0x40 /* Set Break */ |
148 | #define UART_LCR_BKSE 0x80 /* Bank select enable */ | 149 | #define UART_LCR_BKSE 0x80 /* Bank select enable */ |
149 | #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ | 150 | #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ |
150 | 151 | ||
151 | /* | 152 | /* |
152 | * These are the definitions for the Line Status Register | 153 | * These are the definitions for the Line Status Register |
153 | */ | 154 | */ |
154 | #define UART_LSR_DR 0x01 /* Data ready */ | 155 | #define UART_LSR_DR 0x01 /* Data ready */ |
155 | #define UART_LSR_OE 0x02 /* Overrun */ | 156 | #define UART_LSR_OE 0x02 /* Overrun */ |
156 | #define UART_LSR_PE 0x04 /* Parity error */ | 157 | #define UART_LSR_PE 0x04 /* Parity error */ |
157 | #define UART_LSR_FE 0x08 /* Framing error */ | 158 | #define UART_LSR_FE 0x08 /* Framing error */ |
158 | #define UART_LSR_BI 0x10 /* Break */ | 159 | #define UART_LSR_BI 0x10 /* Break */ |
159 | #define UART_LSR_THRE 0x20 /* Xmit holding register empty */ | 160 | #define UART_LSR_THRE 0x20 /* Xmit holding register empty */ |
160 | #define UART_LSR_TEMT 0x40 /* Xmitter empty */ | 161 | #define UART_LSR_TEMT 0x40 /* Xmitter empty */ |
161 | #define UART_LSR_ERR 0x80 /* Error */ | 162 | #define UART_LSR_ERR 0x80 /* Error */ |
162 | 163 | ||
163 | #define UART_MSR_DCD 0x80 /* Data Carrier Detect */ | 164 | #define UART_MSR_DCD 0x80 /* Data Carrier Detect */ |
164 | #define UART_MSR_RI 0x40 /* Ring Indicator */ | 165 | #define UART_MSR_RI 0x40 /* Ring Indicator */ |
165 | #define UART_MSR_DSR 0x20 /* Data Set Ready */ | 166 | #define UART_MSR_DSR 0x20 /* Data Set Ready */ |
166 | #define UART_MSR_CTS 0x10 /* Clear to Send */ | 167 | #define UART_MSR_CTS 0x10 /* Clear to Send */ |
167 | #define UART_MSR_DDCD 0x08 /* Delta DCD */ | 168 | #define UART_MSR_DDCD 0x08 /* Delta DCD */ |
168 | #define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ | 169 | #define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ |
169 | #define UART_MSR_DDSR 0x02 /* Delta DSR */ | 170 | #define UART_MSR_DDSR 0x02 /* Delta DSR */ |
170 | #define UART_MSR_DCTS 0x01 /* Delta CTS */ | 171 | #define UART_MSR_DCTS 0x01 /* Delta CTS */ |
171 | 172 | ||
172 | /* | 173 | /* |
173 | * These are the definitions for the Interrupt Identification Register | 174 | * These are the definitions for the Interrupt Identification Register |
174 | */ | 175 | */ |
175 | #define UART_IIR_NO_INT 0x01 /* No interrupts pending */ | 176 | #define UART_IIR_NO_INT 0x01 /* No interrupts pending */ |
176 | #define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ | 177 | #define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ |
177 | 178 | ||
178 | #define UART_IIR_MSI 0x00 /* Modem status interrupt */ | 179 | #define UART_IIR_MSI 0x00 /* Modem status interrupt */ |
179 | #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ | 180 | #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ |
180 | #define UART_IIR_RDI 0x04 /* Receiver data interrupt */ | 181 | #define UART_IIR_RDI 0x04 /* Receiver data interrupt */ |
181 | #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ | 182 | #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ |
182 | 183 | ||
183 | /* | 184 | /* |
184 | * These are the definitions for the Interrupt Enable Register | 185 | * These are the definitions for the Interrupt Enable Register |
185 | */ | 186 | */ |
186 | #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ | 187 | #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ |
187 | #define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ | 188 | #define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ |
188 | #define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ | 189 | #define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ |
189 | #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ | 190 | #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ |
190 | 191 | ||
191 | /* useful defaults for LCR */ | 192 | /* useful defaults for LCR */ |
192 | #define UART_LCR_8N1 0x03 | 193 | #define UART_LCR_8N1 0x03 |
193 | 194 | ||
194 | void NS16550_init(NS16550_t com_port, int baud_divisor); | 195 | void NS16550_init(NS16550_t com_port, int baud_divisor); |
195 | void NS16550_putc(NS16550_t com_port, char c); | 196 | void NS16550_putc(NS16550_t com_port, char c); |
196 | char NS16550_getc(NS16550_t com_port); | 197 | char NS16550_getc(NS16550_t com_port); |
197 | int NS16550_tstc(NS16550_t com_port); | 198 | int NS16550_tstc(NS16550_t com_port); |
198 | void NS16550_reinit(NS16550_t com_port, int baud_divisor); | 199 | void NS16550_reinit(NS16550_t com_port, int baud_divisor); |
199 | 200 | ||
200 | /** | 201 | /** |
201 | * ns16550_calc_divisor() - calculate the divisor given clock and baud rate | 202 | * ns16550_calc_divisor() - calculate the divisor given clock and baud rate |
202 | * | 203 | * |
203 | * Given the UART input clock and required baudrate, calculate the divisor | 204 | * Given the UART input clock and required baudrate, calculate the divisor |
204 | * that should be used. | 205 | * that should be used. |
205 | * | 206 | * |
206 | * @port: UART port | 207 | * @port: UART port |
207 | * @clock: UART input clock speed in Hz | 208 | * @clock: UART input clock speed in Hz |
208 | * @baudrate: Required baud rate | 209 | * @baudrate: Required baud rate |
209 | * @return baud rate divisor that should be used | 210 | * @return baud rate divisor that should be used |
210 | */ | 211 | */ |
211 | int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate); | 212 | int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate); |
212 | 213 | ||
213 | /** | 214 | /** |
214 | * ns16550_serial_ofdata_to_platdata() - convert DT to platform data | 215 | * ns16550_serial_ofdata_to_platdata() - convert DT to platform data |
215 | * | 216 | * |
216 | * Decode a device tree node for an ns16550 device. This includes the | 217 | * Decode a device tree node for an ns16550 device. This includes the |
217 | * register base address and register shift properties. The caller must set | 218 | * register base address and register shift properties. The caller must set |
218 | * up the clock frequency. | 219 | * up the clock frequency. |
219 | * | 220 | * |
220 | * @dev: dev to decode platform data for | 221 | * @dev: dev to decode platform data for |
221 | * @return: 0 if OK, -EINVAL on error | 222 | * @return: 0 if OK, -EINVAL on error |
222 | */ | 223 | */ |
223 | int ns16550_serial_ofdata_to_platdata(struct udevice *dev); | 224 | int ns16550_serial_ofdata_to_platdata(struct udevice *dev); |
224 | 225 | ||
225 | /** | 226 | /** |
226 | * ns16550_serial_probe() - probe a serial port | 227 | * ns16550_serial_probe() - probe a serial port |
227 | * | 228 | * |
228 | * This sets up the serial port ready for use, except for the baud rate | 229 | * This sets up the serial port ready for use, except for the baud rate |
229 | * @return 0, or -ve on error | 230 | * @return 0, or -ve on error |
230 | */ | 231 | */ |
231 | int ns16550_serial_probe(struct udevice *dev); | 232 | int ns16550_serial_probe(struct udevice *dev); |
232 | 233 | ||
233 | /** | 234 | /** |
234 | * struct ns16550_serial_ops - ns16550 serial operations | 235 | * struct ns16550_serial_ops - ns16550 serial operations |
235 | * | 236 | * |
236 | * These should be used by the client driver for the driver's 'ops' member | 237 | * These should be used by the client driver for the driver's 'ops' member |
237 | */ | 238 | */ |
238 | extern const struct dm_serial_ops ns16550_serial_ops; | 239 | extern const struct dm_serial_ops ns16550_serial_ops; |
239 | 240 |
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c
-
mentioned in commit e5e88c