Commit 4a9cbbe832e1c377d04cfb53e9679844595bc3cf

Authored by wdenk
1 parent e887afc9da

Initial revision

Showing 17 changed files with 4551 additions and 0 deletions Side-by-side Diff

  1 +/*
  2 + * (C) Copyright 2000, 2001
  3 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  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 +
  25 +/*
  26 + * FPGA support
  27 + */
  28 +#include <common.h>
  29 +#include <command.h>
  30 +#include <cmd_fpga.h>
  31 +#include <fpga.h>
  32 +#if (CONFIG_COMMANDS & CFG_CMD_NET)
  33 +#include <net.h>
  34 +#endif
  35 +
  36 +#if 0
  37 +#define FPGA_DEBUG
  38 +#endif
  39 +
  40 +#ifdef FPGA_DEBUG
  41 +#define PRINTF(fmt,args...) printf (fmt ,##args)
  42 +#else
  43 +#define PRINTF(fmt,args...)
  44 +#endif
  45 +
  46 +#if defined (CONFIG_FPGA) && ( CONFIG_COMMANDS & CFG_CMD_FPGA )
  47 +
  48 +/* Local functions */
  49 +static void fpga_usage ( cmd_tbl_t *cmdtp );
  50 +static int fpga_get_op( char *opstr );
  51 +
  52 +/* Local defines */
  53 +#define FPGA_NONE -1
  54 +#define FPGA_INFO 0
  55 +#define FPGA_LOAD 1
  56 +#define FPGA_DUMP 3
  57 +
  58 +/* ------------------------------------------------------------------------- */
  59 +/* command form:
  60 + * fpga <op> <device number> <data addr> <datasize>
  61 + * where op is 'load', 'dump', or 'info'
  62 + * If there is no device number field, the fpga environment variable is used.
  63 + * If there is no data addr field, the fpgadata environment variable is used.
  64 + * The info command requires no data address field.
  65 + */
  66 +int
  67 +do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  68 +{
  69 + int op, dev = FPGA_INVALID_DEVICE;
  70 + size_t data_size = 0;
  71 + void *fpga_data = NULL;
  72 + char *devstr = getenv("fpga");
  73 + char *datastr = getenv("fpgadata");
  74 +
  75 + if ( devstr ) dev = (int)simple_strtoul( devstr, NULL, 16 );
  76 + if ( datastr ) fpga_data = (void *)simple_strtoul( datastr, NULL, 16 );
  77 +
  78 + switch ( argc )
  79 + {
  80 + case 5: /* fpga <op> <dev> <data> <datasize> */
  81 + data_size = simple_strtoul( argv[4], NULL, 16 );
  82 + case 4: /* fpga <op> <dev> <data> */
  83 + fpga_data = (void *)simple_strtoul( argv[3], NULL, 16 );
  84 + PRINTF(__FUNCTION__": fpga_data = 0x%x\n", (uint)fpga_data );
  85 + case 3: /* fpga <op> <dev | data addr> */
  86 + dev = (int)simple_strtoul( argv[2], NULL, 16 );
  87 + PRINTF(__FUNCTION__": device = %d\n", dev );
  88 + /* FIXME - this is a really weak test */
  89 + if (( argc == 3 ) && ( dev > fpga_count() )) { /* must be buffer ptr */
  90 + PRINTF(__FUNCTION__": Assuming buffer pointer in arg 3\n");
  91 + fpga_data = (void *)dev;
  92 + PRINTF(__FUNCTION__": fpga_data = 0x%x\n", (uint)fpga_data );
  93 + dev = FPGA_INVALID_DEVICE; /* reset device num */
  94 + }
  95 + case 2: /* fpga <op> */
  96 + op = (int)fpga_get_op( argv[1] );
  97 + break;
  98 + default:
  99 + PRINTF(__FUNCTION__": Too many or too few args (%d)\n", argc );
  100 + op = FPGA_NONE; /* force usage display */
  101 + break;
  102 + }
  103 +
  104 + switch ( op ) {
  105 + case FPGA_NONE:
  106 + fpga_usage( cmdtp );
  107 + break;
  108 +
  109 + case FPGA_INFO:
  110 + fpga_info( dev );
  111 + break;
  112 +
  113 + case FPGA_LOAD:
  114 + fpga_load( dev, fpga_data, data_size );
  115 + break;
  116 +
  117 + case FPGA_DUMP:
  118 + fpga_dump( dev, fpga_data, data_size );
  119 + break;
  120 +
  121 + default:
  122 + printf( "Unknown operation.\n" );
  123 + fpga_usage( cmdtp );
  124 + break;
  125 + }
  126 + return 0;
  127 +}
  128 +
  129 +static void fpga_usage ( cmd_tbl_t *cmdtp )
  130 +{
  131 + printf( "Usage:\n%s\n", cmdtp->usage );
  132 +}
  133 +
  134 +/*
  135 + * Map op to supported operations. We don't use a table since we
  136 + * would just have to relocate it from flash anyway.
  137 + */
  138 +static int fpga_get_op( char *opstr )
  139 +{
  140 + int op = FPGA_NONE;
  141 +
  142 + if (!strcmp ("info", opstr)) {
  143 + op = FPGA_INFO;
  144 + }
  145 + else if (!strcmp ("load", opstr)) {
  146 + op = FPGA_LOAD;
  147 + }
  148 + else if (!strcmp ("dump", opstr)) {
  149 + op = FPGA_DUMP;
  150 + }
  151 +
  152 + if ( op == FPGA_NONE ) {
  153 + printf ("Unknown fpga operation \"%s\"\n", opstr);
  154 + }
  155 + return op;
  156 +}
  157 +
  158 +#endif /* CONFIG_FPGA && CONFIG_COMMANDS & CFG_CMD_FPGA */
  1 +/* taken from arch/ppc/kernel/ppc-stub.c */
  2 +
  3 +/****************************************************************************
  4 +
  5 + THIS SOFTWARE IS NOT COPYRIGHTED
  6 +
  7 + HP offers the following for use in the public domain. HP makes no
  8 + warranty with regard to the software or its performance and the
  9 + user accepts the software "AS IS" with all faults.
  10 +
  11 + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
  12 + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  13 + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  14 +
  15 +****************************************************************************/
  16 +
  17 +/****************************************************************************
  18 + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
  19 + *
  20 + * Module name: remcom.c $
  21 + * Revision: 1.34 $
  22 + * Date: 91/03/09 12:29:49 $
  23 + * Contributor: Lake Stevens Instrument Division$
  24 + *
  25 + * Description: low level support for gdb debugger. $
  26 + *
  27 + * Considerations: only works on target hardware $
  28 + *
  29 + * Written by: Glenn Engel $
  30 + * ModuleState: Experimental $
  31 + *
  32 + * NOTES: See Below $
  33 + *
  34 + * Modified for SPARC by Stu Grossman, Cygnus Support.
  35 + *
  36 + * This code has been extensively tested on the Fujitsu SPARClite demo board.
  37 + *
  38 + * To enable debugger support, two things need to happen. One, a
  39 + * call to set_debug_traps() is necessary in order to allow any breakpoints
  40 + * or error conditions to be properly intercepted and reported to gdb.
  41 + * Two, a breakpoint needs to be generated to begin communication. This
  42 + * is most easily accomplished by a call to breakpoint(). Breakpoint()
  43 + * simulates a breakpoint by executing a trap #1.
  44 + *
  45 + *************
  46 + *
  47 + * The following gdb commands are supported:
  48 + *
  49 + * command function Return value
  50 + *
  51 + * g return the value of the CPU registers hex data or ENN
  52 + * G set the value of the CPU registers OK or ENN
  53 + * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
  54 + *
  55 + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
  56 + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
  57 + *
  58 + * c Resume at current address SNN ( signal NN)
  59 + * cAA..AA Continue at address AA..AA SNN
  60 + *
  61 + * s Step one instruction SNN
  62 + * sAA..AA Step one instruction from AA..AA SNN
  63 + *
  64 + * k kill
  65 + *
  66 + * ? What was the last sigval ? SNN (signal NN)
  67 + *
  68 + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
  69 + * baud rate
  70 + *
  71 + * All commands and responses are sent with a packet which includes a
  72 + * checksum. A packet consists of
  73 + *
  74 + * $<packet info>#<checksum>.
  75 + *
  76 + * where
  77 + * <packet info> :: <characters representing the command or response>
  78 + * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
  79 + *
  80 + * When a packet is received, it is first acknowledged with either '+' or '-'.
  81 + * '+' indicates a successful transfer. '-' indicates a failed transfer.
  82 + *
  83 + * Example:
  84 + *
  85 + * Host: Reply:
  86 + * $m0,10#2a +$00010203040506070809101112131415#42
  87 + *
  88 + ****************************************************************************/
  89 +
  90 +#include <common.h>
  91 +
  92 +#include <kgdb.h>
  93 +#include <command.h>
  94 +
  95 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
  96 +
  97 +#undef KGDB_DEBUG
  98 +
  99 +/*
  100 + * BUFMAX defines the maximum number of characters in inbound/outbound buffers
  101 + */
  102 +#define BUFMAX 1024
  103 +static char remcomInBuffer[BUFMAX];
  104 +static char remcomOutBuffer[BUFMAX];
  105 +static char remcomRegBuffer[BUFMAX];
  106 +
  107 +static int initialized = 0;
  108 +static int kgdb_active = 0, first_entry = 1;
  109 +static struct pt_regs entry_regs;
  110 +static u_int error_jmp_buf[BUFMAX/2];
  111 +static int longjmp_on_fault = 0;
  112 +#ifdef KGDB_DEBUG
  113 +static int kdebug = 1;
  114 +#endif
  115 +
  116 +static const char hexchars[]="0123456789abcdef";
  117 +
  118 +/* Convert ch from a hex digit to an int */
  119 +static int
  120 +hex(unsigned char ch)
  121 +{
  122 + if (ch >= 'a' && ch <= 'f')
  123 + return ch-'a'+10;
  124 + if (ch >= '0' && ch <= '9')
  125 + return ch-'0';
  126 + if (ch >= 'A' && ch <= 'F')
  127 + return ch-'A'+10;
  128 + return -1;
  129 +}
  130 +
  131 +/* Convert the memory pointed to by mem into hex, placing result in buf.
  132 + * Return a pointer to the last char put in buf (null).
  133 + */
  134 +static unsigned char *
  135 +mem2hex(char *mem, char *buf, int count)
  136 +{
  137 + unsigned char ch;
  138 +
  139 + longjmp_on_fault = 1;
  140 + while (count-- > 0) {
  141 + ch = *mem++;
  142 + *buf++ = hexchars[ch >> 4];
  143 + *buf++ = hexchars[ch & 0xf];
  144 + }
  145 + *buf = 0;
  146 + longjmp_on_fault = 0;
  147 + return buf;
  148 +}
  149 +
  150 +/* convert the hex array pointed to by buf into binary to be placed in mem
  151 + * return a pointer to the character AFTER the last byte fetched from buf.
  152 +*/
  153 +static char *
  154 +hex2mem(char *buf, char *mem, int count)
  155 +{
  156 + int i, hexValue;
  157 + unsigned char ch;
  158 + char *mem_start = mem;
  159 +
  160 + longjmp_on_fault = 1;
  161 + for (i=0; i<count; i++) {
  162 + if ((hexValue = hex(*buf++)) < 0)
  163 + kgdb_error(KGDBERR_NOTHEXDIG);
  164 + ch = hexValue << 4;
  165 + if ((hexValue = hex(*buf++)) < 0)
  166 + kgdb_error(KGDBERR_NOTHEXDIG);
  167 + ch |= hexValue;
  168 + *mem++ = ch;
  169 + }
  170 + kgdb_flush_cache_range((void *)mem_start, (void *)(mem - 1));
  171 + longjmp_on_fault = 0;
  172 +
  173 + return buf;
  174 +}
  175 +
  176 +/*
  177 + * While we find nice hex chars, build an int.
  178 + * Return number of chars processed.
  179 + */
  180 +static int
  181 +hexToInt(char **ptr, int *intValue)
  182 +{
  183 + int numChars = 0;
  184 + int hexValue;
  185 +
  186 + *intValue = 0;
  187 +
  188 + longjmp_on_fault = 1;
  189 + while (**ptr) {
  190 + hexValue = hex(**ptr);
  191 + if (hexValue < 0)
  192 + break;
  193 +
  194 + *intValue = (*intValue << 4) | hexValue;
  195 + numChars ++;
  196 +
  197 + (*ptr)++;
  198 + }
  199 + longjmp_on_fault = 0;
  200 +
  201 + return (numChars);
  202 +}
  203 +
  204 +/* scan for the sequence $<data>#<checksum> */
  205 +static void
  206 +getpacket(char *buffer)
  207 +{
  208 + unsigned char checksum;
  209 + unsigned char xmitcsum;
  210 + int i;
  211 + int count;
  212 + unsigned char ch;
  213 +
  214 + do {
  215 + /* wait around for the start character, ignore all other
  216 + * characters */
  217 + while ((ch = (getDebugChar() & 0x7f)) != '$') {
  218 +#ifdef KGDB_DEBUG
  219 + if (kdebug)
  220 + putc(ch);
  221 +#endif
  222 + ;
  223 + }
  224 +
  225 + checksum = 0;
  226 + xmitcsum = -1;
  227 +
  228 + count = 0;
  229 +
  230 + /* now, read until a # or end of buffer is found */
  231 + while (count < BUFMAX) {
  232 + ch = getDebugChar() & 0x7f;
  233 + if (ch == '#')
  234 + break;
  235 + checksum = checksum + ch;
  236 + buffer[count] = ch;
  237 + count = count + 1;
  238 + }
  239 +
  240 + if (count >= BUFMAX)
  241 + continue;
  242 +
  243 + buffer[count] = 0;
  244 +
  245 + if (ch == '#') {
  246 + xmitcsum = hex(getDebugChar() & 0x7f) << 4;
  247 + xmitcsum |= hex(getDebugChar() & 0x7f);
  248 + if (checksum != xmitcsum)
  249 + putDebugChar('-'); /* failed checksum */
  250 + else {
  251 + putDebugChar('+'); /* successful transfer */
  252 + /* if a sequence char is present, reply the ID */
  253 + if (buffer[2] == ':') {
  254 + putDebugChar(buffer[0]);
  255 + putDebugChar(buffer[1]);
  256 + /* remove sequence chars from buffer */
  257 + count = strlen(buffer);
  258 + for (i=3; i <= count; i++)
  259 + buffer[i-3] = buffer[i];
  260 + }
  261 + }
  262 + }
  263 + } while (checksum != xmitcsum);
  264 +}
  265 +
  266 +/* send the packet in buffer. */
  267 +static void
  268 +putpacket(unsigned char *buffer)
  269 +{
  270 + unsigned char checksum;
  271 + int count;
  272 + unsigned char ch, recv;
  273 +
  274 + /* $<packet info>#<checksum>. */
  275 + do {
  276 + putDebugChar('$');
  277 + checksum = 0;
  278 + count = 0;
  279 +
  280 + while ((ch = buffer[count])) {
  281 + putDebugChar(ch);
  282 + checksum += ch;
  283 + count += 1;
  284 + }
  285 +
  286 + putDebugChar('#');
  287 + putDebugChar(hexchars[checksum >> 4]);
  288 + putDebugChar(hexchars[checksum & 0xf]);
  289 + recv = getDebugChar();
  290 + } while ((recv & 0x7f) != '+');
  291 +}
  292 +
  293 +/*
  294 + * This function does all command processing for interfacing to gdb.
  295 + */
  296 +static int
  297 +handle_exception (struct pt_regs *regs)
  298 +{
  299 + int addr;
  300 + int length;
  301 + char *ptr;
  302 + kgdb_data kd;
  303 + int i;
  304 +
  305 + if (!initialized) {
  306 + printf("kgdb: exception before kgdb is initialized! huh?\n");
  307 + return (0);
  308 + }
  309 +
  310 + /* probably should check which exception occured as well */
  311 + if (longjmp_on_fault) {
  312 + longjmp_on_fault = 0;
  313 + kgdb_longjmp((long*)error_jmp_buf, KGDBERR_MEMFAULT);
  314 + panic("kgdb longjump failed!\n");
  315 + }
  316 +
  317 + if (kgdb_active) {
  318 + printf("kgdb: unexpected exception from within kgdb\n");
  319 + return (0);
  320 + }
  321 + kgdb_active = 1;
  322 +
  323 + kgdb_interruptible(0);
  324 +
  325 + printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
  326 +
  327 + if (kgdb_setjmp((long*)error_jmp_buf) != 0)
  328 + panic("kgdb: error or fault in entry init!\n");
  329 +
  330 + kgdb_enter(regs, &kd);
  331 +
  332 + if (first_entry) {
  333 + /*
  334 + * the first time we enter kgdb, we save the processor
  335 + * state so that we can return to the monitor if the
  336 + * remote end quits gdb (or at least, tells us to quit
  337 + * with the 'k' packet)
  338 + */
  339 + entry_regs = *regs;
  340 + first_entry = 0;
  341 + }
  342 +
  343 + ptr = remcomOutBuffer;
  344 +
  345 + *ptr++ = 'T';
  346 +
  347 + *ptr++ = hexchars[kd.sigval >> 4];
  348 + *ptr++ = hexchars[kd.sigval & 0xf];
  349 +
  350 + for (i = 0; i < kd.nregs; i++) {
  351 + kgdb_reg *rp = &kd.regs[i];
  352 +
  353 + *ptr++ = hexchars[rp->num >> 4];
  354 + *ptr++ = hexchars[rp->num & 0xf];
  355 + *ptr++ = ':';
  356 + ptr = mem2hex((char *)&rp->val, ptr, 4);
  357 + *ptr++ = ';';
  358 + }
  359 +
  360 + *ptr = 0;
  361 +
  362 +#ifdef KGDB_DEBUG
  363 + if (kdebug)
  364 + printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
  365 +#endif
  366 +
  367 + putpacket(remcomOutBuffer);
  368 +
  369 + while (1) {
  370 + volatile int errnum;
  371 +
  372 + remcomOutBuffer[0] = 0;
  373 +
  374 + getpacket(remcomInBuffer);
  375 + ptr = &remcomInBuffer[1];
  376 +
  377 +#ifdef KGDB_DEBUG
  378 + if (kdebug)
  379 + printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer);
  380 +#endif
  381 +
  382 + errnum = kgdb_setjmp((long*)error_jmp_buf);
  383 +
  384 + if (errnum == 0) switch (remcomInBuffer[0]) {
  385 +
  386 + case '?': /* report most recent signal */
  387 + remcomOutBuffer[0] = 'S';
  388 + remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
  389 + remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
  390 + remcomOutBuffer[3] = 0;
  391 + break;
  392 +
  393 +#ifdef KGDB_DEBUG
  394 + case 'd':
  395 + /* toggle debug flag */
  396 + kdebug ^= 1;
  397 + break;
  398 +#endif
  399 +
  400 + case 'g': /* return the value of the CPU registers. */
  401 + length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
  402 + mem2hex(remcomRegBuffer, remcomOutBuffer, length);
  403 + break;
  404 +
  405 + case 'G': /* set the value of the CPU registers */
  406 + length = strlen(ptr);
  407 + if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
  408 + hex2mem(ptr, remcomRegBuffer, length/2);
  409 + kgdb_putregs(regs, remcomRegBuffer, length/2);
  410 + strcpy(remcomOutBuffer,"OK");
  411 + break;
  412 +
  413 + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
  414 + /* Try to read %x,%x. */
  415 +
  416 + if (hexToInt(&ptr, &addr)
  417 + && *ptr++ == ','
  418 + && hexToInt(&ptr, &length)) {
  419 + mem2hex((char *)addr, remcomOutBuffer, length);
  420 + } else {
  421 + kgdb_error(KGDBERR_BADPARAMS);
  422 + }
  423 + break;
  424 +
  425 + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
  426 + /* Try to read '%x,%x:'. */
  427 +
  428 + if (hexToInt(&ptr, &addr)
  429 + && *ptr++ == ','
  430 + && hexToInt(&ptr, &length)
  431 + && *ptr++ == ':') {
  432 + hex2mem(ptr, (char *)addr, length);
  433 + strcpy(remcomOutBuffer, "OK");
  434 + } else {
  435 + kgdb_error(KGDBERR_BADPARAMS);
  436 + }
  437 + break;
  438 +
  439 +
  440 + case 'k': /* kill the program, actually return to monitor */
  441 + kd.extype = KGDBEXIT_KILL;
  442 + *regs = entry_regs;
  443 + first_entry = 1;
  444 + goto doexit;
  445 +
  446 + case 'C': /* CSS continue with signal SS */
  447 + *ptr = '\0'; /* ignore the signal number for now */
  448 + /* fall through */
  449 +
  450 + case 'c': /* cAA..AA Continue; address AA..AA optional */
  451 + /* try to read optional parameter, pc unchanged if no parm */
  452 + kd.extype = KGDBEXIT_CONTINUE;
  453 +
  454 + if (hexToInt(&ptr, &addr)) {
  455 + kd.exaddr = addr;
  456 + kd.extype |= KGDBEXIT_WITHADDR;
  457 + }
  458 +
  459 + goto doexit;
  460 +
  461 + case 'S': /* SSS single step with signal SS */
  462 + *ptr = '\0'; /* ignore the signal number for now */
  463 + /* fall through */
  464 +
  465 + case 's':
  466 + kd.extype = KGDBEXIT_SINGLE;
  467 +
  468 + if (hexToInt(&ptr, &addr)) {
  469 + kd.exaddr = addr;
  470 + kd.extype |= KGDBEXIT_WITHADDR;
  471 + }
  472 +
  473 + doexit:
  474 +/* Need to flush the instruction cache here, as we may have deposited a
  475 + * breakpoint, and the icache probably has no way of knowing that a data ref to
  476 + * some location may have changed something that is in the instruction cache.
  477 + */
  478 + kgdb_flush_cache_all();
  479 + kgdb_exit(regs, &kd);
  480 + kgdb_active = 0;
  481 + kgdb_interruptible(1);
  482 + return (1);
  483 +
  484 + case 'r': /* Reset (if user process..exit ???)*/
  485 + panic("kgdb reset.");
  486 + break;
  487 +
  488 + case 'P': /* Pr=v set reg r to value v (r and v are hex) */
  489 + if (hexToInt(&ptr, &addr)
  490 + && *ptr++ == '='
  491 + && ((length = strlen(ptr)) & 1) == 0) {
  492 + hex2mem(ptr, remcomRegBuffer, length/2);
  493 + kgdb_putreg(regs, addr,
  494 + remcomRegBuffer, length/2);
  495 + strcpy(remcomOutBuffer,"OK");
  496 + } else {
  497 + kgdb_error(KGDBERR_BADPARAMS);
  498 + }
  499 + break;
  500 + } /* switch */
  501 +
  502 + if (errnum != 0)
  503 + sprintf(remcomOutBuffer, "E%02d", errnum);
  504 +
  505 +#ifdef KGDB_DEBUG
  506 + if (kdebug)
  507 + printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
  508 +#endif
  509 +
  510 + /* reply to the request */
  511 + putpacket(remcomOutBuffer);
  512 +
  513 + } /* while(1) */
  514 +}
  515 +
  516 +/*
  517 + * kgdb_init must be called *after* the
  518 + * monitor is relocated into ram
  519 + */
  520 +void
  521 +kgdb_init(void)
  522 +{
  523 + kgdb_serial_init();
  524 + debugger_exception_handler = handle_exception;
  525 + initialized = 1;
  526 +
  527 + putDebugStr("kgdb ready\n");
  528 + puts("ready\n");
  529 +}
  530 +
  531 +void
  532 +kgdb_error(int errnum)
  533 +{
  534 + longjmp_on_fault = 0;
  535 + kgdb_longjmp((long*)error_jmp_buf, errnum);
  536 + panic("kgdb_error: longjmp failed!\n");
  537 +}
  538 +
  539 +/* Output string in GDB O-packet format if GDB has connected. If nothing
  540 + output, returns 0 (caller must then handle output). */
  541 +int
  542 +kgdb_output_string (const char* s, unsigned int count)
  543 +{
  544 + char buffer[512];
  545 +
  546 + count = (count <= (sizeof(buffer) / 2 - 2))
  547 + ? count : (sizeof(buffer) / 2 - 2);
  548 +
  549 + buffer[0] = 'O';
  550 + mem2hex ((char *)s, &buffer[1], count);
  551 + putpacket(buffer);
  552 +
  553 + return 1;
  554 +}
  555 +
  556 +void
  557 +breakpoint(void)
  558 +{
  559 + if (!initialized) {
  560 + printf("breakpoint() called b4 kgdb init\n");
  561 + return;
  562 + }
  563 +
  564 + kgdb_breakpoint(0, 0);
  565 +}
  566 +
  567 +int
  568 +do_kgdb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  569 +{
  570 + printf("Entering KGDB mode via exception handler...\n\n");
  571 + kgdb_breakpoint(argc - 1, argv + 1);
  572 + printf("\nReturned from KGDB mode\n");
  573 + return 0;
  574 +}
  575 +
  576 +#else
  577 +
  578 +int kgdb_not_configured = 1;
  579 +
  580 +#endif /* CFG_CMD_KGDB */
