uboot/arch/powerpc/cpu/mpc85xx/fdt.c
<<
>>
Prefs
   1/*
   2 * Copyright 2007-2010 Freescale Semiconductor, Inc.
   3 *
   4 * (C) Copyright 2000
   5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   6 *
   7 * See file CREDITS for list of people who contributed to this
   8 * project.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 of
  13 * the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 * MA 02111-1307 USA
  24 */
  25
  26#include <common.h>
  27#include <libfdt.h>
  28#include <fdt_support.h>
  29#include <asm/processor.h>
  30#include <linux/ctype.h>
  31#include <asm/io.h>
  32#include <asm/fsl_portals.h>
  33#ifdef CONFIG_FSL_ESDHC
  34#include <fsl_esdhc.h>
  35#endif
  36
  37DECLARE_GLOBAL_DATA_PTR;
  38
  39extern void ft_qe_setup(void *blob);
  40extern void ft_fixup_num_cores(void *blob);
  41
  42#ifdef CONFIG_MP
  43#include "mp.h"
  44
  45void ft_fixup_cpu(void *blob, u64 memory_limit)
  46{
  47        int off;
  48        ulong spin_tbl_addr = get_spin_phys_addr();
  49        u32 bootpg = determine_mp_bootpg();
  50        u32 id = get_my_id();
  51        const char *enable_method;
  52
  53        off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
  54        while (off != -FDT_ERR_NOTFOUND) {
  55                u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
  56
  57                if (reg) {
  58                        u64 val = *reg * SIZE_BOOT_ENTRY + spin_tbl_addr;
  59                        val = cpu_to_fdt32(val);
  60                        if (*reg == id) {
  61                                fdt_setprop_string(blob, off, "status",
  62                                                                "okay");
  63                        } else {
  64                                fdt_setprop_string(blob, off, "status",
  65                                                                "disabled");
  66                        }
  67
  68                        if (hold_cores_in_reset(0)) {
  69#ifdef CONFIG_FSL_CORENET
  70                                /* Cores held in reset, use BRR to release */
  71                                enable_method = "fsl,brr-holdoff";
  72#else
  73                                /* Cores held in reset, use EEBPCR to release */
  74                                enable_method = "fsl,eebpcr-holdoff";
  75#endif
  76                        } else {
  77                                /* Cores out of reset and in a spin-loop */
  78                                enable_method = "spin-table";
  79
  80                                fdt_setprop(blob, off, "cpu-release-addr",
  81                                                &val, sizeof(val));
  82                        }
  83
  84                        fdt_setprop_string(blob, off, "enable-method",
  85                                                        enable_method);
  86                } else {
  87                        printf ("cpu NULL\n");
  88                }
  89                off = fdt_node_offset_by_prop_value(blob, off,
  90                                "device_type", "cpu", 4);
  91        }
  92
  93        /* Reserve the boot page so OSes dont use it */
  94        if ((u64)bootpg < memory_limit) {
  95                off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
  96                if (off < 0)
  97                        printf("%s: %s\n", __FUNCTION__, fdt_strerror(off));
  98        }
  99}
 100#endif
 101
 102#ifdef CONFIG_SYS_FSL_CPC
 103static inline void ft_fixup_l3cache(void *blob, int off)
 104{
 105        u32 line_size, num_ways, size, num_sets;
 106        cpc_corenet_t *cpc = (void *)CONFIG_SYS_FSL_CPC_ADDR;
 107        u32 cfg0 = in_be32(&cpc->cpccfg0);
 108
 109        size = CPC_CFG0_SZ_K(cfg0) * 1024 * CONFIG_SYS_NUM_CPC;
 110        num_ways = CPC_CFG0_NUM_WAYS(cfg0);
 111        line_size = CPC_CFG0_LINE_SZ(cfg0);
 112        num_sets = size / (line_size * num_ways);
 113
 114        fdt_setprop(blob, off, "cache-unified", NULL, 0);
 115        fdt_setprop_cell(blob, off, "cache-block-size", line_size);
 116        fdt_setprop_cell(blob, off, "cache-size", size);
 117        fdt_setprop_cell(blob, off, "cache-sets", num_sets);
 118        fdt_setprop_cell(blob, off, "cache-level", 3);
 119#ifdef CONFIG_SYS_CACHE_STASHING
 120        fdt_setprop_cell(blob, off, "cache-stash-id", 1);
 121#endif
 122}
 123#else
 124#define ft_fixup_l3cache(x, y)
 125#endif
 126
 127#if defined(CONFIG_L2_CACHE)
 128/* return size in kilobytes */
 129static inline u32 l2cache_size(void)
 130{
 131        volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
 132        volatile u32 l2siz_field = (l2cache->l2ctl >> 28) & 0x3;
 133        u32 ver = SVR_SOC_VER(get_svr());
 134
 135        switch (l2siz_field) {
 136        case 0x0:
 137                break;
 138        case 0x1:
 139                if (ver == SVR_8540 || ver == SVR_8560   ||
 140                    ver == SVR_8541 || ver == SVR_8541_E ||
 141                    ver == SVR_8555 || ver == SVR_8555_E)
 142                        return 128;
 143                else
 144                        return 256;
 145                break;
 146        case 0x2:
 147                if (ver == SVR_8540 || ver == SVR_8560   ||
 148                    ver == SVR_8541 || ver == SVR_8541_E ||
 149                    ver == SVR_8555 || ver == SVR_8555_E)
 150                        return 256;
 151                else
 152                        return 512;
 153                break;
 154        case 0x3:
 155                return 1024;
 156                break;
 157        }
 158
 159        return 0;
 160}
 161
 162static inline void ft_fixup_l2cache(void *blob)
 163{
 164        int len, off;
 165        u32 *ph;
 166        struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr()));
 167        char compat_buf[38];
 168
 169        const u32 line_size = 32;
 170        const u32 num_ways = 8;
 171        const u32 size = l2cache_size() * 1024;
 172        const u32 num_sets = size / (line_size * num_ways);
 173
 174        off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
 175        if (off < 0) {
 176                debug("no cpu node fount\n");
 177                return;
 178        }
 179
 180        ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
 181
 182        if (ph == NULL) {
 183                debug("no next-level-cache property\n");
 184                return ;
 185        }
 186
 187        off = fdt_node_offset_by_phandle(blob, *ph);
 188        if (off < 0) {
 189                printf("%s: %s\n", __func__, fdt_strerror(off));
 190                return ;
 191        }
 192
 193        if (cpu) {
 194                if (isdigit(cpu->name[0]))
 195                        len = sprintf(compat_buf,
 196                                "fsl,mpc%s-l2-cache-controller", cpu->name);
 197                else
 198                        len = sprintf(compat_buf,
 199                                "fsl,%c%s-l2-cache-controller",
 200                                tolower(cpu->name[0]), cpu->name + 1);
 201
 202                sprintf(&compat_buf[len + 1], "cache");
 203        }
 204        fdt_setprop(blob, off, "cache-unified", NULL, 0);
 205        fdt_setprop_cell(blob, off, "cache-block-size", line_size);
 206        fdt_setprop_cell(blob, off, "cache-size", size);
 207        fdt_setprop_cell(blob, off, "cache-sets", num_sets);
 208        fdt_setprop_cell(blob, off, "cache-level", 2);
 209        fdt_setprop(blob, off, "compatible", compat_buf, sizeof(compat_buf));
 210
 211        /* we dont bother w/L3 since no platform of this type has one */
 212}
 213#elif defined(CONFIG_BACKSIDE_L2_CACHE)
 214static inline void ft_fixup_l2cache(void *blob)
 215{
 216        int off, l2_off, l3_off = -1;
 217        u32 *ph;
 218        u32 l2cfg0 = mfspr(SPRN_L2CFG0);
 219        u32 size, line_size, num_ways, num_sets;
 220
 221        size = (l2cfg0 & 0x3fff) * 64 * 1024;
 222        num_ways = ((l2cfg0 >> 14) & 0x1f) + 1;
 223        line_size = (((l2cfg0 >> 23) & 0x3) + 1) * 32;
 224        num_sets = size / (line_size * num_ways);
 225
 226        off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
 227
 228        while (off != -FDT_ERR_NOTFOUND) {
 229                ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
 230
 231                if (ph == NULL) {
 232                        debug("no next-level-cache property\n");
 233                        goto next;
 234                }
 235
 236                l2_off = fdt_node_offset_by_phandle(blob, *ph);
 237                if (l2_off < 0) {
 238                        printf("%s: %s\n", __func__, fdt_strerror(off));
 239                        goto next;
 240                }
 241
 242#ifdef CONFIG_SYS_CACHE_STASHING
 243                {
 244                        u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
 245                        if (reg)
 246                                fdt_setprop_cell(blob, l2_off, "cache-stash-id",
 247                                         (*reg * 2) + 32 + 1);
 248                }
 249#endif
 250
 251                fdt_setprop(blob, l2_off, "cache-unified", NULL, 0);
 252                fdt_setprop_cell(blob, l2_off, "cache-block-size", line_size);
 253                fdt_setprop_cell(blob, l2_off, "cache-size", size);
 254                fdt_setprop_cell(blob, l2_off, "cache-sets", num_sets);
 255                fdt_setprop_cell(blob, l2_off, "cache-level", 2);
 256                fdt_setprop(blob, l2_off, "compatible", "cache", 6);
 257
 258                if (l3_off < 0) {
 259                        ph = (u32 *)fdt_getprop(blob, l2_off, "next-level-cache", 0);
 260
 261                        if (ph == NULL) {
 262                                debug("no next-level-cache property\n");
 263                                goto next;
 264                        }
 265                        l3_off = *ph;
 266                }
 267next:
 268                off = fdt_node_offset_by_prop_value(blob, off,
 269                                "device_type", "cpu", 4);
 270        }
 271        if (l3_off > 0) {
 272                l3_off = fdt_node_offset_by_phandle(blob, l3_off);
 273                if (l3_off < 0) {
 274                        printf("%s: %s\n", __func__, fdt_strerror(off));
 275                        return ;
 276                }
 277                ft_fixup_l3cache(blob, l3_off);
 278        }
 279}
 280#else
 281#define ft_fixup_l2cache(x)
 282#endif
 283
 284static inline void ft_fixup_cache(void *blob)
 285{
 286        int off;
 287
 288        off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
 289
 290        while (off != -FDT_ERR_NOTFOUND) {
 291                u32 l1cfg0 = mfspr(SPRN_L1CFG0);
 292                u32 l1cfg1 = mfspr(SPRN_L1CFG1);
 293                u32 isize, iline_size, inum_sets, inum_ways;
 294                u32 dsize, dline_size, dnum_sets, dnum_ways;
 295
 296                /* d-side config */
 297                dsize = (l1cfg0 & 0x7ff) * 1024;
 298                dnum_ways = ((l1cfg0 >> 11) & 0xff) + 1;
 299                dline_size = (((l1cfg0 >> 23) & 0x3) + 1) * 32;
 300                dnum_sets = dsize / (dline_size * dnum_ways);
 301
 302                fdt_setprop_cell(blob, off, "d-cache-block-size", dline_size);
 303                fdt_setprop_cell(blob, off, "d-cache-size", dsize);
 304                fdt_setprop_cell(blob, off, "d-cache-sets", dnum_sets);
 305
 306#ifdef CONFIG_SYS_CACHE_STASHING
 307                {
 308                        u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
 309                        if (reg)
 310                                fdt_setprop_cell(blob, off, "cache-stash-id",
 311                                         (*reg * 2) + 32 + 0);
 312                }
 313#endif
 314
 315                /* i-side config */
 316                isize = (l1cfg1 & 0x7ff) * 1024;
 317                inum_ways = ((l1cfg1 >> 11) & 0xff) + 1;
 318                iline_size = (((l1cfg1 >> 23) & 0x3) + 1) * 32;
 319                inum_sets = isize / (iline_size * inum_ways);
 320
 321                fdt_setprop_cell(blob, off, "i-cache-block-size", iline_size);
 322                fdt_setprop_cell(blob, off, "i-cache-size", isize);
 323                fdt_setprop_cell(blob, off, "i-cache-sets", inum_sets);
 324
 325                off = fdt_node_offset_by_prop_value(blob, off,
 326                                "device_type", "cpu", 4);
 327        }
 328
 329        ft_fixup_l2cache(blob);
 330}
 331
 332
 333void fdt_add_enet_stashing(void *fdt)
 334{
 335        do_fixup_by_compat(fdt, "gianfar", "bd-stash", NULL, 0, 1);
 336
 337        do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-len", 96, 1);
 338
 339        do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-idx", 0, 1);
 340}
 341
 342#if defined(CONFIG_SYS_DPAA_FMAN) || defined(CONFIG_SYS_DPAA_PME)
 343static void ft_fixup_clks(void *blob, const char *compat, u32 offset,
 344                          unsigned long freq)
 345{
 346        phys_addr_t phys = offset + CONFIG_SYS_CCSRBAR_PHYS;
 347        int off = fdt_node_offset_by_compat_reg(blob, compat, phys);
 348
 349        if (off >= 0) {
 350                off = fdt_setprop_cell(blob, off, "clock-frequency", freq);
 351                if (off > 0)
 352                        printf("WARNING enable to set clock-frequency "
 353                                "for %s: %s\n", compat, fdt_strerror(off));
 354        }
 355}
 356
 357static void ft_fixup_dpaa_clks(void *blob)
 358{
 359        sys_info_t sysinfo;
 360
 361        get_sys_info(&sysinfo);
 362        ft_fixup_clks(blob, "fsl,fman", CONFIG_SYS_FSL_FM1_OFFSET,
 363                        sysinfo.freqFMan[0]);
 364
 365#if (CONFIG_SYS_NUM_FMAN == 2)
 366        ft_fixup_clks(blob, "fsl,fman", CONFIG_SYS_FSL_FM2_OFFSET,
 367                        sysinfo.freqFMan[1]);
 368#endif
 369
 370#ifdef CONFIG_SYS_DPAA_PME
 371        do_fixup_by_compat_u32(blob, "fsl,pme",
 372                "clock-frequency", sysinfo.freqPME, 1);
 373#endif
 374}
 375#else
 376#define ft_fixup_dpaa_clks(x)
 377#endif
 378
 379#ifdef CONFIG_QE
 380static void ft_fixup_qe_snum(void *blob)
 381{
 382        unsigned int svr;
 383
 384        svr = mfspr(SPRN_SVR);
 385        if (SVR_SOC_VER(svr) == SVR_8569_E) {
 386                if(IS_SVR_REV(svr, 1, 0))
 387                        do_fixup_by_compat_u32(blob, "fsl,qe",
 388                                "fsl,qe-num-snums", 46, 1);
 389                else
 390                        do_fixup_by_compat_u32(blob, "fsl,qe",
 391                                "fsl,qe-num-snums", 76, 1);
 392        }
 393}
 394#endif
 395
 396void ft_cpu_setup(void *blob, bd_t *bd)
 397{
 398        int off;
 399        int val;
 400        sys_info_t sysinfo;
 401
 402        /* delete crypto node if not on an E-processor */
 403        if (!IS_E_PROCESSOR(get_svr()))
 404                fdt_fixup_crypto_node(blob, 0);
 405
 406        fdt_fixup_ethernet(blob);
 407
 408        fdt_add_enet_stashing(blob);
 409
 410        do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
 411                "timebase-frequency", get_tbclk(), 1);
 412        do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
 413                "bus-frequency", bd->bi_busfreq, 1);
 414        get_sys_info(&sysinfo);
 415        off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
 416        while (off != -FDT_ERR_NOTFOUND) {
 417                u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
 418                val = cpu_to_fdt32(sysinfo.freqProcessor[*reg]);
 419                fdt_setprop(blob, off, "clock-frequency", &val, 4);
 420                off = fdt_node_offset_by_prop_value(blob, off, "device_type",
 421                                                        "cpu", 4);
 422        }
 423        do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
 424                "bus-frequency", bd->bi_busfreq, 1);
 425
 426        do_fixup_by_compat_u32(blob, "fsl,pq3-localbus",
 427                "bus-frequency", gd->lbc_clk, 1);
 428        do_fixup_by_compat_u32(blob, "fsl,elbc",
 429                "bus-frequency", gd->lbc_clk, 1);
 430#ifdef CONFIG_QE
 431        ft_qe_setup(blob);
 432        ft_fixup_qe_snum(blob);
 433#endif
 434
 435#ifdef CONFIG_SYS_NS16550
 436        do_fixup_by_compat_u32(blob, "ns16550",
 437                "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
 438#endif
 439
 440#ifdef CONFIG_CPM2
 441        do_fixup_by_compat_u32(blob, "fsl,cpm2-scc-uart",
 442                "current-speed", bd->bi_baudrate, 1);
 443
 444        do_fixup_by_compat_u32(blob, "fsl,cpm2-brg",
 445                "clock-frequency", bd->bi_brgfreq, 1);
 446#endif
 447
 448#ifdef CONFIG_FSL_CORENET
 449        do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-1.0",
 450                "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
 451#endif
 452
 453        fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
 454
 455#ifdef CONFIG_MP
 456        ft_fixup_cpu(blob, (u64)bd->bi_memstart + (u64)bd->bi_memsize);
 457        ft_fixup_num_cores(blob);
 458#endif
 459
 460        ft_fixup_cache(blob);
 461
 462#if defined(CONFIG_FSL_ESDHC)
 463        fdt_fixup_esdhc(blob, bd);
 464#endif
 465
 466        ft_fixup_dpaa_clks(blob);
 467
 468#if defined(CONFIG_SYS_BMAN_MEM_PHYS)
 469        fdt_portal(blob, "fsl,bman-portal", "bman-portals",
 470                        (u64)CONFIG_SYS_BMAN_MEM_PHYS,
 471                        CONFIG_SYS_BMAN_MEM_SIZE);
 472#endif
 473
 474#if defined(CONFIG_SYS_QMAN_MEM_PHYS)
 475        fdt_portal(blob, "fsl,qman-portal", "qman-portals",
 476                        (u64)CONFIG_SYS_QMAN_MEM_PHYS,
 477                        CONFIG_SYS_QMAN_MEM_SIZE);
 478
 479        fdt_fixup_qportals(blob);
 480#endif
 481}
 482