1/*
2 * BK Id: %F% %I% %G% %U% %#%
3 */
4
5
6/* Minimal serial functions needed to send messages out the serial
7 * port on the MBX console.
8 *
9 * The MBX uxes SMC1 for the serial port.  We reset the port and use
10 * only the first BD that EPPC-Bug set up as a character FIFO.
11 *
12 * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
13 * use COM1 instead of SMC1 as the console port.  This kinda sucks
14 * for the rest of the kernel, so here we force the use of SMC1 again.
15 */
16#include <linux/config.h>
17#include <linux/types.h>
18#include <asm/uaccess.h>
19#include <asm/mpc8xx.h>
20#include <asm/commproc.h>
21
22#ifdef CONFIG_MBX
23#define MBX_CSR1	((volatile u_char *)0xfa100000)
24#define CSR1_COMEN	(u_char)0x02
25#endif
26
27#ifdef TQM_SMC2_CONSOLE
28#define PROFF_CONS	PROFF_SMC2
29#define CPM_CR_CH_CONS	CPM_CR_CH_SMC2
30#define SMC_INDEX	1
31static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport);
32#else
33#define PROFF_CONS	PROFF_SMC1
34#define CPM_CR_CH_CONS	CPM_CR_CH_SMC1
35#define SMC_INDEX	0
36#endif
37
38static cpm8xx_t	*cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
39
40unsigned long
41serial_init(int ignored, bd_t *bd)
42{
43	volatile smc_t		*sp;
44	volatile smc_uart_t	*up;
45	volatile cbd_t	*tbdf, *rbdf;
46	volatile cpm8xx_t	*cp;
47	uint	dpaddr, memaddr;
48#ifndef CONFIG_MBX
49	uint	ui;
50#endif
51
52	cp = cpmp;
53	sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]);
54	up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS];
55
56	/* Disable transmitter/receiver.
57	*/
58	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
59
60#ifdef CONFIG_FADS
61	/* Enable SMC1/2 transceivers.
62	*/
63	*((volatile uint *)BCSR1) &= ~(BCSR1_RS232EN_1|BCSR1_RS232EN_2);
64#endif
65
66#ifndef CONFIG_MBX
67	{
68	/* Initialize SMCx and use it for the console port.
69	 */
70
71	/* Enable SDMA.
72	*/
73	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
74
75#ifdef TQM_SMC2_CONSOLE
76	/* Use Port A for SMC2 instead of other functions.
77	*/
78	iopp->iop_papar |=  0x00c0;
79	iopp->iop_padir &= ~0x00c0;
80	iopp->iop_paodr &= ~0x00c0;
81#else
82	/* Use Port B for SMCs instead of other functions.
83	*/
84	cp->cp_pbpar |= 0x00000cc0;
85	cp->cp_pbdir &= ~0x00000cc0;
86	cp->cp_pbodr &= ~0x00000cc0;
87#endif
88
89	/* Allocate space for two buffer descriptors in the DP ram.
90	 * For now, this address seems OK, but it may have to
91	 * change with newer versions of the firmware.
92	 */
93	dpaddr = 0x0800;
94
95	/* Grab a few bytes from the top of memory for SMC FIFOs.
96	 */
97	memaddr = (bd->bi_memsize - 32) & ~15;
98
99	/* Set the physical address of the host memory buffers in
100	 * the buffer descriptors.
101	 */
102	rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
103	rbdf->cbd_bufaddr = memaddr;
104	rbdf->cbd_sc = 0;
105	tbdf = rbdf + 1;
106	tbdf->cbd_bufaddr = memaddr+4;
107	tbdf->cbd_sc = 0;
108
109	/* Set up the uart parameters in the parameter ram.
110	*/
111	up->smc_rbase = dpaddr;
112	up->smc_tbase = dpaddr+sizeof(cbd_t);
113	up->smc_rfcr = SMC_EB;
114	up->smc_tfcr = SMC_EB;
115
116	/* Set UART mode, 8 bit, no parity, one stop.
117	 * Enable receive and transmit.
118	 */
119	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
120
121	/* Mask all interrupts and remove anything pending.
122	*/
123	sp->smc_smcm = 0;
124	sp->smc_smce = 0xff;
125
126	/* Set up the baud rate generator.
127	 * See 8xx_io/commproc.c for details.
128	 * This wires BRG1 to SMC1 and BRG2 to SMC2;
129	 */
130	cp->cp_simode = 0x10000000;
131	ui = bd->bi_intfreq / 16 / bd->bi_baudrate;
132#ifdef TQM_SMC2_CONSOLE
133	cp->cp_brgc2 =
134#else
135	cp->cp_brgc1 =
136#endif
137		((ui - 1) < 4096)
138		? (((ui - 1) << 1) | CPM_BRG_EN)
139		: ((((ui / 16) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16);
140
141#else /* CONFIG_MBX */
142	if (*MBX_CSR1 & CSR1_COMEN) {
143		/* COM1 is enabled.  Initialize SMC1 and use it for
144		 * the console port.
145		 */
146
147		/* Enable SDMA.
148		*/
149		((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
150
151		/* Use Port B for SMCs instead of other functions.
152		*/
153		cp->cp_pbpar |= 0x00000cc0;
154		cp->cp_pbdir &= ~0x00000cc0;
155		cp->cp_pbodr &= ~0x00000cc0;
156
157		/* Allocate space for two buffer descriptors in the DP ram.
158		 * For now, this address seems OK, but it may have to
159		 * change with newer versions of the firmware.
160		 */
161		dpaddr = 0x0800;
162
163		/* Grab a few bytes from the top of memory.  EPPC-Bug isn't
164		 * running any more, so we can do this.
165		 */
166		memaddr = (bd->bi_memsize - 32) & ~15;
167
168		/* Set the physical address of the host memory buffers in
169		 * the buffer descriptors.
170		 */
171		rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
172		rbdf->cbd_bufaddr = memaddr;
173		rbdf->cbd_sc = 0;
174		tbdf = rbdf + 1;
175		tbdf->cbd_bufaddr = memaddr+4;
176		tbdf->cbd_sc = 0;
177
178		/* Set up the uart parameters in the parameter ram.
179		*/
180		up->smc_rbase = dpaddr;
181		up->smc_tbase = dpaddr+sizeof(cbd_t);
182		up->smc_rfcr = SMC_EB;
183		up->smc_tfcr = SMC_EB;
184
185		/* Set UART mode, 8 bit, no parity, one stop.
186		 * Enable receive and transmit.
187		 */
188		sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
189
190		/* Mask all interrupts and remove anything pending.
191		*/
192		sp->smc_smcm = 0;
193		sp->smc_smce = 0xff;
194
195		/* Set up the baud rate generator.
196		 * See 8xx_io/commproc.c for details.
197		 */
198		cp->cp_simode = 0x10000000;
199		cp->cp_brgc1 =
200			(((bd->bi_intfreq/16) / 9600) << 1) | CPM_BRG_EN;
201
202		/* Enable SMC1 for console output.
203		*/
204		*MBX_CSR1 &= ~CSR1_COMEN;
205	}
206	else {
207#endif /* ndef CONFIG_MBX */
208		/* SMCx is used as console port.
209		*/
210		tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
211		rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase];
212
213		/* Issue a stop transmit, and wait for it.
214		*/
215		cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS,
216					CPM_CR_STOP_TX) | CPM_CR_FLG;
217		while (cp->cp_cpcr & CPM_CR_FLG);
218	}
219
220	/* Make the first buffer the only buffer.
221	*/
222	tbdf->cbd_sc |= BD_SC_WRAP;
223	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
224
225	/* Single character receive.
226	*/
227	up->smc_mrblr = 1;
228	up->smc_maxidl = 0;
229
230	/* Initialize Tx/Rx parameters.
231	*/
232	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG;
233	while (cp->cp_cpcr & CPM_CR_FLG);
234
235	/* Enable transmitter/receiver.
236	*/
237	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
238
239	/* This is ignored.
240	*/
241	return 0;
242}
243
244void
245serial_putc(void *ignored, const char c)
246{
247	volatile cbd_t		*tbdf;
248	volatile char		*buf;
249	volatile smc_uart_t	*up;
250
251	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
252	tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
253
254	/* Wait for last character to go.
255	*/
256	buf = (char *)tbdf->cbd_bufaddr;
257	while (tbdf->cbd_sc & BD_SC_READY);
258
259	*buf = c;
260	tbdf->cbd_datlen = 1;
261	tbdf->cbd_sc |= BD_SC_READY;
262}
263
264char
265serial_getc(void *ignored)
266{
267	volatile cbd_t		*rbdf;
268	volatile char		*buf;
269	volatile smc_uart_t	*up;
270	char			c;
271
272	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
273	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
274
275	/* Wait for character to show up.
276	*/
277	buf = (char *)rbdf->cbd_bufaddr;
278	while (rbdf->cbd_sc & BD_SC_EMPTY);
279	c = *buf;
280	rbdf->cbd_sc |= BD_SC_EMPTY;
281
282	return(c);
283}
284
285int
286serial_tstc(void *ignored)
287{
288	volatile cbd_t		*rbdf;
289	volatile smc_uart_t	*up;
290
291	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
292	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
293
294	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
295}
296
297void
298serial_close(unsigned long com_port)
299{
300}
301