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 int check_CPU(long clock, uint pvr, uint immr)
  38{
  39        immap_t __iomem *immap = (immap_t __iomem *)(immr & 0xFFFF0000);
  40        uint k;
  41        char buf[32];
  42
  43        /* the highest 16 bits should be 0x0050 for a 860 */
  44
  45        if ((pvr >> 16) != 0x0050)
  46                return -1;
  47
  48        k = (immr << 16) |
  49            in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]);
  50
  51        /*
  52         * Some boards use sockets so different CPUs can be used.
  53         * We have to check chip version in run time.
  54         */
  55        switch (k) {
  56                /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
  57        case 0x08010004:                /* Rev. A.0 */
  58                printf("MPC866xxxZPnnA");
  59                break;
  60        case 0x08000003:                /* Rev. 0.3 */
  61                printf("MPC866xxxZPnn");
  62                break;
  63        case 0x09000000:                /* 870/875/880/885 */
  64                puts("MPC885ZPnn");
  65                break;
  66
  67        default:
  68                printf("unknown MPC86x (0x%08x)", k);
  69                break;
  70        }
  71
  72        printf(" at %s MHz: ", strmhz(buf, clock));
  73
  74        print_size(checkicache(), " I-Cache ");
  75        print_size(checkdcache(), " D-Cache");
  76
  77        /* do we have a FEC (860T/P or 852/859/866/885)? */
  78
  79        out_be32(&immap->im_cpm.cp_fec.fec_addr_low, 0x12345678);
  80        if (in_be32(&immap->im_cpm.cp_fec.fec_addr_low) == 0x12345678)
  81                printf(" FEC present");
  82
  83        putc('\n');
  84
  85        return 0;
  86}
  87
  88/* ------------------------------------------------------------------------- */
  89
  90int checkcpu(void)
  91{
  92        ulong clock = gd->cpu_clk;
  93        uint immr = get_immr(0);        /* Return full IMMR contents */
  94        uint pvr = get_pvr();
  95
  96        puts("CPU:   ");
  97
  98        return check_CPU(clock, pvr, immr);
  99}
 100
 101/* ------------------------------------------------------------------------- */
 102/* L1 i-cache                                                                */
 103
 104int checkicache(void)
 105{
 106        immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
 107        memctl8xx_t __iomem *memctl = &immap->im_memctl;
 108        u32 cacheon = rd_ic_cst() & IDC_ENABLED;
 109        /* probe in flash memoryarea */
 110        u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff;
 111        u32 m;
 112        u32 lines = -1;
 113
 114        wr_ic_cst(IDC_UNALL);
 115        wr_ic_cst(IDC_INVALL);
 116        wr_ic_cst(IDC_DISABLE);
 117        __asm__ volatile ("isync");
 118
 119        while (!((m = rd_ic_cst()) & IDC_CERR2)) {
 120                wr_ic_adr(k);
 121                wr_ic_cst(IDC_LDLCK);
 122                __asm__ volatile ("isync");
 123
 124                lines++;
 125                k += 0x10;      /* the number of bytes in a cacheline */
 126        }
 127
 128        wr_ic_cst(IDC_UNALL);
 129        wr_ic_cst(IDC_INVALL);
 130
 131        if (cacheon)
 132                wr_ic_cst(IDC_ENABLE);
 133        else
 134                wr_ic_cst(IDC_DISABLE);
 135
 136        __asm__ volatile ("isync");
 137
 138        return lines << 4;
 139};
 140
 141/* ------------------------------------------------------------------------- */
 142/* L1 d-cache                                                                */
 143/* call with cache disabled                                                  */
 144
 145int checkdcache(void)
 146{
 147        immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
 148        memctl8xx_t __iomem *memctl = &immap->im_memctl;
 149        u32 cacheon = rd_dc_cst() & IDC_ENABLED;
 150        /* probe in flash memoryarea */
 151        u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff;
 152        u32 m;
 153        u32 lines = -1;
 154
 155        wr_dc_cst(IDC_UNALL);
 156        wr_dc_cst(IDC_INVALL);
 157        wr_dc_cst(IDC_DISABLE);
 158
 159        while (!((m = rd_dc_cst()) & IDC_CERR2)) {
 160                wr_dc_adr(k);
 161                wr_dc_cst(IDC_LDLCK);
 162                lines++;
 163                k += 0x10;      /* the number of bytes in a cacheline */
 164        }
 165
 166        wr_dc_cst(IDC_UNALL);
 167        wr_dc_cst(IDC_INVALL);
 168
 169        if (cacheon)
 170                wr_dc_cst(IDC_ENABLE);
 171        else
 172                wr_dc_cst(IDC_DISABLE);
 173
 174        return lines << 4;
 175};
 176
 177/* ------------------------------------------------------------------------- */
 178
 179void upmconfig(uint upm, uint *table, uint size)
 180{
 181        uint i;
 182        uint addr = 0;
 183        immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
 184        memctl8xx_t __iomem *memctl = &immap->im_memctl;
 185
 186        for (i = 0; i < size; i++) {
 187                out_be32(&memctl->memc_mdr, table[i]);          /* (16-15) */
 188                out_be32(&memctl->memc_mcr, addr | upm);        /* (16-16) */
 189                addr++;
 190        }
 191}
 192
 193/* ------------------------------------------------------------------------- */
 194
 195int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 196{
 197        ulong msr, addr;
 198
 199        immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
 200
 201        /* Checkstop Reset enable */
 202        setbits_be32(&immap->im_clkrst.car_plprcr, PLPRCR_CSR);
 203
 204        /* Interrupts and MMU off */
 205        __asm__ volatile ("mtspr    81, 0");
 206        __asm__ volatile ("mfmsr    %0" : "=r" (msr));
 207
 208        msr &= ~0x1030;
 209        __asm__ volatile ("mtmsr    %0" : : "r" (msr));
 210
 211        /*
 212         * Trying to execute the next instruction at a non-existing address
 213         * should cause a machine check, resulting in reset
 214         */
 215#ifdef CONFIG_SYS_RESET_ADDRESS
 216        addr = CONFIG_SYS_RESET_ADDRESS;
 217#else
 218        /*
 219         * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
 220         * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid address.
 221         * Better pick an address known to be invalid on your system and assign
 222         * it to CONFIG_SYS_RESET_ADDRESS.
 223         * "(ulong)-1" used to be a good choice for many systems...
 224         */
 225        addr = CONFIG_SYS_MONITOR_BASE - sizeof(ulong);
 226#endif
 227        ((void (*)(void)) addr)();
 228        return 1;
 229}
 230
 231/* ------------------------------------------------------------------------- */
 232
 233/*
 234 * Get timebase clock frequency (like cpu_clk in Hz)
 235 *
 236 * See sections 14.2 and 14.6 of the User's Manual
 237 */
 238unsigned long get_tbclk(void)
 239{
 240        uint immr = get_immr(0);        /* Return full IMMR contents */
 241        immap_t __iomem *immap = (immap_t __iomem *)(immr & 0xFFFF0000);
 242        ulong oscclk, factor, pll;
 243
 244        if (in_be32(&immap->im_clkrst.car_sccr) & SCCR_TBS)
 245                return gd->cpu_clk / 16;
 246
 247        pll = in_be32(&immap->im_clkrst.car_plprcr);
 248
 249#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
 250
 251        /*
 252         * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
 253         * factor is calculated as follows:
 254         *
 255         *                   MFN
 256         *           MFI + -------
 257         *                 MFD + 1
 258         * factor =  -----------------
 259         *           (PDF + 1) * 2^S
 260         *
 261         */
 262        factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN) / (PLPRCR_val(MFD) + 1)) /
 263                 (PLPRCR_val(PDF) + 1) / (1 << PLPRCR_val(S));
 264
 265        oscclk = gd->cpu_clk / factor;
 266
 267        if ((in_be32(&immap->im_clkrst.car_sccr) & SCCR_RTSEL) == 0 ||
 268            factor > 2)
 269                return oscclk / 4;
 270
 271        return oscclk / 16;
 272}
 273
 274/* ------------------------------------------------------------------------- */
 275
 276#if defined(CONFIG_WATCHDOG)
 277void watchdog_reset(void)
 278{
 279        int re_enable = disable_interrupts();
 280
 281        reset_8xx_watchdog((immap_t __iomem *)CONFIG_SYS_IMMR);
 282        if (re_enable)
 283                enable_interrupts();
 284}
 285#endif /* CONFIG_WATCHDOG */
 286
 287#if defined(CONFIG_WATCHDOG)
 288
 289void reset_8xx_watchdog(immap_t __iomem *immr)
 290{
 291        /*
 292         * All other boards use the MPC8xx Internal Watchdog
 293         */
 294        out_be16(&immr->im_siu_conf.sc_swsr, 0x556c);   /* write magic1 */
 295        out_be16(&immr->im_siu_conf.sc_swsr, 0xaa39);   /* write magic2 */
 296}
 297#endif /* CONFIG_WATCHDOG */
 298
 299/*
 300 * Initializes on-chip ethernet controllers.
 301 * to override, implement board_eth_init()
 302 */
 303int cpu_eth_init(bd_t *bis)
 304{
 305#if defined(CONFIG_MPC8XX_FEC)
 306        fec_initialize(bis);
 307#endif
 308        return 0;
 309}
 310