uboot/arch/powerpc/cpu/mpc8xx/cpu.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2002
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * m8xx.c
  10 *
  11 * CPU specific code
  12 *
  13 * written or collected and sometimes rewritten by
  14 * Magnus Damm <damm@bitsmart.com>
  15 *
  16 * minor modifications by
  17 * Wolfgang Denk <wd@denx.de>
  18 */
  19
  20#include <common.h>
  21#include <watchdog.h>
  22#include <command.h>
  23#include <mpc8xx.h>
  24#include <commproc.h>
  25#include <netdev.h>
  26#include <asm/cache.h>
  27#include <linux/compiler.h>
  28#include <asm/io.h>
  29
  30#if defined(CONFIG_OF_LIBFDT)
  31#include <libfdt.h>
  32#include <fdt_support.h>
  33#endif
  34
  35DECLARE_GLOBAL_DATA_PTR;
  36
  37static char *cpu_warning = "\n         " \
  38        "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
  39
  40#if ((defined(CONFIG_MPC86x) || defined(CONFIG_MPC855)) && \
  41     !defined(CONFIG_MPC862))
  42
  43static int check_CPU (long clock, uint pvr, uint immr)
  44{
  45        char *id_str =
  46# if defined(CONFIG_MPC855)
  47        "PC855";
  48# elif defined(CONFIG_MPC860P)
  49        "PC860P";
  50# else
  51        NULL;
  52# endif
  53        volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
  54        uint k, m;
  55        char buf[32];
  56        char pre = 'X';
  57        char *mid = "xx";
  58        char *suf;
  59
  60        /* the highest 16 bits should be 0x0050 for a 860 */
  61
  62        if ((pvr >> 16) != 0x0050)
  63                return -1;
  64
  65        k = (immr << 16) |
  66                immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)];
  67        m = 0;
  68        suf = "";
  69
  70        /*
  71         * Some boards use sockets so different CPUs can be used.
  72         * We have to check chip version in run time.
  73         */
  74        switch (k) {
  75        case 0x00020001: pre = 'P'; break;
  76        case 0x00030001: break;
  77        case 0x00120003: suf = "A"; break;
  78        case 0x00130003: suf = "A3"; break;
  79
  80        case 0x00200004: suf = "B"; break;
  81
  82        case 0x00300004: suf = "C"; break;
  83        case 0x00310004: suf = "C1"; m = 1; break;
  84
  85        case 0x00200064: mid = "SR"; suf = "B"; break;
  86        case 0x00300065: mid = "SR"; suf = "C"; break;
  87        case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break;
  88        case 0x05010000: suf = "D3"; m = 1; break;
  89        case 0x05020000: suf = "D4"; m = 1; break;
  90                /* this value is not documented anywhere */
  91        case 0x40000000: pre = 'P'; suf = "D"; m = 1; break;
  92                /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
  93        case 0x08010004:                /* Rev. A.0 */
  94                suf = "A";
  95                /* fall through */
  96        case 0x08000003:                /* Rev. 0.3 */
  97                pre = 'M'; m = 1;
  98                if (id_str == NULL)
  99                        id_str =
 100# if defined(CONFIG_MPC859T)
 101                "PC859T";
 102# else
 103                "PC866x"; /* Unknown chip from MPC866 family */
 104# endif
 105                break;
 106        case 0x09000000: pre = 'M'; mid = suf = ""; m = 1;
 107                if (id_str == NULL)
 108                        id_str = "PC885"; /* 870/875/880/885 */
 109                break;
 110
 111        default: suf = NULL; break;
 112        }
 113
 114        if (id_str == NULL)
 115                id_str = "PC86x";       /* Unknown 86x chip */
 116        if (suf)
 117                printf ("%c%s%sZPnn%s", pre, id_str, mid, suf);
 118        else
 119                printf ("unknown M%s (0x%08x)", id_str, k);
 120
 121
 122#if defined(CONFIG_SYS_8xx_CPUCLK_MIN) && defined(CONFIG_SYS_8xx_CPUCLK_MAX)
 123        printf (" at %s MHz [%d.%d...%d.%d MHz]\n       ",
 124                strmhz (buf, clock),
 125                CONFIG_SYS_8xx_CPUCLK_MIN / 1000000,
 126                ((CONFIG_SYS_8xx_CPUCLK_MIN % 1000000) + 50000) / 100000,
 127                CONFIG_SYS_8xx_CPUCLK_MAX / 1000000,
 128                ((CONFIG_SYS_8xx_CPUCLK_MAX % 1000000) + 50000) / 100000
 129        );
 130#else
 131        printf (" at %s MHz: ", strmhz (buf, clock));
 132#endif
 133        print_size(checkicache(), " I-Cache ");
 134        print_size(checkdcache(), " D-Cache");
 135
 136        /* do we have a FEC (860T/P or 852/859/866/885)? */
 137
 138        immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
 139        if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
 140                printf (" FEC present");
 141        }
 142
 143        if (!m) {
 144                puts (cpu_warning);
 145        }
 146
 147        putc ('\n');
 148
 149#ifdef DEBUG
 150        if(clock != measure_gclk()) {
 151            printf ("clock %ldHz != %dHz\n", clock, measure_gclk());
 152        }
 153#endif
 154
 155        return 0;
 156}
 157
 158#elif defined(CONFIG_MPC862)
 159
 160static int check_CPU (long clock, uint pvr, uint immr)
 161{
 162        volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
 163        uint k, m;
 164        char buf[32];
 165        char pre = 'X';
 166        __maybe_unused char *mid = "xx";
 167        char *suf;
 168
 169        /* the highest 16 bits should be 0x0050 for a 8xx */
 170
 171        if ((pvr >> 16) != 0x0050)
 172                return -1;
 173
 174        k = (immr << 16) |
 175                immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)];
 176        m = 0;
 177
 178        switch (k) {
 179
 180                /* this value is not documented anywhere */
 181        case 0x06000000: mid = "P"; suf = "0"; break;
 182        case 0x06010001: mid = "P"; suf = "A"; m = 1; break;
 183        case 0x07000003: mid = "P"; suf = "B"; m = 1; break;
 184        default: suf = NULL; break;
 185        }
 186
 187#ifndef CONFIG_MPC857
 188        if (suf)
 189                printf ("%cPC862%sZPnn%s", pre, mid, suf);
 190        else
 191                printf ("unknown MPC862 (0x%08x)", k);
 192#else
 193        if (suf)
 194                printf ("%cPC857TZPnn%s", pre, suf); /* only 857T tested right now! */
 195        else
 196                printf ("unknown MPC857 (0x%08x)", k);
 197#endif
 198
 199        printf(" at %s MHz: ", strmhz(buf, clock));
 200
 201        print_size(checkicache(), " I-Cache ");
 202        print_size(checkdcache(), " D-Cache");
 203
 204        /* lets check and see if we're running on a 862T (or P?) */
 205
 206        immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
 207        if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
 208                printf (" FEC present");
 209        }
 210
 211        if (!m) {
 212                puts (cpu_warning);
 213        }
 214
 215        putc ('\n');
 216
 217        return 0;
 218}
 219
 220#elif defined(CONFIG_MPC823)
 221
 222static int check_CPU (long clock, uint pvr, uint immr)
 223{
 224        volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
 225        uint k, m;
 226        char buf[32];
 227        char *suf;
 228
 229        /* the highest 16 bits should be 0x0050 for a 8xx */
 230
 231        if ((pvr >> 16) != 0x0050)
 232                return -1;
 233
 234        k = (immr << 16) |
 235                in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]);
 236        m = 0;
 237
 238        switch (k) {
 239                /* MPC823 */
 240        case 0x20000000: suf = "0"; break;
 241        case 0x20010000: suf = "0.1"; break;
 242        case 0x20020000: suf = "Z2/3"; break;
 243        case 0x20020001: suf = "Z3"; break;
 244        case 0x21000000: suf = "A"; break;
 245        case 0x21010000: suf = "B"; m = 1; break;
 246        case 0x21010001: suf = "B2"; m = 1; break;
 247                /* MPC823E */
 248        case 0x24010000: suf = NULL;
 249                        puts ("PPC823EZTnnB2");
 250                        m = 1;
 251                        break;
 252        default:
 253                        suf = NULL;
 254                        printf ("unknown MPC823 (0x%08x)", k);
 255                        break;
 256        }
 257        if (suf)
 258                printf ("PPC823ZTnn%s", suf);
 259
 260        printf(" at %s MHz: ", strmhz(buf, clock));
 261
 262        print_size(checkicache(), " I-Cache ");
 263        print_size(checkdcache(), " D-Cache");
 264
 265        /* lets check and see if we're running on a 860T (or P?) */
 266
 267        immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
 268        if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
 269                puts (" FEC present");
 270        }
 271
 272        if (!m) {
 273                puts (cpu_warning);
 274        }
 275
 276        putc ('\n');
 277
 278        return 0;
 279}
 280
 281#elif defined(CONFIG_MPC850)
 282
 283static int check_CPU (long clock, uint pvr, uint immr)
 284{
 285        volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
 286        uint k, m;
 287        char buf[32];
 288
 289        /* the highest 16 bits should be 0x0050 for a 8xx */
 290
 291        if ((pvr >> 16) != 0x0050)
 292                return -1;
 293
 294        k = (immr << 16) |
 295                immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)];
 296        m = 0;
 297
 298        switch (k) {
 299        case 0x20020001:
 300                printf ("XPC850xxZT");
 301                break;
 302        case 0x21000065:
 303                printf ("XPC850xxZTA");
 304                break;
 305        case 0x21010067:
 306                printf ("XPC850xxZTB");
 307                m = 1;
 308                break;
 309        case 0x21020068:
 310                printf ("XPC850xxZTC");
 311                m = 1;
 312                break;
 313        default:
 314                printf ("unknown MPC850 (0x%08x)", k);
 315        }
 316        printf(" at %s MHz: ", strmhz(buf, clock));
 317
 318        print_size(checkicache(), " I-Cache ");
 319        print_size(checkdcache(), " D-Cache");
 320
 321        /* lets check and see if we're running on a 850T (or P?) */
 322
 323        immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
 324        if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
 325                printf (" FEC present");
 326        }
 327
 328        if (!m) {
 329                puts (cpu_warning);
 330        }
 331
 332        putc ('\n');
 333
 334        return 0;
 335}
 336#else
 337#error CPU undefined
 338#endif
 339/* ------------------------------------------------------------------------- */
 340
 341int checkcpu (void)
 342{
 343        ulong clock = gd->cpu_clk;
 344        uint immr = get_immr (0);       /* Return full IMMR contents */
 345        uint pvr = get_pvr ();
 346
 347        puts ("CPU:   ");
 348
 349        /* 850 has PARTNUM 20 */
 350        /* 801 has PARTNUM 10 */
 351        return check_CPU (clock, pvr, immr);
 352}
 353
 354/* ------------------------------------------------------------------------- */
 355/* L1 i-cache                                                                */
 356/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB)              */
 357/* the 860 P (plus) has 256 sets of 16 bytes in 4 ways (= 16 kB)             */
 358
 359int checkicache (void)
 360{
 361        volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
 362        volatile memctl8xx_t *memctl = &immap->im_memctl;
 363        u32 cacheon = rd_ic_cst () & IDC_ENABLED;
 364
 365#ifdef CONFIG_IP86x
 366        u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
 367#else
 368        u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
 369#endif
 370        u32 m;
 371        u32 lines = -1;
 372
 373        wr_ic_cst (IDC_UNALL);
 374        wr_ic_cst (IDC_INVALL);
 375        wr_ic_cst (IDC_DISABLE);
 376        __asm__ volatile ("isync");
 377
 378        while (!((m = rd_ic_cst ()) & IDC_CERR2)) {
 379                wr_ic_adr (k);
 380                wr_ic_cst (IDC_LDLCK);
 381                __asm__ volatile ("isync");
 382
 383                lines++;
 384                k += 0x10;                              /* the number of bytes in a cacheline */
 385        }
 386
 387        wr_ic_cst (IDC_UNALL);
 388        wr_ic_cst (IDC_INVALL);
 389
 390        if (cacheon)
 391                wr_ic_cst (IDC_ENABLE);
 392        else
 393                wr_ic_cst (IDC_DISABLE);
 394
 395        __asm__ volatile ("isync");
 396
 397        return lines << 4;
 398};
 399
 400/* ------------------------------------------------------------------------- */
 401/* L1 d-cache                                                                */
 402/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB)              */
 403/* the 860 P (plus) has 256 sets of 16 bytes in 2 ways (= 8 kB)              */
 404/* call with cache disabled                                                  */
 405
 406int checkdcache (void)
 407{
 408        volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
 409        volatile memctl8xx_t *memctl = &immap->im_memctl;
 410        u32 cacheon = rd_dc_cst () & IDC_ENABLED;
 411
 412#ifdef CONFIG_IP86x
 413        u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
 414#else
 415        u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
 416#endif
 417        u32 m;
 418        u32 lines = -1;
 419
 420        wr_dc_cst (IDC_UNALL);
 421        wr_dc_cst (IDC_INVALL);
 422        wr_dc_cst (IDC_DISABLE);
 423
 424        while (!((m = rd_dc_cst ()) & IDC_CERR2)) {
 425                wr_dc_adr (k);
 426                wr_dc_cst (IDC_LDLCK);
 427                lines++;
 428                k += 0x10;      /* the number of bytes in a cacheline */
 429        }
 430
 431        wr_dc_cst (IDC_UNALL);
 432        wr_dc_cst (IDC_INVALL);
 433
 434        if (cacheon)
 435                wr_dc_cst (IDC_ENABLE);
 436        else
 437                wr_dc_cst (IDC_DISABLE);
 438
 439        return lines << 4;
 440};
 441
 442/* ------------------------------------------------------------------------- */
 443
 444void upmconfig (uint upm, uint * table, uint size)
 445{
 446        uint i;
 447        uint addr = 0;
 448        volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
 449        volatile memctl8xx_t *memctl = &immap->im_memctl;
 450
 451        for (i = 0; i < size; i++) {
 452                memctl->memc_mdr = table[i];    /* (16-15) */
 453                memctl->memc_mcr = addr | upm;  /* (16-16) */
 454                addr++;
 455        }
 456}
 457
 458/* ------------------------------------------------------------------------- */
 459
 460int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 461{
 462        ulong msr, addr;
 463
 464        volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
 465
 466        immap->im_clkrst.car_plprcr |= PLPRCR_CSR;      /* Checkstop Reset enable */
 467
 468        /* Interrupts and MMU off */
 469        __asm__ volatile ("mtspr    81, 0");
 470        __asm__ volatile ("mfmsr    %0":"=r" (msr));
 471
 472        msr &= ~0x1030;
 473        __asm__ volatile ("mtmsr    %0"::"r" (msr));
 474
 475        /*
 476         * Trying to execute the next instruction at a non-existing address
 477         * should cause a machine check, resulting in reset
 478         */
 479#ifdef CONFIG_SYS_RESET_ADDRESS
 480        addr = CONFIG_SYS_RESET_ADDRESS;
 481#else
 482        /*
 483         * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE
 484         * - sizeof (ulong) is usually a valid address. Better pick an address
 485         * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
 486         * "(ulong)-1" used to be a good choice for many systems...
 487         */
 488        addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
 489#endif
 490        ((void (*)(void)) addr) ();
 491        return 1;
 492}
 493
 494/* ------------------------------------------------------------------------- */
 495
 496/*
 497 * Get timebase clock frequency (like cpu_clk in Hz)
 498 *
 499 * See sections 14.2 and 14.6 of the User's Manual
 500 */
 501unsigned long get_tbclk (void)
 502{
 503        uint immr = get_immr (0);       /* Return full IMMR contents */
 504        volatile immap_t *immap = (volatile immap_t *)(immr & 0xFFFF0000);
 505        ulong oscclk, factor, pll;
 506
 507        if (immap->im_clkrst.car_sccr & SCCR_TBS) {
 508                return (gd->cpu_clk / 16);
 509        }
 510
 511        pll = immap->im_clkrst.car_plprcr;
 512
 513#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
 514
 515        /*
 516         * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
 517         * factor is calculated as follows:
 518         *
 519         *                   MFN
 520         *           MFI + -------
 521         *                 MFD + 1
 522         * factor =  -----------------
 523         *           (PDF + 1) * 2^S
 524         *
 525         * For older chips, it's just MF field of PLPRCR plus one.
 526         */
 527        if ((immr & 0x0FFF) >= MPC8xx_NEW_CLK) { /* MPC866/87x/88x series */
 528                factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN)/(PLPRCR_val(MFD)+1))/
 529                        (PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S));
 530        } else {
 531                factor = PLPRCR_val(MF)+1;
 532        }
 533
 534        oscclk = gd->cpu_clk / factor;
 535
 536        if ((immap->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) {
 537                return (oscclk / 4);
 538        }
 539        return (oscclk / 16);
 540}
 541
 542/* ------------------------------------------------------------------------- */
 543
 544#if defined(CONFIG_WATCHDOG)
 545void watchdog_reset (void)
 546{
 547        int re_enable = disable_interrupts ();
 548
 549        reset_8xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
 550        if (re_enable)
 551                enable_interrupts ();
 552}
 553#endif /* CONFIG_WATCHDOG */
 554
 555#if defined(CONFIG_WATCHDOG)
 556
 557void reset_8xx_watchdog (volatile immap_t * immr)
 558{
 559        /*
 560         * All other boards use the MPC8xx Internal Watchdog
 561         */
 562        immr->im_siu_conf.sc_swsr = 0x556c;     /* write magic1 */
 563        immr->im_siu_conf.sc_swsr = 0xaa39;     /* write magic2 */
 564}
 565#endif /* CONFIG_WATCHDOG */
 566
 567/*
 568 * Initializes on-chip ethernet controllers.
 569 * to override, implement board_eth_init()
 570 */
 571int cpu_eth_init(bd_t *bis)
 572{
 573#if defined(SCC_ENET) && defined(CONFIG_CMD_NET)
 574        scc_initialize(bis);
 575#endif
 576#if defined(FEC_ENET)
 577        fec_initialize(bis);
 578#endif
 579        return 0;
 580}
 581