PageRenderTime 33ms CodeModel.GetById 17ms app.highlight 13ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/ppc/boot/simple/m8xx_tty.c

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