uboot/drivers/cpu/bmips_cpu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
   4 *
   5 * Derived from linux/arch/mips/bcm63xx/cpu.c:
   6 *      Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   7 *      Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
   8 */
   9
  10#include <common.h>
  11#include <cpu.h>
  12#include <dm.h>
  13#include <errno.h>
  14#include <asm/io.h>
  15
  16#define REV_CHIPID_SHIFT                16
  17#define REV_CHIPID_MASK                 (0xffff << REV_CHIPID_SHIFT)
  18#define REV_LONG_CHIPID_SHIFT           12
  19#define REV_LONG_CHIPID_MASK            (0xfffff << REV_LONG_CHIPID_SHIFT)
  20#define REV_REVID_SHIFT                 0
  21#define REV_REVID_MASK                  (0xff << REV_REVID_SHIFT)
  22
  23#define REG_BCM6328_OTP                 0x62c
  24#define BCM6328_TP1_DISABLED            BIT(9)
  25
  26#define REG_BCM6318_STRAP_OVRDBUS       0x900
  27#define OVRDBUS_6318_FREQ_SHIFT         23
  28#define OVRDBUS_6318_FREQ_MASK          (0x3 << OVRDBUS_6318_FREQ_SHIFT)
  29
  30#define REG_BCM6328_MISC_STRAPBUS       0x1a40
  31#define STRAPBUS_6328_FCVO_SHIFT        7
  32#define STRAPBUS_6328_FCVO_MASK         (0x1f << STRAPBUS_6328_FCVO_SHIFT)
  33
  34#define REG_BCM6348_PERF_MIPSPLLCFG     0x34
  35#define MIPSPLLCFG_6348_M1CPU_SHIFT     6
  36#define MIPSPLLCFG_6348_M1CPU_MASK      (0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT)
  37#define MIPSPLLCFG_6348_N2_SHIFT        15
  38#define MIPSPLLCFG_6348_N2_MASK         (0x1F << MIPSPLLCFG_6348_N2_SHIFT)
  39#define MIPSPLLCFG_6348_N1_SHIFT        20
  40#define MIPSPLLCFG_6348_N1_MASK         (0x7 << MIPSPLLCFG_6348_N1_SHIFT)
  41
  42#define REG_BCM6358_DDR_DMIPSPLLCFG     0x12b8
  43#define DMIPSPLLCFG_6358_M1_SHIFT       0
  44#define DMIPSPLLCFG_6358_M1_MASK        (0xff << DMIPSPLLCFG_6358_M1_SHIFT)
  45#define DMIPSPLLCFG_6358_N1_SHIFT       23
  46#define DMIPSPLLCFG_6358_N1_MASK        (0x3f << DMIPSPLLCFG_6358_N1_SHIFT)
  47#define DMIPSPLLCFG_6358_N2_SHIFT       29
  48#define DMIPSPLLCFG_6358_N2_MASK        (0x7 << DMIPSPLLCFG_6358_N2_SHIFT)
  49
  50#define REG_BCM6362_MISC_STRAPBUS       0x1814
  51#define STRAPBUS_6362_FCVO_SHIFT        1
  52#define STRAPBUS_6362_FCVO_MASK         (0x1f << STRAPBUS_6362_FCVO_SHIFT)
  53
  54#define REG_BCM6368_DDR_DMIPSPLLCFG     0x12a0
  55#define DMIPSPLLCFG_6368_P1_SHIFT       0
  56#define DMIPSPLLCFG_6368_P1_MASK        (0xf << DMIPSPLLCFG_6368_P1_SHIFT)
  57#define DMIPSPLLCFG_6368_P2_SHIFT       4
  58#define DMIPSPLLCFG_6368_P2_MASK        (0xf << DMIPSPLLCFG_6368_P2_SHIFT)
  59#define DMIPSPLLCFG_6368_NDIV_SHIFT     16
  60#define DMIPSPLLCFG_6368_NDIV_MASK      (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT)
  61#define REG_BCM6368_DDR_DMIPSPLLDIV     0x12a4
  62#define DMIPSPLLDIV_6368_MDIV_SHIFT     0
  63#define DMIPSPLLDIV_6368_MDIV_MASK      (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT)
  64
  65#define REG_BCM63268_MISC_STRAPBUS      0x1814
  66#define STRAPBUS_63268_FCVO_SHIFT       21
  67#define STRAPBUS_63268_FCVO_MASK        (0xf << STRAPBUS_63268_FCVO_SHIFT)
  68
  69#define REG_BCM6838_OTP_BRCMBITS0       0x440
  70#define VIPER_6838_FREQ_SHIFT           18
  71#define VIPER_6838_FREQ_MASK            (0x7 << VIPER_6838_FREQ_SHIFT)
  72
  73struct bmips_cpu_priv;
  74
  75struct bmips_cpu_hw {
  76        int (*get_cpu_desc)(struct bmips_cpu_priv *priv, char *buf, int size);
  77        ulong (*get_cpu_freq)(struct bmips_cpu_priv *);
  78        int (*get_cpu_count)(struct bmips_cpu_priv *);
  79};
  80
  81struct bmips_cpu_priv {
  82        void __iomem *regs;
  83        const struct bmips_cpu_hw *hw;
  84};
  85
  86/* Specific CPU Ops */
  87static int bmips_short_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
  88                                int size)
  89{
  90        unsigned short cpu_id;
  91        unsigned char cpu_rev;
  92        u32 val;
  93
  94        val = readl_be(priv->regs);
  95        cpu_id = (val & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
  96        cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
  97
  98        snprintf(buf, size, "BCM%04X%02X", cpu_id, cpu_rev);
  99
 100        return 0;
 101}
 102
 103static int bmips_long_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
 104                                int size)
 105{
 106        unsigned int cpu_id;
 107        unsigned char cpu_rev;
 108        u32 val;
 109
 110        val = readl_be(priv->regs);
 111        cpu_id = (val & REV_LONG_CHIPID_MASK) >> REV_LONG_CHIPID_SHIFT;
 112        cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
 113
 114        snprintf(buf, size, "BCM%05X%02X", cpu_id, cpu_rev);
 115
 116        return 0;
 117}
 118
 119static ulong bcm3380_get_cpu_freq(struct bmips_cpu_priv *priv)
 120{
 121        return 333000000;
 122}
 123
 124static ulong bcm6318_get_cpu_freq(struct bmips_cpu_priv *priv)
 125{
 126        unsigned int mips_pll_fcvo;
 127
 128        mips_pll_fcvo = readl_be(priv->regs + REG_BCM6318_STRAP_OVRDBUS);
 129        mips_pll_fcvo = (mips_pll_fcvo & OVRDBUS_6318_FREQ_MASK)
 130                        >> OVRDBUS_6318_FREQ_SHIFT;
 131
 132        switch (mips_pll_fcvo) {
 133        case 0:
 134                return 166000000;
 135        case 1:
 136                return 400000000;
 137        case 2:
 138                return 250000000;
 139        case 3:
 140                return 333000000;
 141        default:
 142                return 0;
 143        }
 144}
 145
 146static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv)
 147{
 148        unsigned int mips_pll_fcvo;
 149
 150        mips_pll_fcvo = readl_be(priv->regs + REG_BCM6328_MISC_STRAPBUS);
 151        mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6328_FCVO_MASK)
 152                        >> STRAPBUS_6328_FCVO_SHIFT;
 153
 154        switch (mips_pll_fcvo) {
 155        case 0x12:
 156        case 0x14:
 157        case 0x19:
 158                return 160000000;
 159        case 0x1c:
 160                return 192000000;
 161        case 0x13:
 162        case 0x15:
 163                return 200000000;
 164        case 0x1a:
 165                return 384000000;
 166        case 0x16:
 167                return 400000000;
 168        default:
 169                return 320000000;
 170        }
 171}
 172
 173static ulong bcm6338_get_cpu_freq(struct bmips_cpu_priv *priv)
 174{
 175        return 240000000;
 176}
 177
 178static ulong bcm6348_get_cpu_freq(struct bmips_cpu_priv *priv)
 179{
 180        unsigned int tmp, n1, n2, m1;
 181
 182        tmp = readl_be(priv->regs + REG_BCM6348_PERF_MIPSPLLCFG);
 183        n1 = (tmp & MIPSPLLCFG_6348_N1_MASK) >> MIPSPLLCFG_6348_N1_SHIFT;
 184        n2 = (tmp & MIPSPLLCFG_6348_N2_MASK) >> MIPSPLLCFG_6348_N2_SHIFT;
 185        m1 = (tmp & MIPSPLLCFG_6348_M1CPU_MASK) >> MIPSPLLCFG_6348_M1CPU_SHIFT;
 186
 187        return (16 * 1000000 * (n1 + 1) * (n2 + 2)) / (m1 + 1);
 188}
 189
 190static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv)
 191{
 192        unsigned int tmp, n1, n2, m1;
 193
 194        tmp = readl_be(priv->regs + REG_BCM6358_DDR_DMIPSPLLCFG);
 195        n1 = (tmp & DMIPSPLLCFG_6358_N1_MASK) >> DMIPSPLLCFG_6358_N1_SHIFT;
 196        n2 = (tmp & DMIPSPLLCFG_6358_N2_MASK) >> DMIPSPLLCFG_6358_N2_SHIFT;
 197        m1 = (tmp & DMIPSPLLCFG_6358_M1_MASK) >> DMIPSPLLCFG_6358_M1_SHIFT;
 198
 199        return (16 * 1000000 * n1 * n2) / m1;
 200}
 201
 202static ulong bcm6362_get_cpu_freq(struct bmips_cpu_priv *priv)
 203{
 204        unsigned int mips_pll_fcvo;
 205
 206        mips_pll_fcvo = readl_be(priv->regs + REG_BCM6362_MISC_STRAPBUS);
 207        mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6362_FCVO_MASK)
 208                        >> STRAPBUS_6362_FCVO_SHIFT;
 209
 210        switch (mips_pll_fcvo) {
 211        case 0x03:
 212        case 0x0b:
 213        case 0x13:
 214        case 0x1b:
 215                return 240000000;
 216        case 0x04:
 217        case 0x0c:
 218        case 0x14:
 219        case 0x1c:
 220                return 160000000;
 221        case 0x05:
 222        case 0x0e:
 223        case 0x16:
 224        case 0x1e:
 225        case 0x1f:
 226                return 400000000;
 227        case 0x06:
 228                return 440000000;
 229        case 0x07:
 230        case 0x17:
 231                return 384000000;
 232        case 0x15:
 233        case 0x1d:
 234                return 200000000;
 235        default:
 236                return 320000000;
 237        }
 238}
 239
 240static ulong bcm6368_get_cpu_freq(struct bmips_cpu_priv *priv)
 241{
 242        unsigned int tmp, p1, p2, ndiv, m1;
 243
 244        tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLCFG);
 245        p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> DMIPSPLLCFG_6368_P1_SHIFT;
 246        p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> DMIPSPLLCFG_6368_P2_SHIFT;
 247        ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
 248               DMIPSPLLCFG_6368_NDIV_SHIFT;
 249
 250        tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLDIV);
 251        m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> DMIPSPLLDIV_6368_MDIV_SHIFT;
 252
 253        return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
 254}
 255
 256static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv)
 257{
 258        unsigned int mips_pll_fcvo;
 259
 260        mips_pll_fcvo = readl_be(priv->regs + REG_BCM63268_MISC_STRAPBUS);
 261        mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_63268_FCVO_MASK)
 262                        >> STRAPBUS_63268_FCVO_SHIFT;
 263
 264        switch (mips_pll_fcvo) {
 265        case 0x3:
 266        case 0xe:
 267                return 320000000;
 268        case 0xa:
 269                return 333000000;
 270        case 0x2:
 271        case 0xb:
 272        case 0xf:
 273                return 400000000;
 274        default:
 275                return 0;
 276        }
 277}
 278
 279static ulong bcm6838_get_cpu_freq(struct bmips_cpu_priv *priv)
 280{
 281        unsigned int mips_viper_freq;
 282
 283        mips_viper_freq = readl_be(priv->regs + REG_BCM6838_OTP_BRCMBITS0);
 284        mips_viper_freq = (mips_viper_freq & VIPER_6838_FREQ_MASK)
 285                >> VIPER_6838_FREQ_SHIFT;
 286
 287        switch (mips_viper_freq) {
 288        case 0x0:
 289                return 600000000;
 290        case 0x1:
 291                return 400000000;
 292        case 0x2:
 293                return 240000000;
 294        default:
 295                return 0;
 296        }
 297}
 298
 299static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv)
 300{
 301        u32 val = readl_be(priv->regs + REG_BCM6328_OTP);
 302
 303        if (val & BCM6328_TP1_DISABLED)
 304                return 1;
 305        else
 306                return 2;
 307}
 308
 309static int bcm6345_get_cpu_count(struct bmips_cpu_priv *priv)
 310{
 311        return 1;
 312}
 313
 314static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv)
 315{
 316        return 2;
 317}
 318
 319static const struct bmips_cpu_hw bmips_cpu_bcm3380 = {
 320        .get_cpu_desc = bmips_short_cpu_desc,
 321        .get_cpu_freq = bcm3380_get_cpu_freq,
 322        .get_cpu_count = bcm6358_get_cpu_count,
 323};
 324
 325static const struct bmips_cpu_hw bmips_cpu_bcm6318 = {
 326        .get_cpu_desc = bmips_short_cpu_desc,
 327        .get_cpu_freq = bcm6318_get_cpu_freq,
 328        .get_cpu_count = bcm6345_get_cpu_count,
 329};
 330
 331static const struct bmips_cpu_hw bmips_cpu_bcm6328 = {
 332        .get_cpu_desc = bmips_long_cpu_desc,
 333        .get_cpu_freq = bcm6328_get_cpu_freq,
 334        .get_cpu_count = bcm6328_get_cpu_count,
 335};
 336
 337static const struct bmips_cpu_hw bmips_cpu_bcm6338 = {
 338        .get_cpu_desc = bmips_short_cpu_desc,
 339        .get_cpu_freq = bcm6338_get_cpu_freq,
 340        .get_cpu_count = bcm6345_get_cpu_count,
 341};
 342
 343static const struct bmips_cpu_hw bmips_cpu_bcm6348 = {
 344        .get_cpu_desc = bmips_short_cpu_desc,
 345        .get_cpu_freq = bcm6348_get_cpu_freq,
 346        .get_cpu_count = bcm6345_get_cpu_count,
 347};
 348
 349static const struct bmips_cpu_hw bmips_cpu_bcm6358 = {
 350        .get_cpu_desc = bmips_short_cpu_desc,
 351        .get_cpu_freq = bcm6358_get_cpu_freq,
 352        .get_cpu_count = bcm6358_get_cpu_count,
 353};
 354
 355static const struct bmips_cpu_hw bmips_cpu_bcm6362 = {
 356        .get_cpu_desc = bmips_short_cpu_desc,
 357        .get_cpu_freq = bcm6362_get_cpu_freq,
 358        .get_cpu_count = bcm6358_get_cpu_count,
 359};
 360
 361static const struct bmips_cpu_hw bmips_cpu_bcm6368 = {
 362        .get_cpu_desc = bmips_short_cpu_desc,
 363        .get_cpu_freq = bcm6368_get_cpu_freq,
 364        .get_cpu_count = bcm6358_get_cpu_count,
 365};
 366
 367static const struct bmips_cpu_hw bmips_cpu_bcm63268 = {
 368        .get_cpu_desc = bmips_long_cpu_desc,
 369        .get_cpu_freq = bcm63268_get_cpu_freq,
 370        .get_cpu_count = bcm6358_get_cpu_count,
 371};
 372
 373static const struct bmips_cpu_hw bmips_cpu_bcm6838 = {
 374        .get_cpu_desc = bmips_short_cpu_desc,
 375        .get_cpu_freq = bcm6838_get_cpu_freq,
 376        .get_cpu_count = bcm6358_get_cpu_count,
 377};
 378
 379/* Generic CPU Ops */
 380static int bmips_cpu_get_desc(struct udevice *dev, char *buf, int size)
 381{
 382        struct bmips_cpu_priv *priv = dev_get_priv(dev);
 383        const struct bmips_cpu_hw *hw = priv->hw;
 384
 385        return hw->get_cpu_desc(priv, buf, size);
 386}
 387
 388static int bmips_cpu_get_info(struct udevice *dev, struct cpu_info *info)
 389{
 390        struct bmips_cpu_priv *priv = dev_get_priv(dev);
 391        const struct bmips_cpu_hw *hw = priv->hw;
 392
 393        info->cpu_freq = hw->get_cpu_freq(priv);
 394        info->features = BIT(CPU_FEAT_L1_CACHE);
 395        info->features |= BIT(CPU_FEAT_MMU);
 396        info->features |= BIT(CPU_FEAT_DEVICE_ID);
 397
 398        return 0;
 399}
 400
 401static int bmips_cpu_get_count(struct udevice *dev)
 402{
 403        struct bmips_cpu_priv *priv = dev_get_priv(dev);
 404        const struct bmips_cpu_hw *hw = priv->hw;
 405
 406        return hw->get_cpu_count(priv);
 407}
 408
 409static int bmips_cpu_get_vendor(struct udevice *dev, char *buf, int size)
 410{
 411        snprintf(buf, size, "Broadcom");
 412
 413        return 0;
 414}
 415
 416static const struct cpu_ops bmips_cpu_ops = {
 417        .get_desc = bmips_cpu_get_desc,
 418        .get_info = bmips_cpu_get_info,
 419        .get_count = bmips_cpu_get_count,
 420        .get_vendor = bmips_cpu_get_vendor,
 421};
 422
 423/* BMIPS CPU driver */
 424int bmips_cpu_bind(struct udevice *dev)
 425{
 426        struct cpu_platdata *plat = dev_get_parent_platdata(dev);
 427
 428        plat->cpu_id = dev_read_u32_default(dev, "reg", -1);
 429        plat->device_id = read_c0_prid();
 430
 431        return 0;
 432}
 433
 434int bmips_cpu_probe(struct udevice *dev)
 435{
 436        struct bmips_cpu_priv *priv = dev_get_priv(dev);
 437        const struct bmips_cpu_hw *hw =
 438                (const struct bmips_cpu_hw *)dev_get_driver_data(dev);
 439
 440        priv->regs = dev_remap_addr(dev_get_parent(dev));
 441        if (!priv->regs)
 442                return -EINVAL;
 443
 444        priv->hw = hw;
 445
 446        return 0;
 447}
 448
 449static const struct udevice_id bmips_cpu_ids[] = {
 450        {
 451                .compatible = "brcm,bcm3380-cpu",
 452                .data = (ulong)&bmips_cpu_bcm3380,
 453        }, {
 454                .compatible = "brcm,bcm6318-cpu",
 455                .data = (ulong)&bmips_cpu_bcm6318,
 456        }, {
 457                .compatible = "brcm,bcm6328-cpu",
 458                .data = (ulong)&bmips_cpu_bcm6328,
 459        }, {
 460                .compatible = "brcm,bcm6338-cpu",
 461                .data = (ulong)&bmips_cpu_bcm6338,
 462        }, {
 463                .compatible = "brcm,bcm6348-cpu",
 464                .data = (ulong)&bmips_cpu_bcm6348,
 465        }, {
 466                .compatible = "brcm,bcm6358-cpu",
 467                .data = (ulong)&bmips_cpu_bcm6358,
 468        }, {
 469                .compatible = "brcm,bcm6362-cpu",
 470                .data = (ulong)&bmips_cpu_bcm6362,
 471        }, {
 472                .compatible = "brcm,bcm6368-cpu",
 473                .data = (ulong)&bmips_cpu_bcm6368,
 474        }, {
 475                .compatible = "brcm,bcm63268-cpu",
 476                .data = (ulong)&bmips_cpu_bcm63268,
 477        }, {
 478                .compatible = "brcm,bcm6838-cpu",
 479                .data = (ulong)&bmips_cpu_bcm6838,
 480        },
 481        { /* sentinel */ }
 482};
 483
 484U_BOOT_DRIVER(bmips_cpu_drv) = {
 485        .name = "bmips_cpu",
 486        .id = UCLASS_CPU,
 487        .of_match = bmips_cpu_ids,
 488        .bind = bmips_cpu_bind,
 489        .probe = bmips_cpu_probe,
 490        .priv_auto_alloc_size = sizeof(struct bmips_cpu_priv),
 491        .ops = &bmips_cpu_ops,
 492        .flags = DM_FLAG_PRE_RELOC,
 493};
 494
 495#ifdef CONFIG_DISPLAY_CPUINFO
 496int print_cpuinfo(void)
 497{
 498        struct cpu_info cpu;
 499        struct udevice *dev;
 500        int err;
 501        char desc[100];
 502
 503        err = uclass_get_device(UCLASS_CPU, 0, &dev);
 504        if (err)
 505                return 0;
 506
 507        err = cpu_get_info(dev, &cpu);
 508        if (err)
 509                return 0;
 510
 511        err = cpu_get_desc(dev, desc, sizeof(desc));
 512        if (err)
 513                return 0;
 514
 515        printf("Chip ID: %s, MIPS: ", desc);
 516        print_freq(cpu.cpu_freq, "\n");
 517
 518        return 0;
 519}
 520#endif
 521