1/* 2 * (C) Copyright 2000 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24/* Modified by Udi Finkelstein 25 * 26 * This file includes communication routines for SMC1 that can run even if 27 * SMC2 have already been initialized. 28 */ 29 30#include <common.h> 31#include <watchdog.h> 32#include <commproc.h> 33#include <stdio_dev.h> 34#include <lcd.h> 35 36DECLARE_GLOBAL_DATA_PTR; 37 38#define SMC_INDEX 0 39#define PROFF_SMC PROFF_SMC1 40#define CPM_CR_CH_SMC CPM_CR_CH_SMC1 41 42#define RBC823_KBD_BAUDRATE 38400 43#define CPM_KEYBOARD_BASE 0x1000 44/* 45 * Minimal serial functions needed to use one of the SMC ports 46 * as serial console interface. 47 */ 48 49void smc1_setbrg (void) 50{ 51 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; 52 volatile cpm8xx_t *cp = &(im->im_cpm); 53 54 /* Set up the baud rate generator. 55 * See 8xx_io/commproc.c for details. 56 * 57 * Wire BRG2 to SMC1, BRG1 to SMC2 58 */ 59 60 cp->cp_simode = 0x00001000; 61 62 cp->cp_brgc2 = 63 (((gd->cpu_clk / 16 / RBC823_KBD_BAUDRATE)-1) << 1) | CPM_BRG_EN; 64} 65 66int smc1_init (void) 67{ 68 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; 69 volatile smc_t *sp; 70 volatile smc_uart_t *up; 71 volatile cbd_t *tbdf, *rbdf; 72 volatile cpm8xx_t *cp = &(im->im_cpm); 73 uint dpaddr; 74 75 /* initialize pointers to SMC */ 76 77 sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]); 78 up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC]; 79 80 /* Disable transmitter/receiver. 81 */ 82 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); 83 84 /* Enable SDMA. 85 */ 86 im->im_siu_conf.sc_sdcr = 1; 87 88 /* clear error conditions */ 89#ifdef CONFIG_SYS_SDSR 90 im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR; 91#else 92 im->im_sdma.sdma_sdsr = 0x83; 93#endif 94 95 /* clear SDMA interrupt mask */ 96#ifdef CONFIG_SYS_SDMR 97 im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR; 98#else 99 im->im_sdma.sdma_sdmr = 0x00; 100#endif 101 102 /* Use Port B for SMC1 instead of other functions. 103 */ 104 cp->cp_pbpar |= 0x000000c0; 105 cp->cp_pbdir &= ~0x000000c0; 106 cp->cp_pbodr &= ~0x000000c0; 107 108 /* Set the physical address of the host memory buffers in 109 * the buffer descriptors. 110 */ 111 112#ifdef CONFIG_SYS_ALLOC_DPRAM 113 dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ; 114#else 115 dpaddr = CPM_KEYBOARD_BASE ; 116#endif 117 118 /* Allocate space for two buffer descriptors in the DP ram. 119 * For now, this address seems OK, but it may have to 120 * change with newer versions of the firmware. 121 * damm: allocating space after the two buffers for rx/tx data 122 */ 123 124 rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; 125 rbdf->cbd_bufaddr = (uint) (rbdf+2); 126 rbdf->cbd_sc = 0; 127 tbdf = rbdf + 1; 128 tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; 129 tbdf->cbd_sc = 0; 130 131 /* Set up the uart parameters in the parameter ram. 132 */ 133 up->smc_rbase = dpaddr; 134 up->smc_tbase = dpaddr+sizeof(cbd_t); 135 up->smc_rfcr = SMC_EB; 136 up->smc_tfcr = SMC_EB; 137 138 /* Set UART mode, 8 bit, no parity, one stop. 139 * Enable receive and transmit. 140 */ 141 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; 142 143 /* Mask all interrupts and remove anything pending. 144 */ 145 sp->smc_smcm = 0; 146 sp->smc_smce = 0xff; 147 148 /* Set up the baud rate generator. 149 */ 150 smc1_setbrg (); 151 152 /* Make the first buffer the only buffer. 153 */ 154 tbdf->cbd_sc |= BD_SC_WRAP; 155 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; 156 157 /* Single character receive. 158 */ 159 up->smc_mrblr = 1; 160 up->smc_maxidl = 0; 161 162 /* Initialize Tx/Rx parameters. 163 */ 164 165 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ 166 ; 167 168 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG; 169 170 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ 171 ; 172 173 /* Enable transmitter/receiver. 174 */ 175 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; 176 177 return (0); 178} 179 180void smc1_putc(const char c) 181{ 182 volatile cbd_t *tbdf; 183 volatile char *buf; 184 volatile smc_uart_t *up; 185 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; 186 volatile cpm8xx_t *cpmp = &(im->im_cpm); 187 188 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; 189 190 tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; 191 192 /* Wait for last character to go. 193 */ 194 195 buf = (char *)tbdf->cbd_bufaddr; 196 197 *buf = c; 198 tbdf->cbd_datlen = 1; 199 tbdf->cbd_sc |= BD_SC_READY; 200 __asm__("eieio"); 201 202 while (tbdf->cbd_sc & BD_SC_READY) { 203 WATCHDOG_RESET (); 204 __asm__("eieio"); 205 } 206} 207 208int smc1_getc(void) 209{ 210 volatile cbd_t *rbdf; 211 volatile unsigned char *buf; 212 volatile smc_uart_t *up; 213 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; 214 volatile cpm8xx_t *cpmp = &(im->im_cpm); 215 unsigned char c; 216 217 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; 218 219 rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; 220 221 /* Wait for character to show up. 222 */ 223 buf = (unsigned char *)rbdf->cbd_bufaddr; 224 225 while (rbdf->cbd_sc & BD_SC_EMPTY) 226 WATCHDOG_RESET (); 227 228 c = *buf; 229 rbdf->cbd_sc |= BD_SC_EMPTY; 230 231 return(c); 232} 233 234int smc1_tstc(void) 235{ 236 volatile cbd_t *rbdf; 237 volatile smc_uart_t *up; 238 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; 239 volatile cpm8xx_t *cpmp = &(im->im_cpm); 240 241 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; 242 243 rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; 244 245 return(!(rbdf->cbd_sc & BD_SC_EMPTY)); 246} 247 248/* search for keyboard and register it if found */ 249int drv_keyboard_init(void) 250{ 251 int error = 0; 252 struct stdio_dev kbd_dev; 253 254 if (0) { 255 /* register the keyboard */ 256 memset (&kbd_dev, 0, sizeof(struct stdio_dev)); 257 strcpy(kbd_dev.name, "kbd"); 258 kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; 259 kbd_dev.putc = NULL; 260 kbd_dev.puts = NULL; 261 kbd_dev.getc = smc1_getc; 262 kbd_dev.tstc = smc1_tstc; 263 error = stdio_register (&kbd_dev); 264 } else { 265 lcd_is_enabled = 0; 266 lcd_disable(); 267 } 268 return error; 269} 270