3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * SPDX-License-Identifier: GPL-2.0+
13 #include <linux/compiler.h>
15 DECLARE_GLOBAL_DATA_PTR
;
17 #if defined(CONFIG_8xx_CONS_SMC1) /* Console on SMC1 */
19 #define PROFF_SMC PROFF_SMC1
20 #define CPM_CR_CH_SMC CPM_CR_CH_SMC1
23 #elif defined(CONFIG_8xx_CONS_SMC2) /* Console on SMC2 */
25 #define PROFF_SMC PROFF_SMC2
26 #define CPM_CR_CH_SMC CPM_CR_CH_SMC2
29 #endif /* CONFIG_8xx_CONS_SMCx */
32 cbd_t rxbd
; /* Rx BD */
33 cbd_t txbd
; /* Tx BD */
34 uint rxindex
; /* index for next character to read */
35 uchar rxbuf
[CONFIG_SYS_SMC_RXBUFLEN
];/* rx buffers */
36 uchar txbuf
; /* tx buffers */
39 static void serial_setdivisor(cpm8xx_t __iomem
*cp
)
41 int divisor
= (gd
->cpu_clk
+ 8 * gd
->baudrate
) / 16 / gd
->baudrate
;
43 if (divisor
/ 16 > 0x1000) {
44 /* bad divisor, assume 50MHz clock and 9600 baud */
45 divisor
= (50 * 1000 * 1000 + 8 * 9600) / 16 / 9600;
48 divisor
/= CONFIG_SYS_BRGCLK_PRESCALE
;
50 if (divisor
<= 0x1000)
51 out_be32(&cp
->cp_brgc1
, ((divisor
- 1) << 1) | CPM_BRG_EN
);
53 out_be32(&cp
->cp_brgc1
, ((divisor
/ 16 - 1) << 1) | CPM_BRG_EN
|
58 * Minimal serial functions needed to use one of the SMC ports
59 * as serial console interface.
62 static void smc_setbrg(void)
64 immap_t __iomem
*im
= (immap_t __iomem
*)CONFIG_SYS_IMMR
;
65 cpm8xx_t __iomem
*cp
= &(im
->im_cpm
);
67 /* Set up the baud rate generator.
68 * See 8xx_io/commproc.c for details.
73 out_be32(&cp
->cp_simode
, 0);
75 serial_setdivisor(cp
);
78 static int smc_init(void)
80 immap_t __iomem
*im
= (immap_t __iomem
*)CONFIG_SYS_IMMR
;
82 smc_uart_t __iomem
*up
;
83 cpm8xx_t __iomem
*cp
= &(im
->im_cpm
);
84 struct serialbuffer __iomem
*rtx
;
86 /* initialize pointers to SMC */
88 sp
= cp
->cp_smc
+ SMC_INDEX
;
89 up
= (smc_uart_t __iomem
*)&cp
->cp_dparam
[PROFF_SMC
];
90 /* Disable relocation */
91 out_be16(&up
->smc_rpbase
, 0);
93 /* Disable transmitter/receiver. */
94 clrbits_be16(&sp
->smc_smcmr
, SMCMR_REN
| SMCMR_TEN
);
97 out_be32(&im
->im_siu_conf
.sc_sdcr
, 1);
99 /* clear error conditions */
100 out_8(&im
->im_sdma
.sdma_sdsr
, CONFIG_SYS_SDSR
);
102 /* clear SDMA interrupt mask */
103 out_8(&im
->im_sdma
.sdma_sdmr
, CONFIG_SYS_SDMR
);
105 /* Use Port B for SMCx instead of other functions. */
106 setbits_be32(&cp
->cp_pbpar
, IOPINS
);
107 clrbits_be32(&cp
->cp_pbdir
, IOPINS
);
108 clrbits_be16(&cp
->cp_pbodr
, IOPINS
);
110 /* Set the physical address of the host memory buffers in
111 * the buffer descriptors.
113 rtx
= (struct serialbuffer __iomem
*)&cp
->cp_dpmem
[CPM_SERIAL_BASE
];
114 /* Allocate space for two buffer descriptors in the DP ram.
115 * For now, this address seems OK, but it may have to
116 * change with newer versions of the firmware.
117 * damm: allocating space after the two buffers for rx/tx data
120 out_be32(&rtx
->rxbd
.cbd_bufaddr
, (__force uint
)&rtx
->rxbuf
);
121 out_be16(&rtx
->rxbd
.cbd_sc
, 0);
123 out_be32(&rtx
->txbd
.cbd_bufaddr
, (__force uint
)&rtx
->txbuf
);
124 out_be16(&rtx
->txbd
.cbd_sc
, 0);
126 /* Set up the uart parameters in the parameter ram. */
127 out_be16(&up
->smc_rbase
, CPM_SERIAL_BASE
);
128 out_be16(&up
->smc_tbase
, CPM_SERIAL_BASE
+ sizeof(cbd_t
));
129 out_8(&up
->smc_rfcr
, SMC_EB
);
130 out_8(&up
->smc_tfcr
, SMC_EB
);
132 /* Set UART mode, 8 bit, no parity, one stop.
133 * Enable receive and transmit.
135 out_be16(&sp
->smc_smcmr
, smcr_mk_clen(9) | SMCMR_SM_UART
);
137 /* Mask all interrupts and remove anything pending.
139 out_8(&sp
->smc_smcm
, 0);
140 out_8(&sp
->smc_smce
, 0xff);
142 /* Set up the baud rate generator */
145 /* Make the first buffer the only buffer. */
146 setbits_be16(&rtx
->txbd
.cbd_sc
, BD_SC_WRAP
);
147 setbits_be16(&rtx
->rxbd
.cbd_sc
, BD_SC_EMPTY
| BD_SC_WRAP
);
149 /* single/multi character receive. */
150 out_be16(&up
->smc_mrblr
, CONFIG_SYS_SMC_RXBUFLEN
);
151 out_be16(&up
->smc_maxidl
, CONFIG_SYS_MAXIDLE
);
152 out_be32(&rtx
->rxindex
, 0);
154 /* Initialize Tx/Rx parameters. */
155 while (in_be16(&cp
->cp_cpcr
) & CPM_CR_FLG
) /* wait if cp is busy */
158 out_be16(&cp
->cp_cpcr
,
159 mk_cr_cmd(CPM_CR_CH_SMC
, CPM_CR_INIT_TRX
) | CPM_CR_FLG
);
161 while (in_be16(&cp
->cp_cpcr
) & CPM_CR_FLG
) /* wait if cp is busy */
164 /* Enable transmitter/receiver. */
165 setbits_be16(&sp
->smc_smcmr
, SMCMR_REN
| SMCMR_TEN
);
170 static void smc_putc(const char c
)
172 immap_t __iomem
*im
= (immap_t __iomem
*)CONFIG_SYS_IMMR
;
173 cpm8xx_t __iomem
*cpmp
= &(im
->im_cpm
);
174 struct serialbuffer __iomem
*rtx
;
179 rtx
= (struct serialbuffer __iomem
*)&cpmp
->cp_dpmem
[CPM_SERIAL_BASE
];
181 /* Wait for last character to go. */
182 out_8(&rtx
->txbuf
, c
);
183 out_be16(&rtx
->txbd
.cbd_datlen
, 1);
184 setbits_be16(&rtx
->txbd
.cbd_sc
, BD_SC_READY
);
186 while (in_be16(&rtx
->txbd
.cbd_sc
) & BD_SC_READY
)
190 static void smc_puts(const char *s
)
196 static int smc_getc(void)
198 immap_t __iomem
*im
= (immap_t __iomem
*)CONFIG_SYS_IMMR
;
199 cpm8xx_t __iomem
*cpmp
= &(im
->im_cpm
);
200 struct serialbuffer __iomem
*rtx
;
204 rtx
= (struct serialbuffer __iomem
*)&cpmp
->cp_dpmem
[CPM_SERIAL_BASE
];
206 /* Wait for character to show up. */
207 while (in_be16(&rtx
->rxbd
.cbd_sc
) & BD_SC_EMPTY
)
210 /* the characters are read one by one,
211 * use the rxindex to know the next char to deliver
213 rxindex
= in_be32(&rtx
->rxindex
);
214 c
= in_8(rtx
->rxbuf
+ rxindex
);
217 /* check if all char are readout, then make prepare for next receive */
218 if (rxindex
>= in_be16(&rtx
->rxbd
.cbd_datlen
)) {
220 setbits_be16(&rtx
->rxbd
.cbd_sc
, BD_SC_EMPTY
);
222 out_be32(&rtx
->rxindex
, rxindex
);
226 static int smc_tstc(void)
228 immap_t __iomem
*im
= (immap_t __iomem
*)CONFIG_SYS_IMMR
;
229 cpm8xx_t __iomem
*cpmp
= &(im
->im_cpm
);
230 struct serialbuffer __iomem
*rtx
;
232 rtx
= (struct serialbuffer __iomem
*)&cpmp
->cp_dpmem
[CPM_SERIAL_BASE
];
234 return !(in_be16(&rtx
->rxbd
.cbd_sc
) & BD_SC_EMPTY
);
237 struct serial_device serial_smc_device
= {
238 .name
= "serial_smc",
241 .setbrg
= smc_setbrg
,
248 __weak
struct serial_device
*default_serial_console(void)
250 return &serial_smc_device
;
253 void mpc8xx_serial_initialize(void)
255 serial_register(&serial_smc_device
);