cpu/74xx_7xx/cpu_init.c
  1 +/*
  2 + * (C) Copyright 2001
  3 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
  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 +/*
  25 + * cpu_init.c - low level cpu init
  26 + *
  27 + * there's really nothing going on here yet. future work area?
  28 + */
  29 +
  30 +#include <common.h>
  31 +#include <74xx_7xx.h>
  32 +
  33 +/*
  34 + * Breath some life into the CPU...
  35 + *
  36 + * there's basically nothing to do here since the memory controller
  37 + * isn't on the CPU in this case.
  38 + */
  39 +void
  40 +cpu_init_f (void)
  41 +{
  42 + if (get_cpu_type() == CPU_7450) {
  43 + /* enable the timebase bit in HID0 */
  44 + set_hid0(get_hid0() | 0x4000000);
  45 + }
  46 +}
  47 +
  48 +/*
  49 + * initialize higher level parts of CPU like timers
  50 + */
  51 +int cpu_init_r (void)
  52 +{
  53 + return (0);
  54 +}
cpu/74xx_7xx/speed.c
  1 +/*
  2 + * (C) Copyright 2000-2002
  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 +#include <common.h>
  25 +#include <74xx_7xx.h>
  26 +#include <asm/processor.h>
  27 +
  28 +static const int hid1_multipliers_x_10[] = {
  29 + 25, /* 0000 - 2.5x */
  30 + 75, /* 0001 - 7.5x */
  31 + 70, /* 0010 - 7x */
  32 + 10, /* 0011 - bypass */
  33 + 20, /* 0100 - 2x */
  34 + 65, /* 0101 - 6.5x */
  35 + 100, /* 0110 - 10x */
  36 + 45, /* 0111 - 4.5x */
  37 + 30, /* 1000 - 3x */
  38 + 55, /* 1001 - 5.5x */
  39 + 40, /* 1010 - 4x */
  40 + 50, /* 1011 - 5x */
  41 + 80, /* 1100 - 8x */
  42 + 60, /* 1101 - 6x */
  43 + 35, /* 1110 - 3.5x */
  44 + 0 /* 1111 - off */
  45 +};
  46 +
  47 +/* ------------------------------------------------------------------------- */
  48 +
  49 +/*
  50 + * Measure CPU clock speed (core clock GCLK1, GCLK2)
  51 + *
  52 + * (Approx. GCLK frequency in Hz)
  53 + */
  54 +
  55 +int get_clocks (void)
  56 +{
  57 + DECLARE_GLOBAL_DATA_PTR;
  58 +
  59 + ulong clock = CFG_BUS_CLK * \
  60 + hid1_multipliers_x_10[get_hid1 () >> 28] / 10;
  61 + gd->cpu_clk = clock;
  62 + gd->bus_clk = CFG_BUS_CLK;
  63 +
  64 + return (0);
  65 +}
  66 +
  67 +/* ------------------------------------------------------------------------- */
  68 +
  69 +#if 0 /* disabled XXX - use global data instead */
  70 +ulong get_bus_freq (ulong gclk_freq)
  71 +{
  72 + return CFG_BUS_CLK;
  73 +}
  74 +#endif /* 0 */
  75 +
  76 +/* ------------------------------------------------------------------------- */
  1 +/*
  2 + * (C) Copyright 2000 - 2002
  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 +#include <config.h>
  25 +#include <mpc824x.h>
  26 +#include <common.h>
  27 +#include <command.h>
  28 +
  29 +int checkcpu (void)
  30 +{
  31 + DECLARE_GLOBAL_DATA_PTR;
  32 +
  33 + unsigned int pvr = get_pvr ();
  34 + unsigned int version = pvr >> 16;
  35 + unsigned char revision;
  36 + ulong clock = gd->cpu_clk;
  37 + char buf[32];
  38 +
  39 + puts ("CPU: ");
  40 +
  41 + switch (version) {
  42 + case CPU_TYPE_8240:
  43 + puts ("MPC8240");
  44 + break;
  45 +
  46 + case CPU_TYPE_8245:
  47 + puts ("MPC8245");
  48 + break;
  49 +
  50 + default:
  51 + return -1; /*not valid for this source */
  52 + }
  53 +
  54 + CONFIG_READ_BYTE (REVID, revision);
  55 +
  56 + if (revision) {
  57 + printf (" Revision %d.%d",
  58 + (revision & 0xf0) >> 4,
  59 + (revision & 0x0f));
  60 + } else {
  61 + return -1; /* no valid CPU revision info */
  62 + }
  63 +
  64 + printf (" at %s MHz:", strmhz (buf, clock));
  65 +
  66 + printf (" %u kB I-Cache", checkicache () >> 10);
  67 + printf (" %u kB D-Cache", checkdcache () >> 10);
  68 +
  69 + puts ("\n");
  70 +
  71 + return 0;
  72 +}
  73 +
  74 +/* ------------------------------------------------------------------------- */
  75 +/* L1 i-cache */
  76 +
  77 +int checkicache (void)
  78 +{
  79 + /*TODO*/
  80 + return 128 * 4 * 32;
  81 +};
  82 +
  83 +/* ------------------------------------------------------------------------- */
  84 +/* L1 d-cache */
  85 +
  86 +int checkdcache (void)
  87 +{
  88 + /*TODO*/
  89 + return 128 * 4 * 32;
  90 +
  91 +};
  92 +
  93 +/*------------------------------------------------------------------- */
  94 +
  95 +int do_reset (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
  96 + char *argv[])
  97 +{
  98 + ulong msr, addr;
  99 +
  100 + /* Interrupts and MMU off */
  101 + __asm__ ("mtspr 81, 0");
  102 +
  103 + /* Interrupts and MMU off */
  104 + __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
  105 +
  106 + msr &= ~0x1030;
  107 + __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
  108 +
  109 + /*
  110 + * Trying to execute the next instruction at a non-existing address
  111 + * should cause a machine check, resulting in reset
  112 + */
  113 +#ifdef CFG_RESET_ADDRESS
  114 + addr = CFG_RESET_ADDRESS;
  115 +#else
  116 + /*
  117 + * note: when CFG_MONITOR_BASE points to a RAM address,
  118 + * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
  119 + * address. Better pick an address known to be invalid on
  120 + * your system and assign it to CFG_RESET_ADDRESS.
  121 + * "(ulong)-1" used to be a good choice for many systems...
  122 + */
  123 + addr = CFG_MONITOR_BASE - sizeof (ulong);
  124 +#endif
  125 + ((void (*)(void)) addr) ();
  126 + return 1;
  127 +
  128 +}
  129 +
  130 +/* ------------------------------------------------------------------------- */
  131 +
  132 +/*
  133 + * Get timebase clock frequency (like cpu_clk in Hz)
  134 + * This is the sys_logic_clk (memory bus) divided by 4
  135 + */
  136 +unsigned long get_tbclk (void)
  137 +{
  138 + return ((get_bus_freq (0) + 2L) / 4L);
  139 +}
  140 +
  141 +/* ------------------------------------------------------------------------- */
  142 +
  143 +/*
  144 + * The MPC824x has an integrated PCI controller known as the MPC107.
  145 + * The following are MPC107 Bridge Controller and PCI Support functions
  146 + *
  147 + */
  148 +
  149 +/*
  150 + * This procedure reads a 32-bit address MPC107 register, and returns
  151 + * a 32 bit value. It swaps the address to little endian before
  152 + * writing it to config address, and swaps the value to big endian
  153 + * before returning to the caller.
  154 + */
  155 +unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
  156 +{
  157 + unsigned int temp;
  158 +
  159 + /* swap the addr. to little endian */
  160 + *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
  161 + temp = *(volatile unsigned int *) CHRP_REG_DATA;
  162 + return PCISWAP (temp); /* swap the data upon return */
  163 +}
  164 +
  165 +/*
  166 + * This procedure writes a 32-bit address MPC107 register. It swaps
  167 + * the address to little endian before writing it to config address.
  168 + */
  169 +
  170 +void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
  171 +{
  172 + /* swap the addr. to little endian */
  173 + *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
  174 + *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
  175 + return;
  176 +}
  177 +
  178 +
  179 +/*
  180 + * Write a byte (8 bits) to a memory location.
  181 + */
  182 +void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
  183 +{
  184 + *(unsigned char *) addr = data;
  185 + __asm__ ("sync");
  186 +}
  187 +
  188 +/*
  189 + * Write a word (16 bits) to a memory location after the value
  190 + * has been byte swapped (big to little endian or vice versa)
  191 + */
  192 +
  193 +void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
  194 +{
  195 + *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
  196 + __asm__ ("sync");
  197 +}
  198 +
  199 +/*
  200 + * Write a long word (32 bits) to a memory location after the value
  201 + * has been byte swapped (big to little endian or vice versa)
  202 + */
  203 +
  204 +void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
  205 +{
  206 + *(volatile unsigned int *) address = LONGSWAP (data);
  207 + __asm__ ("sync");
  208 +}
  209 +
  210 +/*
  211 + * Read a byte (8 bits) from a memory location.
  212 + */
  213 +unsigned char mpc824x_mpc107_read8 (unsigned int addr)
  214 +{
  215 + return *(volatile unsigned char *) addr;
  216 +}
  217 +
  218 +
  219 +/*
  220 + * Read a word (16 bits) from a memory location, and byte swap the
  221 + * value before returning to the caller.
  222 + */
  223 +unsigned short mpc824x_mpc107_read16 (unsigned int address)
  224 +{
  225 + unsigned short retVal;
  226 +
  227 + retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
  228 + return retVal;
  229 +}
  230 +
  231 +
  232 +/*
  233 + * Read a long word (32 bits) from a memory location, and byte
  234 + * swap the value before returning to the caller.
  235 + */
  236 +unsigned int mpc824x_mpc107_read32 (unsigned int address)
  237 +{
  238 + unsigned int retVal;
  239 +
  240 + retVal = LONGSWAP (*(unsigned int *) address);
  241 + return (retVal);
  242 +}
  243 +
  244 +
  245 +/*
  246 + * Read a register in the Embedded Utilities Memory Block address
  247 + * space.
  248 + * Input: regNum - register number + utility base address. Example,
  249 + * the base address of EPIC is 0x40000, the register number
  250 + * being passed is 0x40000+the address of the target register.
  251 + * (See epic.h for register addresses).
  252 + * Output: The 32 bit little endian value of the register.
  253 + */
  254 +
  255 +unsigned int mpc824x_eummbar_read (unsigned int regNum)
  256 +{
  257 + unsigned int temp;
  258 +
  259 + temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
  260 + temp = PCISWAP (temp);
  261 + return temp;
  262 +}
  263 +
  264 +
  265 +/*
  266 + * Write a value to a register in the Embedded Utilities Memory
  267 + * Block address space.
  268 + * Input: regNum - register number + utility base address. Example,
  269 + * the base address of EPIC is 0x40000, the register
  270 + * number is 0x40000+the address of the target register.
  271 + * (See epic.h for register addresses).
  272 + * regVal - value to be written to the register.
  273 + */
  274 +
  275 +void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
  276 +{
  277 + *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
  278 + return;
  279 +}
  280 +
  281 +/* ------------------------------------------------------------------------- */
