1/* Unit-specific 8250 serial ports
2 *
3 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#ifndef _ASM_UNIT_SERIAL_H
13#define _ASM_UNIT_SERIAL_H
14
15#include <asm/cpu-regs.h>
16#include <proc/irq.h>
17#include <unit/fpga-regs.h>
18#include <linux/serial_reg.h>
19
20#define SERIAL_PORT0_BASE_ADDRESS	0xA8200000
21
22#define SERIAL_IRQ	XIRQ1	/* single serial (TL16C550C)	(Lo) */
23
24/*
25 * The ASB2364 has an 12.288 MHz clock
26 * for your UART.
27 *
28 * It'd be nice if someone built a serial card with a 24.576 MHz
29 * clock, since the 16550A is capable of handling a top speed of 1.5
30 * megabits/second; but this requires the faster clock.
31 */
32#define BASE_BAUD (12288000 / 16)
33
34/*
35 * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
36 */
37#ifndef CONFIG_GDBSTUB_ON_TTYSx
38
39#define SERIAL_PORT_DFNS						\
40	{								\
41		.baud_base	= BASE_BAUD,				\
42		.irq		= SERIAL_IRQ,				\
43		.flags		= STD_COM_FLAGS,			\
44		.iomem_base	= (u8 *) SERIAL_PORT0_BASE_ADDRESS,	\
45		.iomem_reg_shift = 1,					\
46		.io_type	= SERIAL_IO_MEM,			\
47	},
48
49#ifndef __ASSEMBLY__
50
51static inline void __debug_to_serial(const char *p, int n)
52{
53}
54
55#endif /* !__ASSEMBLY__ */
56
57#else /* CONFIG_GDBSTUB_ON_TTYSx */
58
59#define SERIAL_PORT_DFNS /* stolen by gdb-stub */
60
61#if defined(CONFIG_GDBSTUB_ON_TTYS0)
62#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 2, u8)
63#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 2, u8)
64#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 2, u8)
65#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 2, u8)
66#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
67#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 2, u8)
68#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 2, u8)
69#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 2, u8)
70#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 2, u8)
71#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 2, u8)
72#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 2, u8)
73#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 2, u8)
74#define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
75
76#elif defined(CONFIG_GDBSTUB_ON_TTYS1)
77#error The ASB2364 does not have a /dev/ttyS1
78#endif
79
80#ifndef __ASSEMBLY__
81
82static inline void __debug_to_serial(const char *p, int n)
83{
84	char ch;
85
86#define LSR_WAIT_FOR(STATE)	\
87	do {} while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE))
88#define FLOWCTL_QUERY(LINE)	\
89	({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; })
90#define FLOWCTL_WAIT_FOR(LINE)	\
91	do {} while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE))
92#define FLOWCTL_CLEAR(LINE)	\
93	do { GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE; } while (0)
94#define FLOWCTL_SET(LINE)	\
95	do { GDBPORT_SERIAL_MCR |= UART_MCR_##LINE; } while (0)
96
97	FLOWCTL_SET(DTR);
98
99	for (; n > 0; n--) {
100		LSR_WAIT_FOR(THRE);
101		FLOWCTL_WAIT_FOR(CTS);
102
103		ch = *p++;
104		if (ch == 0x0a) {
105			GDBPORT_SERIAL_TX = 0x0d;
106			LSR_WAIT_FOR(THRE);
107			FLOWCTL_WAIT_FOR(CTS);
108		}
109		GDBPORT_SERIAL_TX = ch;
110	}
111
112	FLOWCTL_CLEAR(DTR);
113}
114
115#endif /* !__ASSEMBLY__ */
116
117#endif /* CONFIG_GDBSTUB_ON_TTYSx */
118
119#define SERIAL_INITIALIZE					\
120do {								\
121	/* release reset */					\
122	ASB2364_FPGA_REG_RESET_UART = 0x0001;			\
123	SyncExBus();						\
124} while (0)
125
126#define SERIAL_CHECK_INTERRUPT					\
127do {								\
128	if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) {	\
129		return IRQ_NONE;				\
130	}							\
131} while (0)
132
133#define SERIAL_CLEAR_INTERRUPT					\
134do {								\
135	ASB2364_FPGA_REG_IRQ_UART = 0x0001;			\
136	SyncExBus();						\
137} while (0)
138
139#define SERIAL_SET_INT_MASK					\
140do {								\
141	ASB2364_FPGA_REG_MASK_UART = 0x0001;			\
142	SyncExBus();						\
143} while (0)
144
145#define SERIAL_CLEAR_INT_MASK					\
146do {								\
147	ASB2364_FPGA_REG_MASK_UART = 0x0000;			\
148	SyncExBus();						\
149} while (0)
150
151#endif /* _ASM_UNIT_SERIAL_H */
152