xref: /rk3399_rockchip-uboot/arch/powerpc/cpu/mpc85xx/serial_scc.c (revision a47a12becf66f02a56da91c161e2edb625e9f20c)
1*a47a12beSStefan Roese /*
2*a47a12beSStefan Roese  * (C) Copyright 2003 Motorola Inc.
3*a47a12beSStefan Roese  * Xianghua Xiao (X.Xiao@motorola.com)
4*a47a12beSStefan Roese  * Modified based on 8260 for 8560.
5*a47a12beSStefan Roese  *
6*a47a12beSStefan Roese  * (C) Copyright 2000
7*a47a12beSStefan Roese  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8*a47a12beSStefan Roese  *
9*a47a12beSStefan Roese  * See file CREDITS for list of people who contributed to this
10*a47a12beSStefan Roese  * project.
11*a47a12beSStefan Roese  *
12*a47a12beSStefan Roese  * This program is free software; you can redistribute it and/or
13*a47a12beSStefan Roese  * modify it under the terms of the GNU General Public License as
14*a47a12beSStefan Roese  * published by the Free Software Foundation; either version 2 of
15*a47a12beSStefan Roese  * the License, or (at your option) any later version.
16*a47a12beSStefan Roese  *
17*a47a12beSStefan Roese  * This program is distributed in the hope that it will be useful,
18*a47a12beSStefan Roese  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19*a47a12beSStefan Roese  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20*a47a12beSStefan Roese  * GNU General Public License for more details.
21*a47a12beSStefan Roese  *
22*a47a12beSStefan Roese  * You should have received a copy of the GNU General Public License
23*a47a12beSStefan Roese  * along with this program; if not, write to the Free Software
24*a47a12beSStefan Roese  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25*a47a12beSStefan Roese  * MA 02111-1307 USA
26*a47a12beSStefan Roese  *
27*a47a12beSStefan Roese  * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
28*a47a12beSStefan Roese  */
29*a47a12beSStefan Roese 
30*a47a12beSStefan Roese /*
31*a47a12beSStefan Roese  * Minimal serial functions needed to use one of the SCC ports
32*a47a12beSStefan Roese  * as serial console interface.
33*a47a12beSStefan Roese  */
34*a47a12beSStefan Roese 
35*a47a12beSStefan Roese #include <common.h>
36*a47a12beSStefan Roese #include <asm/cpm_85xx.h>
37*a47a12beSStefan Roese 
38*a47a12beSStefan Roese DECLARE_GLOBAL_DATA_PTR;
39*a47a12beSStefan Roese 
40*a47a12beSStefan Roese #if defined(CONFIG_CONS_ON_SCC)
41*a47a12beSStefan Roese 
42*a47a12beSStefan Roese #if CONFIG_CONS_INDEX == 1	/* Console on SCC1 */
43*a47a12beSStefan Roese 
44*a47a12beSStefan Roese #define SCC_INDEX		0
45*a47a12beSStefan Roese #define PROFF_SCC		PROFF_SCC1
46*a47a12beSStefan Roese #define CMXSCR_MASK		(CMXSCR_GR1|CMXSCR_SC1|\
47*a47a12beSStefan Roese 					CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
48*a47a12beSStefan Roese #define CMXSCR_VALUE		(CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
49*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE		CPM_CR_SCC1_PAGE
50*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK	CPM_CR_SCC1_SBLOCK
51*a47a12beSStefan Roese 
52*a47a12beSStefan Roese #elif CONFIG_CONS_INDEX == 2	/* Console on SCC2 */
53*a47a12beSStefan Roese 
54*a47a12beSStefan Roese #define SCC_INDEX		1
55*a47a12beSStefan Roese #define PROFF_SCC		PROFF_SCC2
56*a47a12beSStefan Roese #define CMXSCR_MASK		(CMXSCR_GR2|CMXSCR_SC2|\
57*a47a12beSStefan Roese 					CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
58*a47a12beSStefan Roese #define CMXSCR_VALUE		(CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
59*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE		CPM_CR_SCC2_PAGE
60*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK	CPM_CR_SCC2_SBLOCK
61*a47a12beSStefan Roese 
62*a47a12beSStefan Roese #elif CONFIG_CONS_INDEX == 3	/* Console on SCC3 */
63*a47a12beSStefan Roese 
64*a47a12beSStefan Roese #define SCC_INDEX		2
65*a47a12beSStefan Roese #define PROFF_SCC		PROFF_SCC3
66*a47a12beSStefan Roese #define CMXSCR_MASK		(CMXSCR_GR3|CMXSCR_SC3|\
67*a47a12beSStefan Roese 					CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
68*a47a12beSStefan Roese #define CMXSCR_VALUE		(CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
69*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE		CPM_CR_SCC3_PAGE
70*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK	CPM_CR_SCC3_SBLOCK
71*a47a12beSStefan Roese 
72*a47a12beSStefan Roese #elif CONFIG_CONS_INDEX == 4	/* Console on SCC4 */
73*a47a12beSStefan Roese 
74*a47a12beSStefan Roese #define SCC_INDEX		3
75*a47a12beSStefan Roese #define PROFF_SCC		PROFF_SCC4
76*a47a12beSStefan Roese #define CMXSCR_MASK		(CMXSCR_GR4|CMXSCR_SC4|\
77*a47a12beSStefan Roese 					CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
78*a47a12beSStefan Roese #define CMXSCR_VALUE		(CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
79*a47a12beSStefan Roese #define CPM_CR_SCC_PAGE		CPM_CR_SCC4_PAGE
80*a47a12beSStefan Roese #define CPM_CR_SCC_SBLOCK	CPM_CR_SCC4_SBLOCK
81*a47a12beSStefan Roese 
82*a47a12beSStefan Roese #else
83*a47a12beSStefan Roese 
84*a47a12beSStefan Roese #error "console not correctly defined"
85*a47a12beSStefan Roese 
86*a47a12beSStefan Roese #endif
87*a47a12beSStefan Roese 
88*a47a12beSStefan Roese int serial_init (void)
89*a47a12beSStefan Roese {
90*a47a12beSStefan Roese 	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
91*a47a12beSStefan Roese 	volatile ccsr_cpm_scc_t *sp;
92*a47a12beSStefan Roese 	volatile scc_uart_t *up;
93*a47a12beSStefan Roese 	volatile cbd_t *tbdf, *rbdf;
94*a47a12beSStefan Roese 	volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
95*a47a12beSStefan Roese 	uint	dpaddr;
96*a47a12beSStefan Roese 
97*a47a12beSStefan Roese 	/* initialize pointers to SCC */
98*a47a12beSStefan Roese 
99*a47a12beSStefan Roese 	sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]);
100*a47a12beSStefan Roese 	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
101*a47a12beSStefan Roese 
102*a47a12beSStefan Roese 	/* Disable transmitter/receiver.
103*a47a12beSStefan Roese 	*/
104*a47a12beSStefan Roese 	sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
105*a47a12beSStefan Roese 
106*a47a12beSStefan Roese 	/* put the SCC channel into NMSI (non multiplexd serial interface)
107*a47a12beSStefan Roese 	 * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
108*a47a12beSStefan Roese 	 */
109*a47a12beSStefan Roese 	cpm->im_cpm_mux.cmxscr = \
110*a47a12beSStefan Roese 		(cpm->im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
111*a47a12beSStefan Roese 
112*a47a12beSStefan Roese 	/* Set up the baud rate generator.
113*a47a12beSStefan Roese 	*/
114*a47a12beSStefan Roese 	serial_setbrg ();
115*a47a12beSStefan Roese 
116*a47a12beSStefan Roese 	/* Allocate space for two buffer descriptors in the DP ram.
117*a47a12beSStefan Roese 	 * damm: allocating space after the two buffers for rx/tx data
118*a47a12beSStefan Roese 	 */
119*a47a12beSStefan Roese 
120*a47a12beSStefan Roese 	dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
121*a47a12beSStefan Roese 
122*a47a12beSStefan Roese 	/* Set the physical address of the host memory buffers in
123*a47a12beSStefan Roese 	 * the buffer descriptors.
124*a47a12beSStefan Roese 	 */
125*a47a12beSStefan Roese 	rbdf = (cbd_t *)&(cpm->im_dprambase[dpaddr]);
126*a47a12beSStefan Roese 	rbdf->cbd_bufaddr = (uint) (rbdf+2);
127*a47a12beSStefan Roese 	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
128*a47a12beSStefan Roese 	tbdf = rbdf + 1;
129*a47a12beSStefan Roese 	tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
130*a47a12beSStefan Roese 	tbdf->cbd_sc = BD_SC_WRAP;
131*a47a12beSStefan Roese 
132*a47a12beSStefan Roese 	/* Set up the uart parameters in the parameter ram.
133*a47a12beSStefan Roese 	*/
134*a47a12beSStefan Roese 	up->scc_genscc.scc_rbase = dpaddr;
135*a47a12beSStefan Roese 	up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
136*a47a12beSStefan Roese 	up->scc_genscc.scc_rfcr = CPMFCR_EB;
137*a47a12beSStefan Roese 	up->scc_genscc.scc_tfcr = CPMFCR_EB;
138*a47a12beSStefan Roese 	up->scc_genscc.scc_mrblr = 1;
139*a47a12beSStefan Roese 	up->scc_maxidl = 0;
140*a47a12beSStefan Roese 	up->scc_brkcr = 1;
141*a47a12beSStefan Roese 	up->scc_parec = 0;
142*a47a12beSStefan Roese 	up->scc_frmec = 0;
143*a47a12beSStefan Roese 	up->scc_nosec = 0;
144*a47a12beSStefan Roese 	up->scc_brkec = 0;
145*a47a12beSStefan Roese 	up->scc_uaddr1 = 0;
146*a47a12beSStefan Roese 	up->scc_uaddr2 = 0;
147*a47a12beSStefan Roese 	up->scc_toseq = 0;
148*a47a12beSStefan Roese 	up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
149*a47a12beSStefan Roese 	up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
150*a47a12beSStefan Roese 	up->scc_rccm = 0xc0ff;
151*a47a12beSStefan Roese 
152*a47a12beSStefan Roese 	/* Mask all interrupts and remove anything pending.
153*a47a12beSStefan Roese 	*/
154*a47a12beSStefan Roese 	sp->sccm = 0;
155*a47a12beSStefan Roese 	sp->scce = 0xffff;
156*a47a12beSStefan Roese 
157*a47a12beSStefan Roese 	/* Set 8 bit FIFO, 16 bit oversampling and UART mode.
158*a47a12beSStefan Roese 	*/
159*a47a12beSStefan Roese 	sp->gsmrh = SCC_GSMRH_RFW;	/* 8 bit FIFO */
160*a47a12beSStefan Roese 	sp->gsmrl = \
161*a47a12beSStefan Roese 		SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
162*a47a12beSStefan Roese 
163*a47a12beSStefan Roese 	/* Set CTS no flow control, 1 stop bit, 8 bit character length,
164*a47a12beSStefan Roese 	 * normal async UART mode, no parity
165*a47a12beSStefan Roese 	 */
166*a47a12beSStefan Roese 	sp->psmr = SCU_PSMR_CL;
167*a47a12beSStefan Roese 
168*a47a12beSStefan Roese 	/* execute the "Init Rx and Tx params" CP command.
169*a47a12beSStefan Roese 	*/
170*a47a12beSStefan Roese 
171*a47a12beSStefan Roese 	while (cp->cpcr & CPM_CR_FLG)  /* wait if cp is busy */
172*a47a12beSStefan Roese 	  ;
173*a47a12beSStefan Roese 
174*a47a12beSStefan Roese 	cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
175*a47a12beSStefan Roese 					0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
176*a47a12beSStefan Roese 
177*a47a12beSStefan Roese 	while (cp->cpcr & CPM_CR_FLG)  /* wait if cp is busy */
178*a47a12beSStefan Roese 	  ;
179*a47a12beSStefan Roese 
180*a47a12beSStefan Roese 	/* Enable transmitter/receiver.
181*a47a12beSStefan Roese 	*/
182*a47a12beSStefan Roese 	sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
183*a47a12beSStefan Roese 
184*a47a12beSStefan Roese 	return (0);
185*a47a12beSStefan Roese }
186*a47a12beSStefan Roese 
187*a47a12beSStefan Roese void
188*a47a12beSStefan Roese serial_setbrg (void)
189*a47a12beSStefan Roese {
190*a47a12beSStefan Roese #if defined(CONFIG_CONS_USE_EXTC)
191*a47a12beSStefan Roese 	m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
192*a47a12beSStefan Roese 		CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
193*a47a12beSStefan Roese #else
194*a47a12beSStefan Roese 	m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
195*a47a12beSStefan Roese #endif
196*a47a12beSStefan Roese }
197*a47a12beSStefan Roese 
198*a47a12beSStefan Roese void
199*a47a12beSStefan Roese serial_putc(const char c)
200*a47a12beSStefan Roese {
201*a47a12beSStefan Roese 	volatile scc_uart_t	*up;
202*a47a12beSStefan Roese 	volatile cbd_t		*tbdf;
203*a47a12beSStefan Roese 	volatile ccsr_cpm_t	*cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
204*a47a12beSStefan Roese 
205*a47a12beSStefan Roese 	if (c == '\n')
206*a47a12beSStefan Roese 		serial_putc ('\r');
207*a47a12beSStefan Roese 
208*a47a12beSStefan Roese 	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
209*a47a12beSStefan Roese 	tbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_tbase]);
210*a47a12beSStefan Roese 
211*a47a12beSStefan Roese 	/* Wait for last character to go.
212*a47a12beSStefan Roese 	 */
213*a47a12beSStefan Roese 	while (tbdf->cbd_sc & BD_SC_READY)
214*a47a12beSStefan Roese 		;
215*a47a12beSStefan Roese 
216*a47a12beSStefan Roese 	/* Load the character into the transmit buffer.
217*a47a12beSStefan Roese 	 */
218*a47a12beSStefan Roese 	*(volatile char *)tbdf->cbd_bufaddr = c;
219*a47a12beSStefan Roese 	tbdf->cbd_datlen = 1;
220*a47a12beSStefan Roese 	tbdf->cbd_sc |= BD_SC_READY;
221*a47a12beSStefan Roese }
222*a47a12beSStefan Roese 
223*a47a12beSStefan Roese void
224*a47a12beSStefan Roese serial_puts (const char *s)
225*a47a12beSStefan Roese {
226*a47a12beSStefan Roese 	while (*s) {
227*a47a12beSStefan Roese 		serial_putc (*s++);
228*a47a12beSStefan Roese 	}
229*a47a12beSStefan Roese }
230*a47a12beSStefan Roese 
231*a47a12beSStefan Roese int
232*a47a12beSStefan Roese serial_getc(void)
233*a47a12beSStefan Roese {
234*a47a12beSStefan Roese 	volatile cbd_t		*rbdf;
235*a47a12beSStefan Roese 	volatile scc_uart_t	*up;
236*a47a12beSStefan Roese 	volatile ccsr_cpm_t	*cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
237*a47a12beSStefan Roese 	unsigned char		c;
238*a47a12beSStefan Roese 
239*a47a12beSStefan Roese 	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
240*a47a12beSStefan Roese 	rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
241*a47a12beSStefan Roese 
242*a47a12beSStefan Roese 	/* Wait for character to show up.
243*a47a12beSStefan Roese 	 */
244*a47a12beSStefan Roese 	while (rbdf->cbd_sc & BD_SC_EMPTY)
245*a47a12beSStefan Roese 		;
246*a47a12beSStefan Roese 
247*a47a12beSStefan Roese 	/* Grab the char and clear the buffer again.
248*a47a12beSStefan Roese 	 */
249*a47a12beSStefan Roese 	c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
250*a47a12beSStefan Roese 	rbdf->cbd_sc |= BD_SC_EMPTY;
251*a47a12beSStefan Roese 
252*a47a12beSStefan Roese 	return (c);
253*a47a12beSStefan Roese }
254*a47a12beSStefan Roese 
255*a47a12beSStefan Roese int
256*a47a12beSStefan Roese serial_tstc()
257*a47a12beSStefan Roese {
258*a47a12beSStefan Roese 	volatile cbd_t		*rbdf;
259*a47a12beSStefan Roese 	volatile scc_uart_t	*up;
260*a47a12beSStefan Roese 	volatile ccsr_cpm_t	*cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
261*a47a12beSStefan Roese 
262*a47a12beSStefan Roese 	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
263*a47a12beSStefan Roese 	rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
264*a47a12beSStefan Roese 
265*a47a12beSStefan Roese 	return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
266*a47a12beSStefan Roese }
267*a47a12beSStefan Roese 
268*a47a12beSStefan Roese #endif	/* CONFIG_CONS_ON_SCC */
269