cpu/mpc824x/interrupts.c
  1 +/*
  2 + * (C) Copyright 2000-2002
  3 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com
  5 + *
  6 + * See file CREDITS for list of people who contributed to this
  7 + * project.
  8 + *
  9 + * This program is free software; you can redistribute it and/or
  10 + * modify it under the terms of the GNU General Public License as
  11 + * published by the Free Software Foundation; either version 2 of
  12 + * the License, or (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program; if not, write to the Free Software
  21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 + * MA 02111-1307 USA
  23 + */
  24 +
  25 +#include <common.h>
  26 +#include <mpc824x.h>
  27 +#include <asm/processor.h>
  28 +#include <asm/pci_io.h>
  29 +#include <commproc.h>
  30 +#include "drivers/epic.h"
  31 +
  32 +/****************************************************************************/
  33 +
  34 +unsigned decrementer_count; /* count val for 1e6/HZ microseconds */
  35 +
  36 +static __inline__ unsigned long get_msr (void)
  37 +{
  38 + unsigned long msr;
  39 +
  40 + asm volatile ("mfmsr %0":"=r" (msr):);
  41 +
  42 + return msr;
  43 +}
  44 +
  45 +static __inline__ void set_msr (unsigned long msr)
  46 +{
  47 + asm volatile ("mtmsr %0"::"r" (msr));
  48 +}
  49 +
  50 +static __inline__ unsigned long get_dec (void)
  51 +{
  52 + unsigned long val;
  53 +
  54 + asm volatile ("mfdec %0":"=r" (val):);
  55 +
  56 + return val;
  57 +}
  58 +
  59 +
  60 +static __inline__ void set_dec (unsigned long val)
  61 +{
  62 + asm volatile ("mtdec %0"::"r" (val));
  63 +}
  64 +
  65 +
  66 +void enable_interrupts (void)
  67 +{
  68 + set_msr (get_msr () | MSR_EE);
  69 +}
  70 +
  71 +/* returns flag if MSR_EE was set before */
  72 +int disable_interrupts (void)
  73 +{
  74 + ulong msr = get_msr ();
  75 +
  76 + set_msr (msr & ~MSR_EE);
  77 + return ((msr & MSR_EE) != 0);
  78 +}
  79 +
  80 +/****************************************************************************/
  81 +
  82 +int interrupt_init (void)
  83 +{
  84 + decrementer_count = (get_bus_freq (0) / 4) / CFG_HZ;
  85 +
  86 + /*
  87 + * It's all broken at the moment and I currently don't need
  88 + * interrupts. If you want to fix it, have a look at the epic
  89 + * drivers in dink32 v12. They do everthing and Motorola said
  90 + * I could use the dink source in this project as long as
  91 + * copyright notices remain intact.
  92 + */
  93 +
  94 + epicInit (EPIC_DIRECT_IRQ, 0);
  95 +
  96 + set_dec (decrementer_count);
  97 +
  98 + set_msr (get_msr () | MSR_EE);
  99 +
  100 + return (0);
  101 +}
  102 +
  103 +/****************************************************************************/
  104 +
  105 +/*
  106 + * Handle external interrupts
  107 + */
  108 +void external_interrupt (struct pt_regs *regs)
  109 +{
  110 + register unsigned long temp;
  111 +
  112 + pci_readl (CFG_EUMB_ADDR + EPIC_PROC_INT_ACK_REG, temp);
  113 + sync (); /* i'm not convinced this is needed, but dink source has it */
  114 + temp &= 0xff; /*get vector */
  115 +
  116 + /*TODO: handle them -... */
  117 + epicEOI ();
  118 +}
  119 +
  120 +/****************************************************************************/
  121 +
  122 +/*
  123 + * blank int handlers.
  124 + */
  125 +
  126 +void
  127 +irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
  128 +{
  129 +}
  130 +
  131 +void irq_free_handler (int vec)
  132 +{
  133 +
  134 +}
  135 +
  136 +/*TODO: some handlers for winbond and 87308 interrupts
  137 + and what about generic pci inteerupts?
  138 + vga?
  139 + */
  140 +
  141 +volatile ulong timestamp = 0;
  142 +
  143 +void timer_interrupt (struct pt_regs *regs)
  144 +{
  145 + /* Restore Decrementer Count */
  146 + set_dec (decrementer_count);
  147 +
  148 + timestamp++;
  149 +
  150 +#if defined(CONFIG_WATCHDOG)
  151 + if ((timestamp % (CFG_HZ / 2)) == 0) {
  152 +#if defined(CONFIG_OXC)
  153 + {
  154 + extern void oxc_wdt_reset (void);
  155 +
  156 + oxc_wdt_reset ();
  157 + }
  158 +#endif
  159 + }
  160 +#endif /* CONFIG_WATCHDOG */
  161 +#if defined(CONFIG_SHOW_ACTIVITY) && defined(CONFIG_OXC)
  162 + if ((timestamp % (CFG_HZ / 10)) == 0) {
  163 + {
  164 + extern void oxc_toggle_activeled (void);
  165 +
  166 + oxc_toggle_activeled ();
  167 + }
  168 + }
  169 +#endif
  170 +}
  171 +
  172 +void reset_timer (void)
  173 +{
  174 + timestamp = 0;
  175 +}
  176 +
  177 +ulong get_timer (ulong base)
  178 +{
  179 + return (timestamp - base);
  180 +}
  181 +
  182 +void set_timer (ulong t)
  183 +{
  184 + timestamp = t;
  185 +}
  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 +/*
  25 + * CPU specific code for the MPC8260
  26 + *
  27 + * written or collected and sometimes rewritten by
  28 + * Magnus Damm <damm@bitsmart.com>
  29 + *
  30 + * minor modifications by
  31 + * Wolfgang Denk <wd@denx.de>
  32 + *
  33 + * modified for 8260 by
  34 + * Murray Jensen <Murray.Jensen@cmst.csiro.au>
  35 + *
  36 + * added 8260 masks by
  37 + * Marius Groeger <mag@sysgo.de>
  38 + */
  39 +
  40 +#include <common.h>
  41 +#include <watchdog.h>
  42 +#include <command.h>
  43 +#include <mpc8260.h>
  44 +#include <asm/processor.h>
  45 +#include <asm/cpm_8260.h>
  46 +
  47 +int checkcpu (void)
  48 +{
  49 + DECLARE_GLOBAL_DATA_PTR;
  50 +
  51 + volatile immap_t *immap = (immap_t *) CFG_IMMR;
  52 + ulong clock = gd->cpu_clk;
  53 + uint pvr = get_pvr ();
  54 + uint immr, rev, m, k;
  55 + char buf[32];
  56 +
  57 + puts ("CPU: ");
  58 +
  59 + if (((pvr >> 16) & 0xff) != 0x81)
  60 + return -1; /* whoops! not an MPC8260 */
  61 + rev = pvr & 0xff;
  62 +
  63 + immr = immap->im_memctl.memc_immr;
  64 + if ((immr & IMMR_ISB_MSK) != CFG_IMMR)
  65 + return -1; /* whoops! someone moved the IMMR */
  66 +
  67 + printf ("MPC8260 (Rev %02x, Mask ", rev);
  68 +
  69 + /*
  70 + * the bottom 16 bits of the immr are the Part Number and Mask Number
  71 + * (4-34); the 16 bits at PROFF_REVNUM (0x8af0) in dual port ram is the
  72 + * RISC Microcode Revision Number (13-10).
  73 + * For the 8260, Motorola doesn't include the Microcode Revision
  74 + * in the mask.
  75 + */
  76 + m = immr & (IMMR_PARTNUM_MSK | IMMR_MASKNUM_MSK);
  77 + k = *((ushort *) & immap->im_dprambase[PROFF_REVNUM]);
  78 +
  79 + switch (m) {
  80 + case 0x0000:
  81 + printf ("0.2 2J24M");
  82 + break;
  83 + case 0x0010:
  84 + printf ("A.0 K22A");
  85 + break;
  86 + case 0x0011:
  87 + printf ("A.1 1K22A-XC");
  88 + break;
  89 + case 0x0001:
  90 + printf ("B.1 1K23A");
  91 + break;
  92 + case 0x0021:
  93 + printf ("B.2 2K23A-XC");
  94 + break;
  95 + case 0x0023:
  96 + printf ("B.3 3K23A");
  97 + break;
  98 + case 0x0024:
  99 + printf ("C.2 6K23A");
  100 + break;
  101 + case 0x0060:
  102 + printf ("A.0(A) 2K25A");
  103 + break;
  104 + default:
  105 + printf ("unknown [immr=0x%04x,k=0x%04x]", m, k);
  106 + break;
  107 + }
  108 +
  109 + printf (") at %s MHz\n", strmhz (buf, clock));
  110 +
  111 + return 0;
  112 +}
  113 +
  114 +/* ------------------------------------------------------------------------- */
  115 +/* configures a UPM by writing into the UPM RAM array */
  116 +/* uses bank 11 and a dummy physical address (=BRx_BA_MSK) */
  117 +/* NOTE: the physical address chosen must not overlap into any other area */
  118 +/* mapped by the memory controller because bank 11 has the lowest priority */
  119 +
  120 +void upmconfig (uint upm, uint * table, uint size)
  121 +{
  122 + volatile immap_t *immap = (immap_t *) CFG_IMMR;
  123 + volatile memctl8260_t *memctl = &immap->im_memctl;
  124 + volatile uchar *dummy = (uchar *) BRx_BA_MSK; /* set all BA bits */
  125 + uint i;
  126 +
  127 + /* first set up bank 11 to reference the correct UPM at a dummy address */
  128 +
  129 + memctl->memc_or11 = ORxU_AM_MSK; /* set all AM bits */
  130 +
  131 + switch (upm) {
  132 +
  133 + case UPMA:
  134 + memctl->memc_br11 =
  135 + ((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMA |
  136 + BRx_V;
  137 + memctl->memc_mamr = MxMR_OP_WARR;
  138 + break;
  139 +
  140 + case UPMB:
  141 + memctl->memc_br11 =
  142 + ((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMB |
  143 + BRx_V;
  144 + memctl->memc_mbmr = MxMR_OP_WARR;
  145 + break;
  146 +
  147 + case UPMC:
  148 + memctl->memc_br11 =
  149 + ((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMC |
  150 + BRx_V;
  151 + memctl->memc_mcmr = MxMR_OP_WARR;
  152 + break;
  153 +
  154 + default:
  155 + panic ("upmconfig passed invalid UPM number (%u)\n", upm);
  156 + break;
  157 +
  158 + }
  159 +
  160 + /*
  161 + * at this point, the dummy address is set up to access the selected UPM,
  162 + * the MAD pointer is zero, and the MxMR OP is set for writing to RAM
  163 + *
  164 + * now we simply load the mdr with each word and poke the dummy address.
  165 + * the MAD is incremented on each access.
  166 + */
  167 +
  168 + for (i = 0; i < size; i++) {
  169 + memctl->memc_mdr = table[i];
  170 + *dummy = 0;
  171 + }
  172 +
  173 + /* now kill bank 11 */
  174 + memctl->memc_br11 = 0;
  175 +}
  176 +
  177 +/* ------------------------------------------------------------------------- */
  178 +
  179 +int
  180 +do_reset (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
  181 +{
  182 + ulong msr, addr;
  183 +
  184 + volatile immap_t *immap = (immap_t *) CFG_IMMR;
  185 +
  186 + immap->im_clkrst.car_rmr = RMR_CSRE; /* Checkstop Reset enable */
  187 +
  188 + /* Interrupts and MMU off */
  189 + __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
  190 +
  191 + msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
  192 + __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
  193 +
  194 + /*
  195 + * Trying to execute the next instruction at a non-existing address
  196 + * should cause a machine check, resulting in reset
  197 + */
  198 +#ifdef CFG_RESET_ADDRESS
  199 + addr = CFG_RESET_ADDRESS;
  200 +#else
  201 + /*
  202 + * note: when CFG_MONITOR_BASE points to a RAM address, CFG_MONITOR_BASE
  203 + * - sizeof (ulong) is usually a valid address. Better pick an address
  204 + * known to be invalid on your system and assign it to CFG_RESET_ADDRESS.
  205 + */
  206 + addr = CFG_MONITOR_BASE - sizeof (ulong);
  207 +#endif
  208 + ((void (*)(void)) addr) ();
  209 + return 1;
  210 +
  211 +}
  212 +
  213 +/* ------------------------------------------------------------------------- */
  214 +
  215 +/*
  216 + * Get timebase clock frequency (like cpu_clk in Hz)
  217 + *
  218 + */
  219 +unsigned long get_tbclk (void)
  220 +{
  221 + DECLARE_GLOBAL_DATA_PTR;
  222 +
  223 + ulong tbclk;
  224 +
  225 + tbclk = (gd->bus_clk + 3L) / 4L;
  226 +
  227 + return (tbclk);
  228 +}
  229 +
  230 +/* ------------------------------------------------------------------------- */
  231 +
  232 +#if defined(CONFIG_WATCHDOG)
  233 +void watchdog_reset (void)
  234 +{
  235 + int re_enable = disable_interrupts ();
  236 +
  237 + reset_8260_watchdog ((immap_t *) CFG_IMMR);
  238 + if (re_enable)
  239 + enable_interrupts ();
  240 +}
  241 +#endif /* CONFIG_WATCHDOG */
  242 +
  243 +/* ------------------------------------------------------------------------- */
cpu/mpc8260/interrupts.c
  1 +/*
  2 + * (C) Copyright 2000-2002
  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 + * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 22-Oct-00
  24 + */
  25 +
  26 +#include <common.h>
  27 +#include <watchdog.h>
  28 +#include <command.h>
  29 +#include <mpc8260.h>
  30 +#include <mpc8260_irq.h>
  31 +#include <asm/processor.h>
  32 +
  33 +/****************************************************************************/
  34 +
  35 +unsigned decrementer_count; /* count val for 1e6/HZ microseconds */
  36 +
  37 +struct irq_action {
  38 + interrupt_handler_t *handler;
  39 + void *arg;
  40 + ulong count;
  41 +};
  42 +
  43 +static struct irq_action irq_handlers[NR_IRQS];
  44 +
  45 +static ulong ppc_cached_irq_mask[NR_MASK_WORDS];
  46 +
  47 +/****************************************************************************/
  48 +/* this section was ripped out of arch/ppc/kernel/ppc8260_pic.c in the */
  49 +/* Linux/PPC 2.4.x source. There was no copyright notice in that file. */
  50 +
  51 +/* The 8260 internal interrupt controller. It is usually
  52 + * the only interrupt controller.
  53 + * There are two 32-bit registers (high/low) for up to 64
  54 + * possible interrupts.
  55 + *
  56 + * Now, the fun starts.....Interrupt Numbers DO NOT MAP
  57 + * in a simple arithmetic fashion to mask or pending registers.
  58 + * That is, interrupt 4 does not map to bit position 4.
  59 + * We create two tables, indexed by vector number, to indicate
  60 + * which register to use and which bit in the register to use.
  61 + */
  62 +static u_char irq_to_siureg[] = {
  63 + 1, 1, 1, 1, 1, 1, 1, 1,
  64 + 1, 1, 1, 1, 1, 1, 1, 1,
  65 + 0, 0, 0, 0, 0, 0, 0, 0,
  66 + 0, 0, 0, 0, 0, 0, 0, 0,
  67 + 1, 1, 1, 1, 1, 1, 1, 1,
  68 + 1, 1, 1, 1, 1, 1, 1, 1,
  69 + 0, 0, 0, 0, 0, 0, 0, 0,
  70 + 0, 0, 0, 0, 0, 0, 0, 0
  71 +};
  72 +
  73 +static u_char irq_to_siubit[] = {
  74 + 31, 16, 17, 18, 19, 20, 21, 22,
  75 + 23, 24, 25, 26, 27, 28, 29, 30,
  76 + 29, 30, 16, 17, 18, 19, 20, 21,
  77 + 22, 23, 24, 25, 26, 27, 28, 31,
  78 + 0, 1, 2, 3, 4, 5, 6, 7,
  79 + 8, 9, 10, 11, 12, 13, 14, 15,
  80 + 15, 14, 13, 12, 11, 10, 9, 8,
  81 + 7, 6, 5, 4, 3, 2, 1, 0
  82 +};
  83 +
  84 +static void m8260_mask_irq (unsigned int irq_nr)
  85 +{
  86 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  87 + int bit, word;
  88 + volatile uint *simr;
  89 +
  90 + bit = irq_to_siubit[irq_nr];
  91 + word = irq_to_siureg[irq_nr];
  92 +
  93 + simr = &(immr->im_intctl.ic_simrh);
  94 + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
  95 + simr[word] = ppc_cached_irq_mask[word];
  96 +}
  97 +
  98 +static void m8260_unmask_irq (unsigned int irq_nr)
  99 +{
  100 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  101 + int bit, word;
  102 + volatile uint *simr;
  103 +
  104 + bit = irq_to_siubit[irq_nr];
  105 + word = irq_to_siureg[irq_nr];
  106 +
  107 + simr = &(immr->im_intctl.ic_simrh);
  108 + ppc_cached_irq_mask[word] |= (1 << (31 - bit));
  109 + simr[word] = ppc_cached_irq_mask[word];
  110 +}
  111 +
  112 +static void m8260_mask_and_ack (unsigned int irq_nr)
  113 +{
  114 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  115 + int bit, word;
  116 + volatile uint *simr, *sipnr;
  117 +
  118 + bit = irq_to_siubit[irq_nr];
  119 + word = irq_to_siureg[irq_nr];
  120 +
  121 + simr = &(immr->im_intctl.ic_simrh);
  122 + sipnr = &(immr->im_intctl.ic_sipnrh);
  123 + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
  124 + simr[word] = ppc_cached_irq_mask[word];
  125 + sipnr[word] = 1 << (31 - bit);
  126 +}
  127 +
  128 +static int m8260_get_irq (struct pt_regs *regs)
  129 +{
  130 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  131 + int irq;
  132 + unsigned long bits;
  133 +
  134 + /* For MPC8260, read the SIVEC register and shift the bits down
  135 + * to get the irq number. */
  136 + bits = immr->im_intctl.ic_sivec;
  137 + irq = bits >> 26;
  138 + return irq;
  139 +}
  140 +
  141 +/* end of code ripped out of arch/ppc/kernel/ppc8260_pic.c */
  142 +/****************************************************************************/
  143 +
  144 +static __inline__ unsigned long get_msr (void)
  145 +{
  146 + unsigned long msr;
  147 +
  148 + __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
  149 +
  150 + return msr;
  151 +}
  152 +
  153 +static __inline__ void set_msr (unsigned long msr)
  154 +{
  155 + __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
  156 +}
  157 +
  158 +static __inline__ unsigned long get_dec (void)
  159 +{
  160 + unsigned long val;
  161 +
  162 + __asm__ __volatile__ ("mfdec %0":"=r" (val):);
  163 +
  164 + return val;
  165 +}
  166 +
  167 +static __inline__ void set_dec (unsigned long val)
  168 +{
  169 + __asm__ __volatile__ ("mtdec %0"::"r" (val));
  170 +}
  171 +
  172 +void enable_interrupts (void)
  173 +{
  174 + set_msr (get_msr () | MSR_EE);
  175 +}
  176 +
  177 +/* returns flag if MSR_EE was set before */
  178 +int disable_interrupts (void)
  179 +{
  180 + ulong msr = get_msr ();
  181 +
  182 + set_msr (msr & ~MSR_EE);
  183 + return ((msr & MSR_EE) != 0);
  184 +}
  185 +
  186 +/****************************************************************************/
  187 +
  188 +int interrupt_init (void)
  189 +{
  190 + DECLARE_GLOBAL_DATA_PTR;
  191 +
  192 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  193 +
  194 + decrementer_count = (gd->bus_clk / 4) / CFG_HZ;
  195 +
  196 + /* Initialize the default interrupt mapping priorities */
  197 + immr->im_intctl.ic_sicr = 0;
  198 + immr->im_intctl.ic_siprr = 0x05309770;
  199 + immr->im_intctl.ic_scprrh = 0x05309770;
  200 + immr->im_intctl.ic_scprrl = 0x05309770;
  201 +
  202 + /* disable all interrupts and clear all pending bits */
  203 + immr->im_intctl.ic_simrh = ppc_cached_irq_mask[0] = 0;
  204 + immr->im_intctl.ic_simrl = ppc_cached_irq_mask[1] = 0;
  205 + immr->im_intctl.ic_sipnrh = 0xffffffff;
  206 + immr->im_intctl.ic_sipnrl = 0xffffffff;
  207 +
  208 + set_dec (decrementer_count);
  209 +
  210 + set_msr (get_msr () | MSR_EE);
  211 +
  212 + return (0);
  213 +}
  214 +
  215 +/****************************************************************************/
  216 +
  217 +/*
  218 + * Handle external interrupts
  219 + */
  220 +void external_interrupt (struct pt_regs *regs)
  221 +{
  222 + int irq, unmask = 1;
  223 +
  224 + irq = m8260_get_irq (regs);
  225 +
  226 + m8260_mask_and_ack (irq);
  227 +
  228 + set_msr (get_msr () | MSR_EE);
  229 +
  230 + if (irq_handlers[irq].handler != NULL)
  231 + (*irq_handlers[irq].handler) (irq_handlers[irq].arg);
  232 + else {
  233 + printf ("\nBogus External Interrupt IRQ %d\n", irq);
  234 + /*
  235 + * turn off the bogus interrupt, otherwise it
  236 + * might repeat forever
  237 + */
  238 + unmask = 0;
  239 + }
  240 +
  241 + if (unmask)
  242 + m8260_unmask_irq (irq);
  243 +}
  244 +
  245 +/****************************************************************************/
  246 +
  247 +/*
  248 + * Install and free an interrupt handler.
  249 + */
  250 +
  251 +void
  252 +irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
  253 +{
  254 + if (irq < 0 || irq >= NR_IRQS) {
  255 + printf ("irq_install_handler: bad irq number %d\n", irq);
  256 + return;
  257 + }
  258 +
  259 + if (irq_handlers[irq].handler != NULL)
  260 + printf ("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
  261 + (ulong) handler, (ulong) irq_handlers[irq].handler);
  262 +
  263 + irq_handlers[irq].handler = handler;
  264 + irq_handlers[irq].arg = arg;
  265 +
  266 + m8260_unmask_irq (irq);
  267 +}
  268 +
  269 +void irq_free_handler (int irq)
  270 +{
  271 + if (irq < 0 || irq >= NR_IRQS) {
  272 + printf ("irq_free_handler: bad irq number %d\n", irq);
  273 + return;
  274 + }
  275 +
  276 + m8260_mask_irq (irq);
  277 +
  278 + irq_handlers[irq].handler = NULL;
  279 + irq_handlers[irq].arg = NULL;
  280 +}
  281 +
  282 +/****************************************************************************/
  283 +
  284 +volatile ulong timestamp = 0;
  285 +
  286 +/*
  287 + * timer_interrupt - gets called when the decrementer overflows,
  288 + * with interrupts disabled.
  289 + * Trivial implementation - no need to be really accurate.
  290 + */
  291 +void timer_interrupt (struct pt_regs *regs)
  292 +{
  293 +#if defined(CONFIG_WATCHDOG) || defined(CFG_HYMOD_DBLEDS)
  294 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  295 +#endif /* CONFIG_WATCHDOG */
  296 +
  297 + /* Restore Decrementer Count */
  298 + set_dec (decrementer_count);
  299 +
  300 + timestamp++;
  301 +
  302 +#if defined(CONFIG_WATCHDOG) || \
  303 + defined(CFG_CMA_LCD_HEARTBEAT) || \
  304 + defined(CFG_HYMOD_DBLEDS)
  305 +
  306 + if ((timestamp % CFG_HZ) == 0) {
  307 +#if defined(CFG_CMA_LCD_HEARTBEAT)
  308 + extern void lcd_heartbeat (void);
  309 +#endif /* CFG_CMA_LCD_HEARTBEAT */
  310 +#if defined(CFG_HYMOD_DBLEDS)
  311 + volatile iop8260_t *iop = &immr->im_ioport;
  312 + static int shift = 0;
  313 +#endif /* CFG_HYMOD_DBLEDS */
  314 +
  315 +#if defined(CFG_CMA_LCD_HEARTBEAT)
  316 + lcd_heartbeat ();
  317 +#endif /* CFG_CMA_LCD_HEARTBEAT */
  318 +
  319 +#if defined(CONFIG_WATCHDOG)
  320 + reset_8260_watchdog (immr);
  321 +#endif /* CONFIG_WATCHDOG */
  322 +
  323 +#if defined(CFG_HYMOD_DBLEDS)
  324 + /* hymod daughter board LEDs */
  325 + if (++shift > 3)
  326 + shift = 0;
  327 + iop->iop_pdatd =
  328 + (iop->iop_pdatd & ~0x0f000000) | (1 << (24 + shift));
  329 +#endif /* CFG_HYMOD_DBLEDS */
  330 + }
  331 +#endif /* CONFIG_WATCHDOG || CFG_CMA_LCD_HEARTBEAT */
  332 +}
  333 +
  334 +/****************************************************************************/
  335 +
  336 +void reset_timer (void)
  337 +{
  338 + timestamp = 0;
  339 +}
  340 +
  341 +ulong get_timer (ulong base)
  342 +{
  343 + return (timestamp - base);
  344 +}
  345 +
  346 +void set_timer (ulong t)
  347 +{
  348 + timestamp = t;
  349 +}
  350 +
  351 +/****************************************************************************/
  352 +
  353 +#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
  354 +
  355 +/* ripped this out of ppc4xx/interrupts.c */
  356 +
  357 +/*******************************************************************************
  358 +*
  359 +* irqinfo - print information about PCI devices
  360 +*
  361 +*/
  362 +void
  363 +do_irqinfo (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
  364 +{
  365 + int irq, re_enable;
  366 +
  367 + re_enable = disable_interrupts ();
  368 +
  369 + printf ("\nInterrupt-Information:\n");
  370 + printf ("Nr Routine Arg Count\n");
  371 +
  372 + for (irq = 0; irq < 32; irq++)
  373 + if (irq_handlers[irq].handler != NULL)
  374 + printf ("%02d %08lx %08lx %ld\n", irq,
  375 + (ulong) irq_handlers[irq].handler,
  376 + (ulong) irq_handlers[irq].arg,
  377 + irq_handlers[irq].count);
  378 +
  379 + if (re_enable)
  380 + enable_interrupts ();
  381 +}
  382 +
  383 +#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
cpu/mpc8260/serial_scc.c
  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 + * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
  24 + */
  25 +
  26 +/*
  27 + * Minimal serial functions needed to use one of the SCC ports
  28 + * as serial console interface.
  29 + */
  30 +
  31 +#include <common.h>
  32 +#include <mpc8260.h>
  33 +#include <asm/cpm_8260.h>
  34 +
  35 +#if defined(CONFIG_CONS_ON_SCC)
  36 +
  37 +#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
  38 +
  39 +#define SCC_INDEX 0
  40 +#define PROFF_SCC PROFF_SCC1
  41 +#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
  42 + CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  43 +#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
  44 +#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
  45 +#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
  46 +
  47 +#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
  48 +
  49 +#define SCC_INDEX 1
  50 +#define PROFF_SCC PROFF_SCC2
  51 +#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
  52 + CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
  53 +#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
  54 +#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
  55 +#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
  56 +
  57 +#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
  58 +
  59 +#define SCC_INDEX 2
  60 +#define PROFF_SCC PROFF_SCC3
  61 +#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
  62 + CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
  63 +#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
  64 +#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
  65 +#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
  66 +
  67 +#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
  68 +
  69 +#define SCC_INDEX 3
  70 +#define PROFF_SCC PROFF_SCC4
  71 +#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
  72 + CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
  73 +#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
  74 +#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
  75 +#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
  76 +
  77 +#else
  78 +
  79 +#error "console not correctly defined"
  80 +
  81 +#endif
  82 +
  83 +int serial_init (void)
  84 +{
  85 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  86 + volatile scc_t *sp;
  87 + volatile scc_uart_t *up;
  88 + volatile cbd_t *tbdf, *rbdf;
  89 + volatile cpm8260_t *cp = &(im->im_cpm);
  90 + uint dpaddr;
  91 +
  92 + /* initialize pointers to SCC */
  93 +
  94 + sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
  95 + up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  96 +
  97 + /* Disable transmitter/receiver.
  98 + */
  99 + sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  100 +
  101 + /* put the SCC channel into NMSI (non multiplexd serial interface)
  102 + * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
  103 + */
  104 + im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
  105 +
  106 + /* Set up the baud rate generator.
  107 + */
  108 + serial_setbrg ();
  109 +
  110 + /* Allocate space for two buffer descriptors in the DP ram.
  111 + * damm: allocating space after the two buffers for rx/tx data
  112 + */
  113 +
  114 + dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  115 +
  116 + /* Set the physical address of the host memory buffers in
  117 + * the buffer descriptors.
  118 + */
  119 + rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
  120 + rbdf->cbd_bufaddr = (uint) (rbdf+2);
  121 + rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
  122 + tbdf = rbdf + 1;
  123 + tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  124 + tbdf->cbd_sc = BD_SC_WRAP;
  125 +
  126 + /* Set up the uart parameters in the parameter ram.
  127 + */
  128 + up->scc_genscc.scc_rbase = dpaddr;
  129 + up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
  130 + up->scc_genscc.scc_rfcr = CPMFCR_EB;
  131 + up->scc_genscc.scc_tfcr = CPMFCR_EB;
  132 + up->scc_genscc.scc_mrblr = 1;
  133 + up->scc_maxidl = 0;
  134 + up->scc_brkcr = 1;
  135 + up->scc_parec = 0;
  136 + up->scc_frmec = 0;
  137 + up->scc_nosec = 0;
  138 + up->scc_brkec = 0;
  139 + up->scc_uaddr1 = 0;
  140 + up->scc_uaddr2 = 0;
  141 + up->scc_toseq = 0;
  142 + up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
  143 + up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
  144 + up->scc_rccm = 0xc0ff;
  145 +
  146 + /* Mask all interrupts and remove anything pending.
  147 + */
  148 + sp->scc_sccm = 0;
  149 + sp->scc_scce = 0xffff;
  150 +
  151 + /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
  152 + */
  153 + sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
  154 + sp->scc_gsmrl = \
  155 + SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
  156 +
  157 + /* Set CTS flow control, 1 stop bit, 8 bit character length,
  158 + * normal async UART mode, no parity
  159 + */
  160 + sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
  161 +
  162 + /* execute the "Init Rx and Tx params" CP command.
  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_SCC_PAGE, CPM_CR_SCC_SBLOCK,
  169 + 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  170 +
  171 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  172 + ;
  173 +
  174 + /* Enable transmitter/receiver.
  175 + */
  176 + sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
  177 +
  178 + return (0);
  179 +}
  180 +
  181 +void
  182 +serial_setbrg (void)
  183 +{
  184 + DECLARE_GLOBAL_DATA_PTR;
  185 +
  186 +#if defined(CONFIG_CONS_USE_EXTC)
  187 + m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
  188 + CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
  189 +#else
  190 + m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
  191 +#endif
  192 +}
  193 +
  194 +void
  195 +serial_putc(const char c)
  196 +{
  197 + volatile scc_uart_t *up;
  198 + volatile cbd_t *tbdf;
  199 + volatile immap_t *im;
  200 +
  201 + if (c == '\n')
  202 + serial_putc ('\r');
  203 +
  204 + im = (immap_t *)CFG_IMMR;
  205 + up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  206 + tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
  207 +
  208 + /* Wait for last character to go.
  209 + */
  210 + while (tbdf->cbd_sc & BD_SC_READY)
  211 + ;
  212 +
  213 + /* Load the character into the transmit buffer.
  214 + */
  215 + *(volatile char *)tbdf->cbd_bufaddr = c;
  216 + tbdf->cbd_datlen = 1;
  217 + tbdf->cbd_sc |= BD_SC_READY;
  218 +}
  219 +
  220 +void
  221 +serial_puts (const char *s)
  222 +{
  223 + while (*s) {
  224 + serial_putc (*s++);
  225 + }
  226 +}
  227 +
  228 +int
  229 +serial_getc(void)
  230 +{
  231 + volatile cbd_t *rbdf;
  232 + volatile scc_uart_t *up;
  233 + volatile immap_t *im;
  234 + unsigned char c;
  235 +
  236 + im = (immap_t *)CFG_IMMR;
  237 + up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  238 + rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
  239 +
  240 + /* Wait for character to show up.
  241 + */
  242 + while (rbdf->cbd_sc & BD_SC_EMPTY)
  243 + ;
  244 +
  245 + /* Grab the char and clear the buffer again.
  246 + */
  247 + c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
  248 + rbdf->cbd_sc |= BD_SC_EMPTY;
  249 +
  250 + return (c);
  251 +}
  252 +
  253 +int
  254 +serial_tstc()
  255 +{
  256 + volatile cbd_t *rbdf;
  257 + volatile scc_uart_t *up;
  258 + volatile immap_t *im;
  259 +
  260 + im = (immap_t *)CFG_IMMR;
  261 + up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  262 + rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
  263 +
  264 + return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
  265 +}
  266 +
  267 +#endif /* CONFIG_CONS_ON_SCC */
  268 +
  269 +#if defined(CONFIG_KGDB_ON_SCC)
  270 +
  271 +#if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
  272 +#error Whoops! serial console and kgdb are on the same scc serial port
  273 +#endif
  274 +
  275 +#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SCC1 */
  276 +
  277 +#define KGDB_SCC_INDEX 0
  278 +#define KGDB_PROFF_SCC PROFF_SCC1
  279 +#define KGDB_CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
  280 + CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  281 +#define KGDB_CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
  282 +#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
  283 +#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
  284 +
  285 +#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SCC2 */
  286 +
  287 +#define KGDB_SCC_INDEX 1
  288 +#define KGDB_PROFF_SCC PROFF_SCC2
  289 +#define KGDB_CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
  290 + CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
  291 +#define KGDB_CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
  292 +#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
  293 +#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
  294 +
  295 +#elif CONFIG_KGDB_INDEX == 3 /* KGDB Port on SCC3 */
  296 +
  297 +#define KGDB_SCC_INDEX 2
  298 +#define KGDB_PROFF_SCC PROFF_SCC3
  299 +#define KGDB_CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
  300 + CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
  301 +#define KGDB_CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
  302 +#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
  303 +#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
  304 +
  305 +#elif CONFIG_KGDB_INDEX == 4 /* KGDB Port on SCC4 */
  306 +
  307 +#define KGDB_SCC_INDEX 3
  308 +#define KGDB_PROFF_SCC PROFF_SCC4
  309 +#define KGDB_CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
  310 + CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
  311 +#define KGDB_CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
  312 +#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
  313 +#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
  314 +
  315 +#else
  316 +
  317 +#error "kgdb serial port not correctly defined"
  318 +
  319 +#endif
  320 +
  321 +void
  322 +kgdb_serial_init (void)
  323 +{
  324 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  325 + volatile scc_t *sp;
  326 + volatile scc_uart_t *up;
  327 + volatile cbd_t *tbdf, *rbdf;
  328 + volatile cpm8260_t *cp = &(im->im_cpm);
  329 + uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
  330 + char *s, *e;
  331 +
  332 + if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
  333 + ulong rate = simple_strtoul(s, &e, 10);
  334 + if (e > s && *e == '\0')
  335 + speed = rate;
  336 + }
  337 +
  338 + /* initialize pointers to SCC */
  339 +
  340 + sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
  341 + up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
  342 +
  343 + /* Disable transmitter/receiver.
  344 + */
  345 + sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  346 +
  347 + /* put the SCC channel into NMSI (non multiplexd serial interface)
  348 + * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
  349 + */
  350 + im->im_cpmux.cmx_scr = \
  351 + (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
  352 +
  353 + /* Set up the baud rate generator.
  354 + */
  355 +#if defined(CONFIG_KGDB_USE_EXTC)
  356 + m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
  357 + CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
  358 +#else
  359 + m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
  360 +#endif
  361 +
  362 + /* Allocate space for two buffer descriptors in the DP ram.
  363 + * damm: allocating space after the two buffers for rx/tx data
  364 + */
  365 +
  366 + dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  367 +
  368 + /* Set the physical address of the host memory buffers in
  369 + * the buffer descriptors.
  370 + */
  371 + rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
  372 + rbdf->cbd_bufaddr = (uint) (rbdf+2);
  373 + rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
  374 + tbdf = rbdf + 1;
  375 + tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  376 + tbdf->cbd_sc = BD_SC_WRAP;
  377 +
  378 + /* Set up the uart parameters in the parameter ram.
  379 + */
  380 + up->scc_genscc.scc_rbase = dpaddr;
  381 + up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
  382 + up->scc_genscc.scc_rfcr = CPMFCR_EB;
  383 + up->scc_genscc.scc_tfcr = CPMFCR_EB;
  384 + up->scc_genscc.scc_mrblr = 1;
  385 + up->scc_maxidl = 0;
  386 + up->scc_brkcr = 1;
  387 + up->scc_parec = 0;
  388 + up->scc_frmec = 0;
  389 + up->scc_nosec = 0;
  390 + up->scc_brkec = 0;
  391 + up->scc_uaddr1 = 0;
  392 + up->scc_uaddr2 = 0;
  393 + up->scc_toseq = 0;
  394 + up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
  395 + up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
  396 + up->scc_rccm = 0xc0ff;
  397 +
  398 + /* Mask all interrupts and remove anything pending.
  399 + */
  400 + sp->scc_sccm = 0;
  401 + sp->scc_scce = 0xffff;
  402 +
  403 + /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
  404 + */
  405 + sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
  406 + sp->scc_gsmrl = \
  407 + SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
  408 +
  409 + /* Set CTS flow control, 1 stop bit, 8 bit character length,
  410 + * normal async UART mode, no parity
  411 + */
  412 + sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
  413 +
  414 + /* execute the "Init Rx and Tx params" CP command.
  415 + */
  416 +
  417 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  418 + ;
  419 +
  420 + cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
  421 + 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  422 +
  423 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  424 + ;
  425 +
  426 + /* Enable transmitter/receiver.
  427 + */
  428 + sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
  429 +
  430 + printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
  431 +}
  432 +
  433 +void
  434 +putDebugChar(const char c)
  435 +{
  436 + volatile scc_uart_t *up;
  437 + volatile cbd_t *tbdf;
  438 + volatile immap_t *im;
  439 +
  440 + if (c == '\n')
  441 + putDebugChar ('\r');
  442 +
  443 + im = (immap_t *)CFG_IMMR;
  444 + up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
  445 + tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
  446 +
  447 + /* Wait for last character to go.
  448 + */
  449 + while (tbdf->cbd_sc & BD_SC_READY)
  450 + ;
  451 +
  452 + /* Load the character into the transmit buffer.
  453 + */
  454 + *(volatile char *)tbdf->cbd_bufaddr = c;
  455 + tbdf->cbd_datlen = 1;
  456 + tbdf->cbd_sc |= BD_SC_READY;
  457 +}
  458 +
  459 +void
  460 +putDebugStr (const char *s)
  461 +{
  462 + while (*s) {
  463 + putDebugChar (*s++);
  464 + }
  465 +}
  466 +
  467 +int
  468 +getDebugChar(void)
  469 +{
  470 + volatile cbd_t *rbdf;
  471 + volatile scc_uart_t *up;
  472 + volatile immap_t *im;
  473 + unsigned char c;
  474 +
  475 + im = (immap_t *)CFG_IMMR;
  476 + up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
  477 + rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
  478 +
  479 + /* Wait for character to show up.
  480 + */
  481 + while (rbdf->cbd_sc & BD_SC_EMPTY)
  482 + ;
  483 +
  484 + /* Grab the char and clear the buffer again.
  485 + */
  486 + c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
  487 + rbdf->cbd_sc |= BD_SC_EMPTY;
  488 +
  489 + return (c);
  490 +}
  491 +
  492 +void
  493 +kgdb_interruptible(int yes)
  494 +{
  495 + return;
  496 +}
  497 +
  498 +#endif /* CONFIG_KGDB_ON_SCC */
cpu/mpc8260/serial_smc.c
  1 +/*
  2 + * (C) Copyright 2000, 2001, 2002
  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 + * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
  24 + * changes based on the file arch/ppc/mbxboot/m8260_tty.c from the
  25 + * Linux/PPC sources (m8260_tty.c had no copyright info in it).
  26 + */
  27 +
  28 +/*
  29 + * Minimal serial functions needed to use one of the SMC ports
  30 + * as serial console interface.
  31 + */
  32 +
  33 +#include <common.h>
  34 +#include <mpc8260.h>
  35 +#include <asm/cpm_8260.h>
  36 +
  37 +#if defined(CONFIG_CONS_ON_SMC)
  38 +
  39 +#if CONFIG_CONS_INDEX == 1 /* Console on SMC1 */
  40 +
  41 +#define SMC_INDEX 0
  42 +#define PROFF_SMC_BASE PROFF_SMC1_BASE
  43 +#define PROFF_SMC PROFF_SMC1
  44 +#define CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
  45 +#define CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
  46 +#define CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
  47 +#define CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
  48 +
  49 +#elif CONFIG_CONS_INDEX == 2 /* Console on SMC2 */
  50 +
  51 +#define SMC_INDEX 1
  52 +#define PROFF_SMC_BASE PROFF_SMC2_BASE
  53 +#define PROFF_SMC PROFF_SMC2
  54 +#define CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
  55 +#define CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
  56 +#define CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
  57 +#define CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
  58 +
  59 +#else
  60 +
  61 +#error "console not correctly defined"
  62 +
  63 +#endif
  64 +
  65 +/* map rs_table index to baud rate generator index */
  66 +static unsigned char brg_map[] = {
  67 + 6, /* BRG7 for SMC1 */
  68 + 7, /* BRG8 for SMC2 */
  69 + 0, /* BRG1 for SCC1 */
  70 + 1, /* BRG1 for SCC2 */
  71 + 2, /* BRG1 for SCC3 */
  72 + 3, /* BRG1 for SCC4 */
  73 +};
  74 +
  75 +int serial_init (void)
  76 +{
  77 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  78 + volatile smc_t *sp;
  79 + volatile smc_uart_t *up;
  80 + volatile cbd_t *tbdf, *rbdf;
  81 + volatile cpm8260_t *cp = &(im->im_cpm);
  82 + uint dpaddr;
  83 +
  84 + /* initialize pointers to SMC */
  85 +
  86 + sp = (smc_t *) &(im->im_smc[SMC_INDEX]);
  87 + *(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC;
  88 + up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC];
  89 +
  90 + /* Disable transmitter/receiver.
  91 + */
  92 + sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
  93 +
  94 + /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
  95 +
  96 + /* Allocate space for two buffer descriptors in the DP ram.
  97 + * damm: allocating space after the two buffers for rx/tx data
  98 + */
  99 +
  100 + dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  101 +
  102 + /* Set the physical address of the host memory buffers in
  103 + * the buffer descriptors.
  104 + */
  105 + rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
  106 + rbdf->cbd_bufaddr = (uint) (rbdf+2);
  107 + rbdf->cbd_sc = 0;
  108 + tbdf = rbdf + 1;
  109 + tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  110 + tbdf->cbd_sc = 0;
  111 +
  112 + /* Set up the uart parameters in the parameter ram.
  113 + */
  114 + up->smc_rbase = dpaddr;
  115 + up->smc_tbase = dpaddr+sizeof(cbd_t);
  116 + up->smc_rfcr = CPMFCR_EB;
  117 + up->smc_tfcr = CPMFCR_EB;
  118 + up->smc_brklen = 0;
  119 + up->smc_brkec = 0;
  120 + up->smc_brkcr = 0;
  121 +
  122 + /* Set UART mode, 8 bit, no parity, one stop.
  123 + * Enable receive and transmit.
  124 + */
  125 + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
  126 +
  127 + /* Mask all interrupts and remove anything pending.
  128 + */
  129 + sp->smc_smcm = 0;
  130 + sp->smc_smce = 0xff;
  131 +
  132 + /* put the SMC channel into NMSI (non multiplexd serial interface)
  133 + * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
  134 + */
  135 + im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE;
  136 +
  137 + /* Set up the baud rate generator.
  138 + */
  139 + serial_setbrg ();
  140 +
  141 + /* Make the first buffer the only buffer.
  142 + */
  143 + tbdf->cbd_sc |= BD_SC_WRAP;
  144 + rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
  145 +
  146 + /* Single character receive.
  147 + */
  148 + up->smc_mrblr = 1;
  149 + up->smc_maxidl = 0;
  150 +
  151 + /* Initialize Tx/Rx parameters.
  152 + */
  153 +
  154 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  155 + ;
  156 +
  157 + cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC_PAGE, CPM_CR_SMC_SBLOCK,
  158 + 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  159 +
  160 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  161 + ;
  162 +
  163 + /* Enable transmitter/receiver.
  164 + */
  165 + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
  166 +
  167 + return (0);
  168 +}
  169 +
  170 +void
  171 +serial_setbrg (void)
  172 +{
  173 + DECLARE_GLOBAL_DATA_PTR;
  174 +
  175 +#if defined(CONFIG_CONS_USE_EXTC)
  176 + m8260_cpm_extcbrg(brg_map[SMC_INDEX], gd->baudrate,
  177 + CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
  178 +#else
  179 + m8260_cpm_setbrg(brg_map[SMC_INDEX], gd->baudrate);
  180 +#endif
  181 +}
  182 +
  183 +void
  184 +serial_putc(const char c)
  185 +{
  186 + volatile cbd_t *tbdf;
  187 + volatile char *buf;
  188 + volatile smc_uart_t *up;
  189 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  190 +
  191 + if (c == '\n')
  192 + serial_putc ('\r');
  193 +
  194 + up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
  195 +
  196 + tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
  197 +
  198 + /* Wait for last character to go.
  199 + */
  200 + buf = (char *)tbdf->cbd_bufaddr;
  201 + while (tbdf->cbd_sc & BD_SC_READY)
  202 + ;
  203 +
  204 + *buf = c;
  205 + tbdf->cbd_datlen = 1;
  206 + tbdf->cbd_sc |= BD_SC_READY;
  207 +}
  208 +
  209 +void
  210 +serial_puts (const char *s)
  211 +{
  212 + while (*s) {
  213 + serial_putc (*s++);
  214 + }
  215 +}
  216 +
  217 +int
  218 +serial_getc(void)
  219 +{
  220 + volatile cbd_t *rbdf;
  221 + volatile unsigned char *buf;
  222 + volatile smc_uart_t *up;
  223 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  224 + unsigned char c;
  225 +
  226 + up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
  227 +
  228 + rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
  229 +
  230 + /* Wait for character to show up.
  231 + */
  232 + buf = (unsigned char *)rbdf->cbd_bufaddr;
  233 + while (rbdf->cbd_sc & BD_SC_EMPTY)
  234 + ;
  235 + c = *buf;
  236 + rbdf->cbd_sc |= BD_SC_EMPTY;
  237 +
  238 + return(c);
  239 +}
  240 +
  241 +int
  242 +serial_tstc()
  243 +{
  244 + volatile cbd_t *rbdf;
  245 + volatile smc_uart_t *up;
  246 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  247 +
  248 + up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
  249 +
  250 + rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
  251 +
  252 + return(!(rbdf->cbd_sc & BD_SC_EMPTY));
  253 +}
  254 +
  255 +#endif /* CONFIG_CONS_ON_SMC */
  256 +
  257 +#if defined(CONFIG_KGDB_ON_SMC)
  258 +
  259 +#if defined(CONFIG_CONS_ON_SMC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
  260 +#error Whoops! serial console and kgdb are on the same smc serial port
  261 +#endif
  262 +
  263 +#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SMC1 */
  264 +
  265 +#define KGDB_SMC_INDEX 0
  266 +#define KGDB_PROFF_SMC_BASE PROFF_SMC1_BASE
  267 +#define KGDB_PROFF_SMC PROFF_SMC1
  268 +#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
  269 +#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
  270 +#define KGDB_CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
  271 +#define KGDB_CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
  272 +
  273 +#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SMC2 */
  274 +
  275 +#define KGDB_SMC_INDEX 1
  276 +#define KGDB_PROFF_SMC_BASE PROFF_SMC2_BASE
  277 +#define KGDB_PROFF_SMC PROFF_SMC2
  278 +#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
  279 +#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
  280 +#define KGDB_CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
  281 +#define KGDB_CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
  282 +
  283 +#else
  284 +
  285 +#error "console not correctly defined"
  286 +
  287 +#endif
  288 +
  289 +void
  290 +kgdb_serial_init (void)
  291 +{
  292 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  293 + volatile smc_t *sp;
  294 + volatile smc_uart_t *up;
  295 + volatile cbd_t *tbdf, *rbdf;
  296 + volatile cpm8260_t *cp = &(im->im_cpm);
  297 + uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
  298 + char *s, *e;
  299 +
  300 + if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
  301 + ulong rate = simple_strtoul(s, &e, 10);
  302 + if (e > s && *e == '\0')
  303 + speed = rate;
  304 + }
  305 +
  306 + /* initialize pointers to SMC */
  307 +
  308 + sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]);
  309 + *(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC;
  310 + up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC];
  311 +
  312 + /* Disable transmitter/receiver.
  313 + */
  314 + sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
  315 +
  316 + /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
  317 +
  318 + /* Allocate space for two buffer descriptors in the DP ram.
  319 + * damm: allocating space after the two buffers for rx/tx data
  320 + */
  321 +
  322 + dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  323 +
  324 + /* Set the physical address of the host memory buffers in
  325 + * the buffer descriptors.
  326 + */
  327 + rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
  328 + rbdf->cbd_bufaddr = (uint) (rbdf+2);
  329 + rbdf->cbd_sc = 0;
  330 + tbdf = rbdf + 1;
  331 + tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  332 + tbdf->cbd_sc = 0;
  333 +
  334 + /* Set up the uart parameters in the parameter ram.
  335 + */
  336 + up->smc_rbase = dpaddr;
  337 + up->smc_tbase = dpaddr+sizeof(cbd_t);
  338 + up->smc_rfcr = CPMFCR_EB;
  339 + up->smc_tfcr = CPMFCR_EB;
  340 + up->smc_brklen = 0;
  341 + up->smc_brkec = 0;
  342 + up->smc_brkcr = 0;
  343 +
  344 + /* Set UART mode, 8 bit, no parity, one stop.
  345 + * Enable receive and transmit.
  346 + */
  347 + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
  348 +
  349 + /* Mask all interrupts and remove anything pending.
  350 + */
  351 + sp->smc_smcm = 0;
  352 + sp->smc_smce = 0xff;
  353 +
  354 + /* put the SMC channel into NMSI (non multiplexd serial interface)
  355 + * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
  356 + */
  357 + im->im_cpmux.cmx_smr =
  358 + (im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE;
  359 +
  360 + /* Set up the baud rate generator.
  361 + */
  362 +#if defined(CONFIG_KGDB_USE_EXTC)
  363 + m8260_cpm_extcbrg(KGDB_SMC_INDEX, speed,
  364 + CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
  365 +#else
  366 + m8260_cpm_setbrg(KGDB_SMC_INDEX, speed);
  367 +#endif
  368 +
  369 + /* Make the first buffer the only buffer.
  370 + */
  371 + tbdf->cbd_sc |= BD_SC_WRAP;
  372 + rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
  373 +
  374 + /* Single character receive.
  375 + */
  376 + up->smc_mrblr = 1;
  377 + up->smc_maxidl = 0;
  378 +
  379 + /* Initialize Tx/Rx parameters.
  380 + */
  381 +
  382 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  383 + ;
  384 +
  385 + cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SMC_PAGE, KGDB_CPM_CR_SMC_SBLOCK,
  386 + 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  387 +
  388 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  389 + ;
  390 +
  391 + /* Enable transmitter/receiver.
  392 + */
  393 + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
  394 +
  395 + printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
  396 +}
  397 +
  398 +void
  399 +putDebugChar(const char c)
  400 +{
  401 + volatile cbd_t *tbdf;
  402 + volatile char *buf;
  403 + volatile smc_uart_t *up;
  404 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  405 +
  406 + if (c == '\n')
  407 + putDebugChar ('\r');
  408 +
  409 + up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
  410 +
  411 + tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
  412 +
  413 + /* Wait for last character to go.
  414 + */
  415 + buf = (char *)tbdf->cbd_bufaddr;
  416 + while (tbdf->cbd_sc & BD_SC_READY)
  417 + ;
  418 +
  419 + *buf = c;
  420 + tbdf->cbd_datlen = 1;
  421 + tbdf->cbd_sc |= BD_SC_READY;
  422 +}
  423 +
  424 +void
  425 +putDebugStr (const char *s)
  426 +{
  427 + while (*s) {
  428 + putDebugChar (*s++);
  429 + }
  430 +}
  431 +
  432 +int
  433 +getDebugChar(void)
  434 +{
  435 + volatile cbd_t *rbdf;
  436 + volatile unsigned char *buf;
  437 + volatile smc_uart_t *up;
  438 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  439 + unsigned char c;
  440 +
  441 + up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
  442 +
  443 + rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
  444 +
  445 + /* Wait for character to show up.
  446 + */
  447 + buf = (unsigned char *)rbdf->cbd_bufaddr;
  448 + while (rbdf->cbd_sc & BD_SC_EMPTY)
  449 + ;
  450 + c = *buf;
  451 + rbdf->cbd_sc |= BD_SC_EMPTY;
  452 +
  453 + return(c);
  454 +}
  455 +
  456 +void
  457 +kgdb_interruptible(int yes)
  458 +{
  459 + return;
  460 +}
  461 +
  462 +#endif /* CONFIG_KGDB_ON_SMC */
  1 +/*
  2 + * (C) Copyright 2000-2002
  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 +#include <common.h>
  25 +#include <mpc8260.h>
  26 +#include <asm/processor.h>
  27 +
  28 +/* ------------------------------------------------------------------------- */
  29 +
  30 +/* Bus-to-Core Multiplier */
  31 +#define _1x 2
  32 +#define _1_5x 3
  33 +#define _2x 4
  34 +#define _2_5x 5
  35 +#define _3x 6
  36 +#define _3_5x 7
  37 +#define _4x 8
  38 +#define _4_5x 9
  39 +#define _5x 10
  40 +#define _5_5x 11
  41 +#define _6x 12
  42 +#define _6_5x 13
  43 +#define _7x 14
  44 +#define _7_5x 15
  45 +#define _8x 16
  46 +#define _byp -1
  47 +#define _off -2
  48 +#define _unk -3
  49 +
  50 +typedef struct {
  51 + int b2c_mult;
  52 + int vco_div;
  53 + char *freq_60x;
  54 + char *freq_core;
  55 +} corecnf_t;
  56 +
  57 +/*
  58 + * this table based on "Errata to MPC8260 PowerQUICC II User's Manual",
  59 + * Rev. 1, 8/2000, page 10.
  60 + */
  61 +corecnf_t corecnf_tab[] = {
  62 + { _1_5x, 4, " 33-100", " 33-100" }, /* 0x00 */
  63 + { _1x, 4, " 50-150", " 50-150" }, /* 0x01 */
  64 + { _1x, 8, " 25-75 ", " 25-75 " }, /* 0x02 */
  65 + { _byp, -1, " ?-? ", " ?-? " }, /* 0x03 */
  66 + { _2x, 2, " 50-150", "100-300" }, /* 0x04 */
  67 + { _2x, 4, " 25-75 ", " 50-150" }, /* 0x05 */
  68 + { _2_5x, 2, " 40-120", "100-240" }, /* 0x06 */
  69 + { _4_5x, 2, " 22-65 ", "100-300" }, /* 0x07 */
  70 + { _3x, 2, " 33-100", "100-300" }, /* 0x08 */
  71 + { _5_5x, 2, " 18-55 ", "100-300" }, /* 0x09 */
  72 + { _4x, 2, " 25-75 ", "100-300" }, /* 0x0A */
  73 + { _5x, 2, " 20-60 ", "100-300" }, /* 0x0B */
  74 + { _1_5x, 8, " 16-50 ", " 16-50 " }, /* 0x0C */
  75 + { _6x, 2, " 16-50 ", "100-300" }, /* 0x0D */
  76 + { _3_5x, 2, " 30-85 ", "100-300" }, /* 0x0E */
  77 + { _off, -1, " ?-? ", " ?-? " }, /* 0x0F */
  78 + { _3x, 4, " 16-50 ", " 50-150" }, /* 0x10 */
  79 + { _2_5x, 4, " 20-60 ", " 50-120" }, /* 0x11 */
  80 + { _6_5x, 2, " 15-46 ", "100-300" }, /* 0x12 */
  81 + { _byp, -1, " ?-? ", " ?-? " }, /* 0x13 */
  82 + { _7x, 2, " 14-43 ", "100-300" }, /* 0x14 */
  83 + { _2x, 4, " 25-75 ", " 50-150" }, /* 0x15 */
  84 + { _7_5x, 2, " 13-40 ", "100-300" }, /* 0x16 */
  85 + { _4_5x, 2, " 22-65 ", "100-300" }, /* 0x17 */
  86 + { _unk, -1, " ?-? ", " ?-? " }, /* 0x18 */
  87 + { _5_5x, 2, " 18-55 ", "100-300" }, /* 0x19 */
  88 + { _4x, 2, " 25-75 ", "100-300" }, /* 0x1A */
  89 + { _5x, 2, " 20-60 ", "100-300" }, /* 0x1B */
  90 + { _8x, 2, " 12-38 ", "100-300" }, /* 0x1C */
  91 + { _6x, 2, " 16-50 ", "100-300" }, /* 0x1D */
  92 + { _3_5x, 2, " 30-85 ", "100-300" }, /* 0x1E */
  93 + { _off, -1, " ?-? ", " ?-? " }, /* 0x1F */
  94 +};
  95 +
  96 +/* ------------------------------------------------------------------------- */
  97 +
  98 +/*
  99 + *
  100 + */
  101 +
  102 +int get_clocks (void)
  103 +{
  104 + DECLARE_GLOBAL_DATA_PTR;
  105 +
  106 + volatile immap_t *immap = (immap_t *) CFG_IMMR;
  107 + ulong clkin;
  108 + ulong sccr, dfbrg;
  109 + ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf;
  110 + corecnf_t *cp;
  111 +
  112 +#if !defined(CONFIG_8260_CLKIN)
  113 +#error clock measuring not implemented yet - define CONFIG_8260_CLKIN
  114 +#else
  115 + clkin = CONFIG_8260_CLKIN;
  116 +#endif
  117 +
  118 + sccr = immap->im_clkrst.car_sccr;
  119 + dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
  120 +
  121 + scmr = immap->im_clkrst.car_scmr;
  122 + corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
  123 + busdf = (scmr & SCMR_BUSDF_MSK) >> SCMR_BUSDF_SHIFT;
  124 + cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT;
  125 + plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
  126 + pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
  127 +
  128 + cp = &corecnf_tab[corecnf];
  129 +
  130 + gd->vco_out = (clkin * 2 * (pllmf + 1)) / (plldf + 1);
  131 +
  132 +#if 0
  133 + if (gd->vco_out / (busdf + 1) != clkin) {
  134 + /* aaarrrggghhh!!! */
  135 + return (1);
  136 + }
  137 +#endif
  138 +
  139 + gd->cpm_clk = gd->vco_out / 2;
  140 + gd->bus_clk = clkin;
  141 + gd->scc_clk = gd->vco_out / 4;
  142 + gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
  143 +
  144 + if (cp->b2c_mult > 0) {
  145 + gd->cpu_clk = (clkin * cp->b2c_mult) / 2;
  146 + } else {
  147 + gd->cpu_clk = clkin;
  148 + }
  149 +
  150 + return (0);
  151 +}
  152 +
  153 +int prt_8260_clks (void)
  154 +{
  155 + DECLARE_GLOBAL_DATA_PTR;
  156 +
  157 + volatile immap_t *immap = (immap_t *) CFG_IMMR;
  158 + ulong sccr, dfbrg;
  159 + ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf;
  160 + corecnf_t *cp;
  161 +
  162 + sccr = immap->im_clkrst.car_sccr;
  163 + dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
  164 +
  165 + scmr = immap->im_clkrst.car_scmr;
  166 + corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
  167 + busdf = (scmr & SCMR_BUSDF_MSK) >> SCMR_BUSDF_SHIFT;
  168 + cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT;
  169 + plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
  170 + pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
  171 +
  172 + cp = &corecnf_tab[corecnf];
  173 +
  174 + printf ("MPC8260 Clock Configuration\n - Bus-to-Core Mult ");
  175 +
  176 + switch (cp->b2c_mult) {
  177 + case _byp:
  178 + printf ("BYPASS");
  179 + break;
  180 +
  181 + case _off:
  182 + printf ("OFF");
  183 + break;
  184 +
  185 + case _unk:
  186 + printf ("UNKNOWN");
  187 + break;
  188 +
  189 + default:
  190 + printf ("%d%sx",
  191 + cp->b2c_mult / 2,
  192 + (cp->b2c_mult % 2) ? ".5" : "");
  193 + break;
  194 + }
  195 +
  196 + printf (", VCO Div %d, 60x Bus Freq %s, Core Freq %s\n",
  197 + cp->vco_div, cp->freq_60x, cp->freq_core);
  198 +
  199 + printf (" - dfbrg %ld, corecnf 0x%02lx, busdf %ld, cpmdf %ld, "
  200 + "plldf %ld, pllmf %ld\n", dfbrg, corecnf, busdf, cpmdf, plldf,
  201 + pllmf);
  202 +
  203 + printf (" - vco_out %10ld, scc_clk %10ld, brg_clk %10ld\n",
  204 + gd->vco_out, gd->scc_clk, gd->brg_clk);
  205 +
  206 + printf (" - cpu_clk %10ld, cpm_clk %10ld, bus_clk %10ld\n\n",
  207 + gd->cpu_clk, gd->cpm_clk, gd->bus_clk);
  208 + return (0);
  209 +}
  210 +
  211 +/* ------------------------------------------------------------------------- */
cpu/mpc8xx/cpu_init.c
  1 +/*
  2 + * (C) Copyright 2000-2002
  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 +#include <common.h>
  25 +#include <watchdog.h>
  26 +
  27 +#include <mpc8xx.h>
  28 +#include <commproc.h>
  29 +
  30 +#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH)
  31 +void cpm_load_patch (volatile immap_t * immr);
  32 +#endif
  33 +
  34 +/*
  35 + * Breath some life into the CPU...
  36 + *
  37 + * Set up the memory map,
  38 + * initialize a bunch of registers,
  39 + * initialize the UPM's
  40 + */
  41 +void cpu_init_f (volatile immap_t * immr)
  42 +{
  43 +#ifndef CONFIG_MBX
  44 + volatile memctl8xx_t *memctl = &immr->im_memctl;
  45 + ulong reg;
  46 +#endif
  47 +
  48 + /* SYPCR - contains watchdog control (11-9) */
  49 +
  50 + immr->im_siu_conf.sc_sypcr = CFG_SYPCR;
  51 +
  52 +#if defined(CONFIG_WATCHDOG)
  53 + reset_8xx_watchdog (immr);
  54 +#endif /* CONFIG_WATCHDOG */
  55 +
  56 + /* SIUMCR - contains debug pin configuration (11-6) */
  57 +
  58 + immr->im_siu_conf.sc_siumcr |= CFG_SIUMCR;
  59 +
  60 + /* initialize timebase status and control register (11-26) */
  61 + /* unlock TBSCRK */
  62 +
  63 + immr->im_sitk.sitk_tbscrk = KAPWR_KEY;
  64 + immr->im_sit.sit_tbscr = CFG_TBSCR;
  65 +
  66 + /* initialize the PIT (11-31) */
  67 +
  68 + immr->im_sitk.sitk_piscrk = KAPWR_KEY;
  69 + immr->im_sit.sit_piscr = CFG_PISCR;
  70 +
  71 + /* PLL (CPU clock) settings (15-30) */
  72 +
  73 + immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
  74 +
  75 +#ifndef CONFIG_MBX /* MBX board does things different */
  76 +
  77 + /* If CFG_PLPRCR (set in the various *_config.h files) tries to
  78 + * set the MF field, then just copy CFG_PLPRCR over car_plprcr,
  79 + * otherwise OR in CFG_PLPRCR so we do not change the currentMF
  80 + * field value.
  81 + */
  82 +#if ((CFG_PLPRCR & PLPRCR_MF_MSK) != 0)
  83 + reg = CFG_PLPRCR; /* reset control bits */
  84 +#else
  85 + reg = immr->im_clkrst.car_plprcr;
  86 + reg &= PLPRCR_MF_MSK; /* isolate MF field */
  87 + reg |= CFG_PLPRCR; /* reset control bits */
  88 +#endif
  89 + immr->im_clkrst.car_plprcr = reg;
  90 +
  91 + /* System integration timers. Don't change EBDF! (15-27) */
  92 +
  93 + immr->im_clkrstk.cark_sccrk = KAPWR_KEY;
  94 + reg = immr->im_clkrst.car_sccr;
  95 + reg &= SCCR_MASK;
  96 + reg |= CFG_SCCR;
  97 + immr->im_clkrst.car_sccr = reg;
  98 +
  99 + /*
  100 + * Memory Controller:
  101 + */
  102 +
  103 + /* perform BR0 reset that MPC850 Rev. A can't guarantee */
  104 + reg = memctl->memc_br0;
  105 + reg &= BR_PS_MSK; /* Clear everything except Port Size bits */
  106 + reg |= BR_V; /* then add just the "Bank Valid" bit */
  107 + memctl->memc_br0 = reg;
  108 +
  109 + /* Map banks 0 (and maybe 1) to the FLASH banks 0 (and 1) at
  110 + * preliminary addresses - these have to be modified later
  111 + * when FLASH size has been determined
  112 + *
  113 + * Depending on the size of the memory region defined by
  114 + * CFG_OR0_REMAP some boards (wide address mask) allow to map the
  115 + * CFG_MONITOR_BASE, while others (narrower address mask) can't
  116 + * map CFG_MONITOR_BASE.
  117 + *
  118 + * For example, for CONFIG_IVMS8, the CFG_MONITOR_BASE is
  119 + * 0xff000000, but CFG_OR0_REMAP's address mask is 0xfff80000.
  120 + *
  121 + * If BR0 wasn't loaded with address base 0xff000000, then BR0's
  122 + * base address remains as 0x00000000. However, the address mask
  123 + * have been narrowed to 512Kb, so CFG_MONITOR_BASE wasn't mapped
  124 + * into the Bank0.
  125 + *
  126 + * This is why CONFIG_IVMS8 and similar boards must load BR0 with
  127 + * CFG_BR0_PRELIM in advance.
  128 + *
  129 + * [Thanks to Michael Liao for this explanation.
  130 + * I owe him a free beer. - wd]
  131 + */
  132 +
  133 +#if defined(CONFIG_GTH) || \
  134 + defined(CONFIG_HERMES) || \
  135 + defined(CONFIG_ICU862) || \
  136 + defined(CONFIG_IP860) || \
  137 + defined(CONFIG_IVML24) || \
  138 + defined(CONFIG_IVMS8) || \
  139 + defined(CONFIG_LWMON) || \
  140 + defined(CONFIG_MHPC) || \
  141 + defined(CONFIG_PCU_E) || \
  142 + defined(CONFIG_R360MPI) || \
  143 + defined(CONFIG_RPXCLASSIC) || \
  144 + defined(CONFIG_RPXLITE) || \
  145 + defined(CONFIG_SPD823TS) || \
  146 + (defined(CONFIG_MPC860T) && defined(CONFIG_FADS))
  147 +
  148 + memctl->memc_br0 = CFG_BR0_PRELIM;
  149 +#endif
  150 +
  151 +#if defined(CFG_OR0_REMAP)
  152 + memctl->memc_or0 = CFG_OR0_REMAP;
  153 +#endif
  154 +#if defined(CFG_OR1_REMAP)
  155 + memctl->memc_or1 = CFG_OR1_REMAP;
  156 +#endif
  157 +#if defined(CFG_OR5_REMAP)
  158 + memctl->memc_or5 = CFG_OR5_REMAP;
  159 +#endif
  160 +
  161 + /* now restrict to preliminary range */
  162 + memctl->memc_br0 = CFG_BR0_PRELIM;
  163 + memctl->memc_or0 = CFG_OR0_PRELIM;
  164 +
  165 +#if (defined(CFG_OR1_PRELIM) && defined(CFG_BR1_PRELIM))
  166 + memctl->memc_or1 = CFG_OR1_PRELIM;
  167 + memctl->memc_br1 = CFG_BR1_PRELIM;
  168 +#endif
  169 +
  170 +#if defined(CONFIG_IP860) /* disable CS0 now that Flash is mapped on CS1 */
  171 + memctl->memc_br0 = 0;
  172 +#endif
  173 +
  174 +#if defined(CFG_OR2_PRELIM) && defined(CFG_BR2_PRELIM)
  175 + memctl->memc_or2 = CFG_OR2_PRELIM;
  176 + memctl->memc_br2 = CFG_BR2_PRELIM;
  177 +#endif
  178 +
  179 +#if defined(CFG_OR3_PRELIM) && defined(CFG_BR3_PRELIM)
  180 + memctl->memc_or3 = CFG_OR3_PRELIM;
  181 + memctl->memc_br3 = CFG_BR3_PRELIM;
  182 +#endif
  183 +
  184 +#if defined(CFG_OR4_PRELIM) && defined(CFG_BR4_PRELIM)
  185 + memctl->memc_or4 = CFG_OR4_PRELIM;
  186 + memctl->memc_br4 = CFG_BR4_PRELIM;
  187 +#endif
  188 +
  189 +#if defined(CFG_OR5_PRELIM) && defined(CFG_BR5_PRELIM)
  190 + memctl->memc_or5 = CFG_OR5_PRELIM;
  191 + memctl->memc_br5 = CFG_BR5_PRELIM;
  192 +#endif
  193 +
  194 +#if defined(CFG_OR6_PRELIM) && defined(CFG_BR6_PRELIM)
  195 + memctl->memc_or6 = CFG_OR6_PRELIM;
  196 + memctl->memc_br6 = CFG_BR6_PRELIM;
  197 +#endif
  198 +
  199 +#if defined(CFG_OR7_PRELIM) && defined(CFG_BR7_PRELIM)
  200 + memctl->memc_or7 = CFG_OR7_PRELIM;
  201 + memctl->memc_br7 = CFG_BR7_PRELIM;
  202 +#endif
  203 +
  204 +#endif /* ! CONFIG_MBX */
  205 +
  206 + /*
  207 + * Reset CPM
  208 + */
  209 + immr->im_cpm.cp_cpcr = CPM_CR_RST | CPM_CR_FLG;
  210 + do { /* Spin until command processed */
  211 + __asm__ ("eieio");
  212 + } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
  213 +
  214 +#ifdef CONFIG_MBX
  215 + /*
  216 + * on the MBX, things are a little bit different:
  217 + * - we need to read the VPD to get board information
  218 + * - the plprcr is set up dynamically
  219 + * - the memory controller is set up dynamically
  220 + */
  221 + mbx_init ();
  222 +#endif /* CONFIG_MBX */
  223 +
  224 +#ifdef CONFIG_RPXCLASSIC
  225 + rpxclassic_init ();
  226 +#endif
  227 +
  228 +#ifdef CFG_RCCR /* must be done before cpm_load_patch() */
  229 + /* write config value */
  230 + immr->im_cpm.cp_rccr = CFG_RCCR;
  231 +#endif
  232 +
  233 +#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH)
  234 + cpm_load_patch (immr); /* load mpc8xx microcode patch */
  235 +#endif
  236 +}
  237 +
  238 +/*
  239 + * initialize higher level parts of CPU like timers
  240 + */
  241 +int cpu_init_r (void)
  242 +{
  243 +#if defined(CFG_RTCSC) || defined(CFG_RMDS)
  244 + DECLARE_GLOBAL_DATA_PTR;
  245 +
  246 + bd_t *bd = gd->bd;
  247 + volatile immap_t *immr = (volatile immap_t *) (bd->bi_immr_base);
  248 +#endif
  249 +
  250 +#ifdef CFG_RTCSC
  251 + /* Unlock RTSC register */
  252 + immr->im_sitk.sitk_rtcsck = KAPWR_KEY;
  253 + /* write config value */
  254 + immr->im_sit.sit_rtcsc = CFG_RTCSC;
  255 +#endif
  256 +
  257 +#ifdef CFG_RMDS
  258 + /* write config value */
  259 + immr->im_cpm.cp_rmds = CFG_RMDS;
  260 +#endif
  261 + return (0);
  262 +}
  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 +#include <common.h>
  25 +#include <commproc.h>
  26 +#include <command.h>
  27 +
  28 +#if !defined(CONFIG_8xx_CONS_NONE) /* No Console at all */
  29 +
  30 +#if defined(CONFIG_8xx_CONS_SMC1) /* Console on SMC1 */
  31 +#define SMC_INDEX 0
  32 +#undef SCC_INDEX
  33 +#define PROFF_SMC PROFF_SMC1
  34 +#define CPM_CR_CH_SMC CPM_CR_CH_SMC1
  35 +
  36 +#elif defined(CONFIG_8xx_CONS_SMC2) /* Console on SMC2 */
  37 +#define SMC_INDEX 1
  38 +#undef SCC_INDEX
  39 +#define PROFF_SMC PROFF_SMC2
  40 +#define CPM_CR_CH_SMC CPM_CR_CH_SMC2
  41 +
  42 +#elif defined(CONFIG_8xx_CONS_SCC1) /* Console on SCC1 */
  43 +#undef SMC_INDEX
  44 +#define SCC_INDEX 0
  45 +#define PROFF_SCC PROFF_SCC1
  46 +#define CPM_CR_CH_SCC CPM_CR_CH_SCC1
  47 +
  48 +#elif defined(CONFIG_8xx_CONS_SCC2) /* Console on SCC2 */
  49 +#undef SMC_INDEX
  50 +#define SCC_INDEX 1
  51 +#define PROFF_SCC PROFF_SCC2
  52 +#define CPM_CR_CH_SCC CPM_CR_CH_SCC2
  53 +
  54 +#elif defined(CONFIG_8xx_CONS_SCC3) /* Console on SCC3 */
  55 +#undef SMC_INDEX
  56 +#define SCC_INDEX 2
  57 +#define PROFF_SCC PROFF_SCC3
  58 +#define CPM_CR_CH_SCC CPM_CR_CH_SCC3
  59 +
  60 +#elif defined(CONFIG_8xx_CONS_SCC4) /* Console on SCC4 */
  61 +#undef SMC_INDEX
  62 +#define SCC_INDEX 3
  63 +#define PROFF_SCC PROFF_SCC4
  64 +#define CPM_CR_CH_SCC CPM_CR_CH_SCC4
  65 +
  66 +#else /* CONFIG_8xx_CONS_? */
  67 +#error "console not correctly defined"
  68 +#endif
  69 +
  70 +#if (defined (CONFIG_8xx_CONS_SMC1) || defined (CONFIG_8xx_CONS_SMC2))
  71 +
  72 +/*
  73 + * Minimal serial functions needed to use one of the SMC ports
  74 + * as serial console interface.
  75 + */
  76 +
  77 +int serial_init (void)
  78 +{
  79 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  80 + volatile smc_t *sp;
  81 + volatile smc_uart_t *up;
  82 + volatile cbd_t *tbdf, *rbdf;
  83 + volatile cpm8xx_t *cp = &(im->im_cpm);
  84 +#if (!defined(CONFIG_8xx_CONS_SMC1)) && (defined(CONFIG_MPC823) || defined(CONFIG_MPC850))
  85 + volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
  86 +#endif
  87 + uint dpaddr;
  88 +
  89 + /* initialize pointers to SMC */
  90 +
  91 + sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]);
  92 + up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC];
  93 +
  94 + /* Disable transmitter/receiver.
  95 + */
  96 + sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
  97 +
  98 + /* Enable SDMA.
  99 + */
  100 + im->im_siu_conf.sc_sdcr = 1;
  101 +
  102 + /* clear error conditions */
  103 +#ifdef CFG_SDSR
  104 + im->im_sdma.sdma_sdsr = CFG_SDSR;
  105 +#else
  106 + im->im_sdma.sdma_sdsr = 0x83;
  107 +#endif
  108 +
  109 + /* clear SDMA interrupt mask */
  110 +#ifdef CFG_SDMR
  111 + im->im_sdma.sdma_sdmr = CFG_SDMR;
  112 +#else
  113 + im->im_sdma.sdma_sdmr = 0x00;
  114 +#endif
  115 +
  116 +#if defined(CONFIG_8xx_CONS_SMC1)
  117 + /* Use Port B for SMC1 instead of other functions.
  118 + */
  119 + cp->cp_pbpar |= 0x000000c0;
  120 + cp->cp_pbdir &= ~0x000000c0;
  121 + cp->cp_pbodr &= ~0x000000c0;
  122 +#else /* CONFIG_8xx_CONS_SMC2 */
  123 +# if defined(CONFIG_MPC823) || defined(CONFIG_MPC850)
  124 + /* Use Port A for SMC2 instead of other functions.
  125 + */
  126 + ip->iop_papar |= 0x00c0;
  127 + ip->iop_padir &= ~0x00c0;
  128 + ip->iop_paodr &= ~0x00c0;
  129 +# else /* must be a 860 then */
  130 + /* Use Port B for SMC2 instead of other functions.
  131 + */
  132 + cp->cp_pbpar |= 0x00000c00;
  133 + cp->cp_pbdir &= ~0x00000c00;
  134 + cp->cp_pbodr &= ~0x00000c00;
  135 +# endif
  136 +#endif
  137 +
  138 +#if defined(CONFIG_FADS)
  139 + /* Enable RS232 */
  140 +#if defined(CONFIG_8xx_CONS_SMC1)
  141 + *((uint *) BCSR1) &= ~BCSR1_RS232EN_1;
  142 +#else
  143 + *((uint *) BCSR1) &= ~BCSR1_RS232EN_2;
  144 +#endif
  145 +#endif /* CONFIG_FADS */
  146 +
  147 +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
  148 + /* Enable Monitor Port Transceiver */
  149 + *((uchar *) BCSR0) |= BCSR0_ENMONXCVR ;
  150 +#endif /* CONFIG_RPXLITE */
  151 +
  152 + /* Set the physical address of the host memory buffers in
  153 + * the buffer descriptors.
  154 + */
  155 +
  156 +#ifdef CFG_ALLOC_DPRAM
  157 + dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
  158 +#else
  159 + dpaddr = CPM_SERIAL_BASE ;
  160 +#endif
  161 +
  162 + /* Allocate space for two buffer descriptors in the DP ram.
  163 + * For now, this address seems OK, but it may have to
  164 + * change with newer versions of the firmware.
  165 + * damm: allocating space after the two buffers for rx/tx data
  166 + */
  167 +
  168 + rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
  169 + rbdf->cbd_bufaddr = (uint) (rbdf+2);
  170 + rbdf->cbd_sc = 0;
  171 + tbdf = rbdf + 1;
  172 + tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  173 + tbdf->cbd_sc = 0;
  174 +
  175 + /* Set up the uart parameters in the parameter ram.
  176 + */
  177 + up->smc_rbase = dpaddr;
  178 + up->smc_tbase = dpaddr+sizeof(cbd_t);
  179 + up->smc_rfcr = SMC_EB;
  180 + up->smc_tfcr = SMC_EB;
  181 +
  182 +#if defined(CONFIG_MBX)
  183 + board_serial_init();
  184 +#endif /* CONFIG_MBX */
  185 +
  186 + /* Set UART mode, 8 bit, no parity, one stop.
  187 + * Enable receive and transmit.
  188 + */
  189 + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
  190 +
  191 + /* Mask all interrupts and remove anything pending.
  192 + */
  193 + sp->smc_smcm = 0;
  194 + sp->smc_smce = 0xff;
  195 +
  196 + /* Set up the baud rate generator.
  197 + */
  198 + serial_setbrg ();
  199 +
  200 + /* Make the first buffer the only buffer.
  201 + */
  202 + tbdf->cbd_sc |= BD_SC_WRAP;
  203 + rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
  204 +
  205 + /* Single character receive.
  206 + */
  207 + up->smc_mrblr = 1;
  208 + up->smc_maxidl = 0;
  209 +
  210 + /* Initialize Tx/Rx parameters.
  211 + */
  212 +
  213 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  214 + ;
  215 +
  216 + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  217 +
  218 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  219 + ;
  220 +
  221 + /* Enable transmitter/receiver.
  222 + */
  223 + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
  224 +
  225 + return (0);
  226 +}
  227 +
  228 +void
  229 +serial_setbrg (void)
  230 +{
  231 + DECLARE_GLOBAL_DATA_PTR;
  232 +
  233 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  234 + volatile cpm8xx_t *cp = &(im->im_cpm);
  235 +
  236 + /* Set up the baud rate generator.
  237 + * See 8xx_io/commproc.c for details.
  238 + *
  239 + * Wire BRG1 to SMCx
  240 + */
  241 +
  242 + cp->cp_simode = 0x00000000;
  243 +
  244 + cp->cp_brgc1 =
  245 + (((gd->cpu_clk / 16 / gd->baudrate)-1) << 1) | CPM_BRG_EN;
  246 +}
  247 +
  248 +void
  249 +serial_putc(const char c)
  250 +{
  251 + volatile cbd_t *tbdf;
  252 + volatile char *buf;
  253 + volatile smc_uart_t *up;
  254 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  255 + volatile cpm8xx_t *cpmp = &(im->im_cpm);
  256 +
  257 + if (c == '\n')
  258 + serial_putc ('\r');
  259 +
  260 + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
  261 +
  262 + tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
  263 +
  264 + /* Wait for last character to go.
  265 + */
  266 +
  267 + buf = (char *)tbdf->cbd_bufaddr;
  268 +#if 0
  269 + __asm__("eieio");
  270 + while (tbdf->cbd_sc & BD_SC_READY)
  271 + __asm__("eieio");
  272 +#endif
  273 +
  274 + *buf = c;
  275 + tbdf->cbd_datlen = 1;
  276 + tbdf->cbd_sc |= BD_SC_READY;
  277 + __asm__("eieio");
  278 +#if 1
  279 + while (tbdf->cbd_sc & BD_SC_READY)
  280 + __asm__("eieio");
  281 +#endif
  282 +}
  283 +
  284 +int
  285 +serial_getc(void)
  286 +{
  287 + volatile cbd_t *rbdf;
  288 + volatile unsigned char *buf;
  289 + volatile smc_uart_t *up;
  290 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  291 + volatile cpm8xx_t *cpmp = &(im->im_cpm);
  292 + unsigned char c;
  293 +
  294 + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
  295 +
  296 + rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
  297 +
  298 + /* Wait for character to show up.
  299 + */
  300 + buf = (unsigned char *)rbdf->cbd_bufaddr;
  301 + while (rbdf->cbd_sc & BD_SC_EMPTY)
  302 + ;
  303 + c = *buf;
  304 + rbdf->cbd_sc |= BD_SC_EMPTY;
  305 +
  306 + return(c);
  307 +}
  308 +
  309 +int
  310 +serial_tstc()
  311 +{
  312 + volatile cbd_t *rbdf;
  313 + volatile smc_uart_t *up;
  314 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  315 + volatile cpm8xx_t *cpmp = &(im->im_cpm);
  316 +
  317 + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
  318 +
  319 + rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
  320 +
  321 + return(!(rbdf->cbd_sc & BD_SC_EMPTY));
  322 +}
  323 +
  324 +#else /* ! CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2 */
  325 +
  326 +int serial_init (void)
  327 +{
  328 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  329 + volatile scc_t *sp;
  330 + volatile scc_uart_t *up;
  331 + volatile cbd_t *tbdf, *rbdf;
  332 + volatile cpm8xx_t *cp = &(im->im_cpm);
  333 + uint dpaddr;
  334 +#if (SCC_INDEX != 2) || !defined(CONFIG_MPC850)
  335 + volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
  336 +#endif
  337 +
  338 + /* initialize pointers to SCC */
  339 +
  340 + sp = (scc_t *) &(cp->cp_scc[SCC_INDEX]);
  341 + up = (scc_uart_t *) &cp->cp_dparam[PROFF_SCC];
  342 +
  343 +#if defined(CONFIG_LWMON) && defined(CONFIG_8xx_CONS_SCC2)
  344 + { /* Disable Ethernet, enable Serial */
  345 + uchar c;
  346 +
  347 + c = pic_read (0x61);
  348 + c &= ~0x40; /* enable COM3 */
  349 + c |= 0x80; /* disable Ethernet */
  350 + pic_write (0x61, c);
  351 +
  352 + /* enable RTS2 */
  353 + cp->cp_pbpar |= 0x2000;
  354 + cp->cp_pbdat |= 0x2000;
  355 + cp->cp_pbdir |= 0x2000;
  356 + }
  357 +#endif /* CONFIG_LWMON */
  358 +
  359 + /* Disable transmitter/receiver.
  360 + */
  361 + sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  362 +
  363 +#if (SCC_INDEX == 2) && defined(CONFIG_MPC850)
  364 + /*
  365 + * The MPC850 has SCC3 on Port B
  366 + */
  367 + cp->cp_pbpar |= 0x06;
  368 + cp->cp_pbdir &= ~0x06;
  369 + cp->cp_pbodr &= ~0x06;
  370 +
  371 +#elif (SCC_INDEX < 2) || !defined(CONFIG_IP860)
  372 + /*
  373 + * Standard configuration for SCC's is on Part A
  374 + */
  375 + ip->iop_papar |= ((3 << (2 * SCC_INDEX)));
  376 + ip->iop_padir &= ~((3 << (2 * SCC_INDEX)));
  377 + ip->iop_paodr &= ~((3 << (2 * SCC_INDEX)));
  378 +#else
  379 + /*
  380 + * The IP860 has SCC3 and SCC4 on Port D
  381 + */
  382 + ip->iop_pdpar |= ((3 << (2 * SCC_INDEX)));
  383 +#endif
  384 +
  385 + /* Allocate space for two buffer descriptors in the DP ram.
  386 + */
  387 +
  388 +#ifdef CFG_ALLOC_DPRAM
  389 + dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
  390 +#else
  391 + dpaddr = CPM_SERIAL_BASE ;
  392 +#endif
  393 +
  394 + /* Enable SDMA.
  395 + */
  396 + im->im_siu_conf.sc_sdcr = 0x0001;
  397 +
  398 + /* Set the physical address of the host memory buffers in
  399 + * the buffer descriptors.
  400 + */
  401 +
  402 + rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
  403 + rbdf->cbd_bufaddr = (uint) (rbdf+2);
  404 + rbdf->cbd_sc = 0;
  405 + tbdf = rbdf + 1;
  406 + tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  407 + tbdf->cbd_sc = 0;
  408 +
  409 + /* Set up the baud rate generator.
  410 + */
  411 + serial_setbrg ();
  412 +
  413 + /* Set up the uart parameters in the parameter ram.
  414 + */
  415 + up->scc_genscc.scc_rbase = dpaddr;
  416 + up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
  417 +
  418 + /* Initialize Tx/Rx parameters.
  419 + */
  420 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  421 + ;
  422 + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  423 +
  424 + while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  425 + ;
  426 +
  427 + up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
  428 + up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
  429 +
  430 + up->scc_genscc.scc_mrblr = 1; /* Single character receive */
  431 + up->scc_maxidl = 0; /* disable max idle */
  432 + up->scc_brkcr = 1; /* send one break character on stop TX */
  433 + up->scc_parec = 0;
  434 + up->scc_frmec = 0;
  435 + up->scc_nosec = 0;
  436 + up->scc_brkec = 0;
  437 + up->scc_uaddr1 = 0;
  438 + up->scc_uaddr2 = 0;
  439 + up->scc_toseq = 0;
  440 + up->scc_char1 = 0x8000;
  441 + up->scc_char2 = 0x8000;
  442 + up->scc_char3 = 0x8000;
  443 + up->scc_char4 = 0x8000;
  444 + up->scc_char5 = 0x8000;
  445 + up->scc_char6 = 0x8000;
  446 + up->scc_char7 = 0x8000;
  447 + up->scc_char8 = 0x8000;
  448 + up->scc_rccm = 0xc0ff;
  449 +
  450 + /* Set low latency / small fifo.
  451 + */
  452 + sp->scc_gsmrh = SCC_GSMRH_RFW;
  453 +
  454 + /* Set SCC(x) clock mode to 16x
  455 + * See 8xx_io/commproc.c for details.
  456 + *
  457 + * Wire BRG1 to SCCn
  458 + */
  459 +
  460 + /* Set UART mode, clock divider 16 on Tx and Rx
  461 + */
  462 + sp->scc_gsmrl |=
  463 + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
  464 +
  465 + sp->scc_psmr |= SCU_PSMR_CL;
  466 +
  467 + /* Mask all interrupts and remove anything pending.
  468 + */
  469 + sp->scc_sccm = 0;
  470 + sp->scc_scce = 0xffff;
  471 + sp->scc_dsr = 0x7e7e;
  472 + sp->scc_psmr = 0x3000;
  473 +
  474 + /* Make the first buffer the only buffer.
  475 + */
  476 + tbdf->cbd_sc |= BD_SC_WRAP;
  477 + rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
  478 +
  479 + /* Enable transmitter/receiver.
  480 + */
  481 + sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  482 +
  483 + return (0);
  484 +}
  485 +
  486 +void
  487 +serial_setbrg (void)
  488 +{
  489 + DECLARE_GLOBAL_DATA_PTR;
  490 +
  491 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  492 + volatile cpm8xx_t *cp = &(im->im_cpm);
  493 +
  494 + /* Set up the baud rate generator.
  495 + * See 8xx_io/commproc.c for details.
  496 + *
  497 + * Wire BRG1 to SCCx
  498 + */
  499 +
  500 + cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
  501 + /* no |= needed, since BRG1 is 000 */
  502 +
  503 + cp->cp_brgc1 =
  504 + (((gd->cpu_clk / 16 / gd->baudrate)-1) << 1) | CPM_BRG_EN;
  505 +}
  506 +
  507 +void
  508 +serial_putc(const char c)
  509 +{
  510 + volatile cbd_t *tbdf;
  511 + volatile char *buf;
  512 + volatile scc_uart_t *up;
  513 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  514 + volatile cpm8xx_t *cpmp = &(im->im_cpm);
  515 +
  516 + if (c == '\n')
  517 + serial_putc ('\r');
  518 +
  519 + up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
  520 +
  521 + tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
  522 +
  523 + /* Wait for last character to go.
  524 + */
  525 +
  526 + buf = (char *)tbdf->cbd_bufaddr;
  527 +#if 0
  528 + __asm__("eieio");
  529 + while (tbdf->cbd_sc & BD_SC_READY)
  530 + __asm__("eieio");
  531 +#endif
  532 +
  533 + *buf = c;
  534 + tbdf->cbd_datlen = 1;
  535 + tbdf->cbd_sc |= BD_SC_READY;
  536 + __asm__("eieio");
  537 +#if 1
  538 + while (tbdf->cbd_sc & BD_SC_READY)
  539 + __asm__("eieio");
  540 +#endif
  541 +}
  542 +
  543 +int
  544 +serial_getc(void)
  545 +{
  546 + volatile cbd_t *rbdf;
  547 + volatile unsigned char *buf;
  548 + volatile scc_uart_t *up;
  549 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  550 + volatile cpm8xx_t *cpmp = &(im->im_cpm);
  551 + unsigned char c;
  552 +
  553 + up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
  554 +
  555 + rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
  556 +
  557 + /* Wait for character to show up.
  558 + */
  559 + buf = (unsigned char *)rbdf->cbd_bufaddr;
  560 + while (rbdf->cbd_sc & BD_SC_EMPTY)
  561 + ;
  562 + c = *buf;
  563 + rbdf->cbd_sc |= BD_SC_EMPTY;
  564 +
  565 + return(c);
  566 +}
  567 +
  568 +int
  569 +serial_tstc()
  570 +{
  571 + volatile cbd_t *rbdf;
  572 + volatile scc_uart_t *up;
  573 + volatile immap_t *im = (immap_t *)CFG_IMMR;
  574 + volatile cpm8xx_t *cpmp = &(im->im_cpm);
  575 +
  576 + up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
  577 +
  578 + rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
  579 +
  580 + return(!(rbdf->cbd_sc & BD_SC_EMPTY));
  581 +}
  582 +
  583 +#endif /* CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2 */
  584 +
  585 +
  586 +void
  587 +serial_puts (const char *s)
  588 +{
  589 + while (*s) {
  590 + serial_putc (*s++);
  591 + }
  592 +}
  593 +
  594 +
  595 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
  596 +
  597 +void
  598 +kgdb_serial_init(void)
  599 +{
  600 +#if defined(CONFIG_8xx_CONS_SMC1)
  601 + serial_printf("[on SMC1] ");
  602 +#elif defined(CONFIG_8xx_CONS_SMC2)
  603 + serial_printf("[on SMC2] ");
  604 +#elif defined(CONFIG_8xx_CONS_SCC1)
  605 + serial_printf("[on SCC1] ");
  606 +#elif defined(CONFIG_8xx_CONS_SCC2)
  607 + serial_printf("[on SCC2] ");
  608 +#elif defined(CONFIG_8xx_CONS_SCC3)
  609 + serial_printf("[on SCC3] ");
  610 +#elif defined(CONFIG_8xx_CONS_SCC4)
  611 + serial_printf("[on SCC4] ");
  612 +#endif
  613 +}
  614 +
  615 +void
  616 +putDebugChar (int c)
  617 +{
  618 + serial_putc (c);
  619 +}
  620 +
  621 +void
  622 +putDebugStr (const char *str)
  623 +{
  624 + serial_puts (str);
  625 +}
  626 +
  627 +int
  628 +getDebugChar (void)
  629 +{
  630 + return serial_getc();
  631 +}
  632 +
  633 +void
  634 +kgdb_interruptible (int yes)
  635 +{
  636 + return;
  637 +}
  638 +#endif /* CFG_CMD_KGDB */
  639 +
  640 +#endif /* CONFIG_8xx_CONS_NONE */
  1 +/*
  2 + * (C) Copyright 2000-2002
  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 +#include <common.h>
  25 +#include <mpc8xx.h>
  26 +#include <asm/processor.h>
  27 +
  28 +#define PITC_SHIFT 16
  29 +#define PITR_SHIFT 16
  30 +/* pitc values to time for 58/8192 seconds (about 70.8 milliseconds) */
  31 +#define SPEED_PIT_COUNTS 58
  32 +#define SPEED_PITC ((SPEED_PIT_COUNTS - 1) << PITC_SHIFT)
  33 +#define SPEED_PITC_INIT ((SPEED_PIT_COUNTS + 1) << PITC_SHIFT)
  34 +
  35 +#if !defined(CONFIG_8xx_GCLK_FREQ)
  36 +/* Access functions for the Machine State Register */
  37 +static __inline__ unsigned long get_msr(void)
  38 +{
  39 + unsigned long msr;
  40 +
  41 + asm volatile("mfmsr %0" : "=r" (msr) :);
  42 + return msr;
  43 +}
  44 +
  45 +static __inline__ void set_msr(unsigned long msr)
  46 +{
  47 + asm volatile("mtmsr %0" : : "r" (msr));
  48 +}
  49 +#endif
  50 +
  51 +/* ------------------------------------------------------------------------- */
  52 +
  53 +/*
  54 + * Measure CPU clock speed (core clock GCLK1, GCLK2),
  55 + * also determine bus clock speed (checking bus divider factor)
  56 + *
  57 + * (Approx. GCLK frequency in Hz)
  58 + *
  59 + * Initializes timer 2 and PIT, but disables them before return.
  60 + * [Use timer 2, because MPC823 CPUs mask 0.x do not have timers 3 and 4]
  61 + *
  62 + * When measuring the CPU clock against the PIT, we count cpu clocks
  63 + * for 58/8192 seconds with a prescale divide by 177 for the cpu clock.
  64 + * These strange values for the timing interval and prescaling are used
  65 + * because the formula for the CPU clock is:
  66 + *
  67 + * CPU clock = count * (177 * (8192 / 58))
  68 + *
  69 + * = count * 24999.7241
  70 + *
  71 + * which is very close to
  72 + *
  73 + * = count * 25000
  74 + *
  75 + * Since the count gives the CPU clock divided by 25000, we can get
  76 + * the CPU clock rounded to the nearest 0.1 MHz by
  77 + *
  78 + * CPU clock = ((count + 2) / 4) * 100000;
  79 + *
  80 + * The rounding is important since the measurement is sometimes going
  81 + * to be high or low by 0.025 MHz, depending on exactly how the clocks
  82 + * and counters interact. By rounding we get the exact answer for any
  83 + * CPU clock that is an even multiple of 0.1 MHz.
  84 + */
  85 +
  86 +int get_clocks (void)
  87 +{
  88 + DECLARE_GLOBAL_DATA_PTR;
  89 +
  90 + volatile immap_t *immr = (immap_t *) CFG_IMMR;
  91 +#ifndef CONFIG_8xx_GCLK_FREQ
  92 + volatile cpmtimer8xx_t *timerp = &immr->im_cpmtimer;
  93 + ulong timer2_val;
  94 + ulong msr_val;
  95 +
  96 + /* Reset + Stop Timer 2, no cascading
  97 + */
  98 + timerp->cpmt_tgcr &= ~(TGCR_CAS2 | TGCR_RST2);
  99 +
  100 + /* Keep stopped, halt in debug mode
  101 + */
  102 + timerp->cpmt_tgcr |= (TGCR_FRZ2 | TGCR_STP2);
  103 +
  104 + /* Timer 2 setup:
  105 + * Output ref. interrupt disable, int. clock
  106 + * Prescale by 177. Note that prescaler divides by value + 1
  107 + * so we must subtract 1 here.
  108 + */
  109 + timerp->cpmt_tmr2 = ((177 - 1) << TMR_PS_SHIFT) | TMR_ICLK_IN_GEN;
  110 +
  111 + timerp->cpmt_tcn2 = 0; /* reset state */
  112 + timerp->cpmt_tgcr |= TGCR_RST2; /* enable timer 2 */
  113 +
  114 + /*
  115 + * PIT setup:
  116 + *
  117 + * We want to time for SPEED_PITC_COUNTS counts (of 8192 Hz),
  118 + * so the count value would be SPEED_PITC_COUNTS - 1.
  119 + * But there would be an uncertainty in the start time of 1/4
  120 + * count since when we enable the PIT the count is not
  121 + * synchronized to the 32768 Hz oscillator. The trick here is
  122 + * to start the count higher and wait until the PIT count
  123 + * changes to the required value before starting timer 2.
  124 + *
  125 + * One count high should be enough, but occasionally the start
  126 + * is off by 1 or 2 counts of 32768 Hz. With the start value
  127 + * set two counts high it seems very reliable.
  128 + */
  129 +
  130 + immr->im_sitk.sitk_pitck = KAPWR_KEY; /* PIT initialization */
  131 + immr->im_sit.sit_pitc = SPEED_PITC_INIT;
  132 +
  133 + immr->im_sitk.sitk_piscrk = KAPWR_KEY;
  134 + immr->im_sit.sit_piscr = CFG_PISCR;
  135 +
  136 + /*
  137 + * Start measurement - disable interrupts, just in case
  138 + */
  139 + msr_val = get_msr ();
  140 + set_msr (msr_val & ~MSR_EE);
  141 +
  142 + immr->im_sit.sit_piscr |= PISCR_PTE;
  143 +
  144 + /* spin until get exact count when we want to start */
  145 + while (immr->im_sit.sit_pitr > SPEED_PITC);
  146 +
  147 + timerp->cpmt_tgcr &= ~TGCR_STP2; /* Start Timer 2 */
  148 + while ((immr->im_sit.sit_piscr & PISCR_PS) == 0);
  149 + timerp->cpmt_tgcr |= TGCR_STP2; /* Stop Timer 2 */
  150 +
  151 + /* re-enable external interrupts if they were on */
  152 + set_msr (msr_val);
  153 +
  154 + /* Disable timer and PIT
  155 + */
  156 + timer2_val = timerp->cpmt_tcn2; /* save before reset timer */
  157 +
  158 + timerp->cpmt_tgcr &= ~(TGCR_RST2 | TGCR_FRZ2 | TGCR_STP2);
  159 + immr->im_sit.sit_piscr &= ~PISCR_PTE;
  160 +
  161 + gd->cpu_clk = ((timer2_val + 2) / 4) * 100000L; /* convert to Hz */
  162 +
  163 +#else /* CONFIG_8xx_GCLK_FREQ */
  164 +
  165 + /*
  166 + * If for some reason measuring the gclk frequency won't
  167 + * work, we return the hardwired value.
  168 + * (For example, the cogent CMA286-60 CPU module has no
  169 + * separate oscillator for PITRTCLK)
  170 + */
  171 +
  172 + gd->cpu_clk = CONFIG_8xx_GCLK_FREQ;
  173 +
  174 +#endif /* CONFIG_8xx_GCLK_FREQ */
  175 +
  176 + if ((immr->im_clkrst.car_sccr & SCCR_EBDF11) == 0) {
  177 + /* No Bus Divider active */
  178 + gd->bus_clk = gd->cpu_clk;
  179 + } else {
  180 + /* The MPC8xx has only one BDF: half clock speed */
  181 + gd->bus_clk = gd->cpu_clk / 2;
  182 + }
  183 +
  184 + return (0);
  185 +}
  186 +
  187 +/* ------------------------------------------------------------------------- */
  1 +/*
  2 + * (C) Copyright 2000
  3 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
  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 +#include <common.h>
  25 +#include <config.h>
  26 +
  27 +#ifdef CONFIG_WL_4PPM_KEYBOARD
  28 +
  29 +/* WIP: Wireless keyboard on SMC
  30 + */
  31 +int drv_wlkbd_init (void)
  32 +{
  33 + return 0 ;
  34 +}
  35 +
  36 +#endif /* CONFIG_WL_4PPM_KEYBOARD */
cpu/ppc4xx/cpu_init.c
  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 +#include <common.h>
  25 +#include <watchdog.h>
  26 +#include <405gp_enet.h>
  27 +#include <asm/processor.h>
  28 +#include <ppc4xx.h>
  29 +
  30 +
  31 +#define mtebc(reg, data) mtdcr(ebccfga,reg);mtdcr(ebccfgd,data)
  32 +
  33 +
  34 +/*
  35 + * Breath some life into the CPU...
  36 + *
  37 + * Set up the memory map,
  38 + * initialize a bunch of registers
  39 + */
  40 +void
  41 +cpu_init_f (void)
  42 +{
  43 + /*
  44 + * External Bus Controller (EBC) Setup
  45 + */
  46 +#if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
  47 + /*
  48 + * Move the next instructions into icache, since these modify the flash
  49 + * we are running from!
  50 + */
  51 + asm volatile(" bl 0f" ::: "lr");
  52 + asm volatile("0: mflr 3" ::: "r3");
  53 + asm volatile(" addi 4, 0, 14" ::: "r4");
  54 + asm volatile(" mtctr 4" ::: "ctr");
  55 + asm volatile("1: icbt 0, 3");
  56 + asm volatile(" addi 3, 3, 32" ::: "r3");
  57 + asm volatile(" bdnz 1b" ::: "ctr", "cr0");
  58 + asm volatile(" addis 3, 0, 0x0" ::: "r3");
  59 + asm volatile(" ori 3, 3, 0xA000" ::: "r3");
  60 + asm volatile(" mtctr 3" ::: "ctr");
  61 + asm volatile("2: bdnz 2b" ::: "ctr", "cr0");
  62 +
  63 + mtebc(pb0ap, CFG_EBC_PB0AP);
  64 + mtebc(pb0cr, CFG_EBC_PB0CR);
  65 +#endif
  66 +
  67 +#if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR))
  68 + mtebc(pb1ap, CFG_EBC_PB1AP);
  69 + mtebc(pb1cr, CFG_EBC_PB1CR);
  70 +#endif
  71 +
  72 +#if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR))
  73 + mtebc(pb2ap, CFG_EBC_PB2AP);
  74 + mtebc(pb2cr, CFG_EBC_PB2CR);
  75 +#endif
  76 +
  77 +#if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR))
  78 + mtebc(pb3ap, CFG_EBC_PB3AP);
  79 + mtebc(pb3cr, CFG_EBC_PB3CR);
  80 +#endif
  81 +
  82 +#if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR))
  83 + mtebc(pb4ap, CFG_EBC_PB4AP);
  84 + mtebc(pb4cr, CFG_EBC_PB4CR);
  85 +#endif
  86 +
  87 +#if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR))
  88 + mtebc(pb5ap, CFG_EBC_PB5AP);
  89 + mtebc(pb5cr, CFG_EBC_PB5CR);
  90 +#endif
  91 +
  92 +#if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR))
  93 + mtebc(pb6ap, CFG_EBC_PB6AP);
  94 + mtebc(pb6cr, CFG_EBC_PB6CR);
  95 +#endif
  96 +
  97 +#if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR))
  98 + mtebc(pb7ap, CFG_EBC_PB7AP);
  99 + mtebc(pb7cr, CFG_EBC_PB7CR);
  100 +#endif
  101 +
  102 +#if defined(CONFIG_WATCHDOG)
  103 + unsigned long val;
  104 +
  105 + val = mfspr(tcr);
  106 + val |= 0xf0000000; /* generate system reset after 2.684 seconds */
  107 + mtspr(tcr, val);
  108 +
  109 + val = mfspr(tsr);
  110 + val |= 0x80000000; /* enable watchdog timer */
  111 + mtspr(tsr, val);
  112 +
  113 + reset_4xx_watchdog();
  114 +#endif /* CONFIG_WATCHDOG */
  115 +}
  116 +
  117 +/*
  118 + * initialize higher level parts of CPU like time base and timers
  119 + */
  120 +int cpu_init_r (void)
  121 +{
  122 +#ifdef CONFIG_405GP
  123 + DECLARE_GLOBAL_DATA_PTR;
  124 +
  125 + bd_t *bd = gd->bd;
  126 + unsigned long reg;
  127 +
  128 + /*
  129 + * Write Ethernetaddress into on-chip register
  130 + */
  131 + reg = 0x00000000;
  132 + reg |= bd->bi_enetaddr[0]; /* set high address */
  133 + reg = reg << 8;
  134 + reg |= bd->bi_enetaddr[1];
  135 + out32 (EMAC_IAH, reg);
  136 +
  137 + reg = 0x00000000;
  138 + reg |= bd->bi_enetaddr[2]; /* set low address */
  139 + reg = reg << 8;
  140 + reg |= bd->bi_enetaddr[3];
  141 + reg = reg << 8;
  142 + reg |= bd->bi_enetaddr[4];
  143 + reg = reg << 8;
  144 + reg |= bd->bi_enetaddr[5];
  145 + out32 (EMAC_IAL, reg);
  146 +#endif /* CONFIG_405GP */
  147 + return (0);
  148 +}
  1 +/*
  2 + * (C) Copyright 2002
  3 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  4 + * Marius Groeger <mgroeger@sysgo.de>
  5 + *
  6 + * (C) Copyright 2002
  7 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  8 + * Alex Zuepke <azu@sysgo.de>
  9 + *
  10 + * See file CREDITS for list of people who contributed to this
  11 + * project.
  12 + *
  13 + * This program is free software; you can redistribute it and/or
  14 + * modify it under the terms of the GNU General Public License as
  15 + * published by the Free Software Foundation; either version 2 of
  16 + * the License, or (at your option) any later version.
  17 + *
  18 + * This program is distributed in the hope that it will be useful,
  19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21 + * GNU General Public License for more details.
  22 + *
  23 + * You should have received a copy of the GNU General Public License
  24 + * along with this program; if not, write to the Free Software
  25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  26 + * MA 02111-1307 USA
  27 + */
  28 +
  29 +/*
  30 + * CPU specific code
  31 + */
  32 +
  33 +#include <common.h>
  34 +#include <command.h>
  35 +
  36 +int cpu_init (void)
  37 +{
  38 + /*
  39 + * setup up stack if necessary
  40 + */
  41 +#ifdef CONFIG_USE_IRQ
  42 + IRQ_STACK_START = _armboot_end +
  43 + CONFIG_STACKSIZE + CONFIG_STACKSIZE_IRQ - 4;
  44 + FIQ_STACK_START = IRQ_STACK_START + CONFIG_STACKSIZE_FIQ;
  45 + _armboot_real_end = FIQ_STACK_START + 4;
  46 +#else
  47 + _armboot_real_end = _armboot_end + CONFIG_STACKSIZE;
  48 +#endif
  49 + return (0);
  50 +}
  51 +
  52 +int cleanup_before_linux (void)
  53 +{
  54 + /*
  55 + * this function is called just before we call linux
  56 + * it prepares the processor for linux
  57 + *
  58 + * just disable everything that can disturb booting linux
  59 + */
  60 +
  61 + unsigned long i;
  62 +
  63 + disable_interrupts ();
  64 +
  65 + /* turn off I-cache */
  66 + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  67 + i &= ~0x1000;
  68 + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  69 +
  70 + /* flush I-cache */
  71 + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i));
  72 +
  73 + return (0);
  74 +}
  75 +
  76 +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  77 +{
  78 + extern void reset_cpu (ulong addr);
  79 +
  80 + printf ("resetting ...\n");
  81 +
  82 + udelay (50000); /* wait 50 ms */
  83 + disable_interrupts ();
  84 + reset_cpu (0);
  85 +
  86 + /*NOTREACHED*/
  87 + return (0);
  88 +}
  89 +
  90 +/* taken from blob */
  91 +void icache_enable (void)
  92 +{
  93 + register u32 i;
  94 +
  95 + /* read control register */
  96 + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  97 +
  98 + /* set i-cache */
  99 + i |= 0x1000;
  100 +
  101 + /* write back to control register */
  102 + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  103 +}
  104 +
  105 +void icache_disable (void)
  106 +{
  107 + register u32 i;
  108 +
  109 + /* read control register */
  110 + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  111 +
  112 + /* clear i-cache */
  113 + i &= ~0x1000;
  114 +
  115 + /* write back to control register */
  116 + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  117 +
  118 + /* flush i-cache */
  119 + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i));
  120 +}
  121 +
  122 +int icache_status (void)
  123 +{
  124 + register u32 i;
  125 +
  126 + /* read control register */
  127 + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  128 +
  129 + /* return bit */
  130 + return (i & 0x1000);
  131 +}
  132 +
  133 +/* we will never enable dcache, because we have to setup MMU first */
  134 +void dcache_enable (void)
  135 +{
  136 + return;
  137 +}
  138 +
  139 +void dcache_disable (void)
  140 +{
  141 + return;
  142 +}
  143 +
  144 +int dcache_status (void)
  145 +{
  146 + return 0; /* always off */
  147 +}