linux/arch/mips/bcm63xx/cpu.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   7 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/export.h>
  12#include <linux/cpu.h>
  13#include <asm/cpu.h>
  14#include <asm/cpu-info.h>
  15#include <asm/mipsregs.h>
  16#include <bcm63xx_cpu.h>
  17#include <bcm63xx_regs.h>
  18#include <bcm63xx_io.h>
  19#include <bcm63xx_irq.h>
  20
  21const unsigned long *bcm63xx_regs_base;
  22EXPORT_SYMBOL(bcm63xx_regs_base);
  23
  24const int *bcm63xx_irqs;
  25EXPORT_SYMBOL(bcm63xx_irqs);
  26
  27u16 bcm63xx_cpu_id __read_mostly;
  28EXPORT_SYMBOL(bcm63xx_cpu_id);
  29
  30static u8 bcm63xx_cpu_rev;
  31static unsigned int bcm63xx_cpu_freq;
  32static unsigned int bcm63xx_memory_size;
  33
  34static const unsigned long bcm3368_regs_base[] = {
  35        __GEN_CPU_REGS_TABLE(3368)
  36};
  37
  38static const int bcm3368_irqs[] = {
  39        __GEN_CPU_IRQ_TABLE(3368)
  40};
  41
  42static const unsigned long bcm6328_regs_base[] = {
  43        __GEN_CPU_REGS_TABLE(6328)
  44};
  45
  46static const int bcm6328_irqs[] = {
  47        __GEN_CPU_IRQ_TABLE(6328)
  48};
  49
  50static const unsigned long bcm6338_regs_base[] = {
  51        __GEN_CPU_REGS_TABLE(6338)
  52};
  53
  54static const int bcm6338_irqs[] = {
  55        __GEN_CPU_IRQ_TABLE(6338)
  56};
  57
  58static const unsigned long bcm6345_regs_base[] = {
  59        __GEN_CPU_REGS_TABLE(6345)
  60};
  61
  62static const int bcm6345_irqs[] = {
  63        __GEN_CPU_IRQ_TABLE(6345)
  64};
  65
  66static const unsigned long bcm6348_regs_base[] = {
  67        __GEN_CPU_REGS_TABLE(6348)
  68};
  69
  70static const int bcm6348_irqs[] = {
  71        __GEN_CPU_IRQ_TABLE(6348)
  72
  73};
  74
  75static const unsigned long bcm6358_regs_base[] = {
  76        __GEN_CPU_REGS_TABLE(6358)
  77};
  78
  79static const int bcm6358_irqs[] = {
  80        __GEN_CPU_IRQ_TABLE(6358)
  81
  82};
  83
  84static const unsigned long bcm6362_regs_base[] = {
  85        __GEN_CPU_REGS_TABLE(6362)
  86};
  87
  88static const int bcm6362_irqs[] = {
  89        __GEN_CPU_IRQ_TABLE(6362)
  90
  91};
  92
  93static const unsigned long bcm6368_regs_base[] = {
  94        __GEN_CPU_REGS_TABLE(6368)
  95};
  96
  97static const int bcm6368_irqs[] = {
  98        __GEN_CPU_IRQ_TABLE(6368)
  99
 100};
 101
 102u8 bcm63xx_get_cpu_rev(void)
 103{
 104        return bcm63xx_cpu_rev;
 105}
 106
 107EXPORT_SYMBOL(bcm63xx_get_cpu_rev);
 108
 109unsigned int bcm63xx_get_cpu_freq(void)
 110{
 111        return bcm63xx_cpu_freq;
 112}
 113
 114unsigned int bcm63xx_get_memory_size(void)
 115{
 116        return bcm63xx_memory_size;
 117}
 118
 119static unsigned int detect_cpu_clock(void)
 120{
 121        u16 cpu_id = bcm63xx_get_cpu_id();
 122
 123        switch (cpu_id) {
 124        case BCM3368_CPU_ID:
 125                return 300000000;
 126
 127        case BCM6328_CPU_ID:
 128        {
 129                unsigned int tmp, mips_pll_fcvo;
 130
 131                tmp = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
 132                mips_pll_fcvo = (tmp & STRAPBUS_6328_FCVO_MASK)
 133                                >> STRAPBUS_6328_FCVO_SHIFT;
 134
 135                switch (mips_pll_fcvo) {
 136                case 0x12:
 137                case 0x14:
 138                case 0x19:
 139                        return 160000000;
 140                case 0x1c:
 141                        return 192000000;
 142                case 0x13:
 143                case 0x15:
 144                        return 200000000;
 145                case 0x1a:
 146                        return 384000000;
 147                case 0x16:
 148                        return 400000000;
 149                default:
 150                        return 320000000;
 151                }
 152
 153        }
 154        case BCM6338_CPU_ID:
 155                /* BCM6338 has a fixed 240 Mhz frequency */
 156                return 240000000;
 157
 158        case BCM6345_CPU_ID:
 159                /* BCM6345 has a fixed 140Mhz frequency */
 160                return 140000000;
 161
 162        case BCM6348_CPU_ID:
 163        {
 164                unsigned int tmp, n1, n2, m1;
 165
 166                /* 16MHz * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) */
 167                tmp = bcm_perf_readl(PERF_MIPSPLLCTL_REG);
 168                n1 = (tmp & MIPSPLLCTL_N1_MASK) >> MIPSPLLCTL_N1_SHIFT;
 169                n2 = (tmp & MIPSPLLCTL_N2_MASK) >> MIPSPLLCTL_N2_SHIFT;
 170                m1 = (tmp & MIPSPLLCTL_M1CPU_MASK) >> MIPSPLLCTL_M1CPU_SHIFT;
 171                n1 += 1;
 172                n2 += 2;
 173                m1 += 1;
 174                return (16 * 1000000 * n1 * n2) / m1;
 175        }
 176
 177        case BCM6358_CPU_ID:
 178        {
 179                unsigned int tmp, n1, n2, m1;
 180
 181                /* 16MHz * N1 * N2 / M1_CPU */
 182                tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_REG);
 183                n1 = (tmp & DMIPSPLLCFG_N1_MASK) >> DMIPSPLLCFG_N1_SHIFT;
 184                n2 = (tmp & DMIPSPLLCFG_N2_MASK) >> DMIPSPLLCFG_N2_SHIFT;
 185                m1 = (tmp & DMIPSPLLCFG_M1_MASK) >> DMIPSPLLCFG_M1_SHIFT;
 186                return (16 * 1000000 * n1 * n2) / m1;
 187        }
 188
 189        case BCM6362_CPU_ID:
 190        {
 191                unsigned int tmp, mips_pll_fcvo;
 192
 193                tmp = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
 194                mips_pll_fcvo = (tmp & STRAPBUS_6362_FCVO_MASK)
 195                                >> STRAPBUS_6362_FCVO_SHIFT;
 196                switch (mips_pll_fcvo) {
 197                case 0x03:
 198                case 0x0b:
 199                case 0x13:
 200                case 0x1b:
 201                        return 240000000;
 202                case 0x04:
 203                case 0x0c:
 204                case 0x14:
 205                case 0x1c:
 206                        return 160000000;
 207                case 0x05:
 208                case 0x0e:
 209                case 0x16:
 210                case 0x1e:
 211                case 0x1f:
 212                        return 400000000;
 213                case 0x06:
 214                        return 440000000;
 215                case 0x07:
 216                case 0x17:
 217                        return 384000000;
 218                case 0x15:
 219                case 0x1d:
 220                        return 200000000;
 221                default:
 222                        return 320000000;
 223                }
 224        }
 225        case BCM6368_CPU_ID:
 226        {
 227                unsigned int tmp, p1, p2, ndiv, m1;
 228
 229                /* (64MHz / P1) * P2 * NDIV / M1_CPU */
 230                tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_6368_REG);
 231
 232                p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >>
 233                        DMIPSPLLCFG_6368_P1_SHIFT;
 234
 235                p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >>
 236                        DMIPSPLLCFG_6368_P2_SHIFT;
 237
 238                ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
 239                        DMIPSPLLCFG_6368_NDIV_SHIFT;
 240
 241                tmp = bcm_ddr_readl(DDR_DMIPSPLLDIV_6368_REG);
 242                m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >>
 243                        DMIPSPLLDIV_6368_MDIV_SHIFT;
 244
 245                return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
 246        }
 247
 248        default:
 249                panic("Failed to detect clock for CPU with id=%04X\n", cpu_id);
 250        }
 251}
 252
 253/*
 254 * attempt to detect the amount of memory installed
 255 */
 256static unsigned int detect_memory_size(void)
 257{
 258        unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
 259        u32 val;
 260
 261        if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
 262                return bcm_ddr_readl(DDR_CSEND_REG) << 24;
 263
 264        if (BCMCPU_IS_6345()) {
 265                val = bcm_sdram_readl(SDRAM_MBASE_REG);
 266                return val * 8 * 1024 * 1024;
 267        }
 268
 269        if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
 270                val = bcm_sdram_readl(SDRAM_CFG_REG);
 271                rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
 272                cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
 273                is_32bits = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
 274                banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
 275        }
 276
 277        if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
 278                val = bcm_memc_readl(MEMC_CFG_REG);
 279                rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
 280                cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
 281                is_32bits = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
 282                banks = 2;
 283        }
 284
 285        /* 0 => 11 address bits ... 2 => 13 address bits */
 286        rows += 11;
 287
 288        /* 0 => 8 address bits ... 2 => 10 address bits */
 289        cols += 8;
 290
 291        return 1 << (cols + rows + (is_32bits + 1) + banks);
 292}
 293
 294void __init bcm63xx_cpu_init(void)
 295{
 296        unsigned int tmp;
 297        unsigned int cpu = smp_processor_id();
 298        u32 chipid_reg;
 299
 300        /* soc registers location depends on cpu type */
 301        chipid_reg = 0;
 302
 303        switch (current_cpu_type()) {
 304        case CPU_BMIPS3300:
 305                if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
 306                        __cpu_name[cpu] = "Broadcom BCM6338";
 307                fallthrough;
 308        case CPU_BMIPS32:
 309                chipid_reg = BCM_6345_PERF_BASE;
 310                break;
 311        case CPU_BMIPS4350:
 312                switch ((read_c0_prid() & PRID_REV_MASK)) {
 313                case 0x04:
 314                        chipid_reg = BCM_3368_PERF_BASE;
 315                        break;
 316                case 0x10:
 317                        chipid_reg = BCM_6345_PERF_BASE;
 318                        break;
 319                default:
 320                        chipid_reg = BCM_6368_PERF_BASE;
 321                        break;
 322                }
 323                break;
 324        }
 325
 326        /*
 327         * really early to panic, but delaying panic would not help since we
 328         * will never get any working console
 329         */
 330        if (!chipid_reg)
 331                panic("unsupported Broadcom CPU");
 332
 333        /* read out CPU type */
 334        tmp = bcm_readl(chipid_reg);
 335        bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
 336        bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
 337
 338        switch (bcm63xx_cpu_id) {
 339        case BCM3368_CPU_ID:
 340                bcm63xx_regs_base = bcm3368_regs_base;
 341                bcm63xx_irqs = bcm3368_irqs;
 342                break;
 343        case BCM6328_CPU_ID:
 344                bcm63xx_regs_base = bcm6328_regs_base;
 345                bcm63xx_irqs = bcm6328_irqs;
 346                break;
 347        case BCM6338_CPU_ID:
 348                bcm63xx_regs_base = bcm6338_regs_base;
 349                bcm63xx_irqs = bcm6338_irqs;
 350                break;
 351        case BCM6345_CPU_ID:
 352                bcm63xx_regs_base = bcm6345_regs_base;
 353                bcm63xx_irqs = bcm6345_irqs;
 354                break;
 355        case BCM6348_CPU_ID:
 356                bcm63xx_regs_base = bcm6348_regs_base;
 357                bcm63xx_irqs = bcm6348_irqs;
 358                break;
 359        case BCM6358_CPU_ID:
 360                bcm63xx_regs_base = bcm6358_regs_base;
 361                bcm63xx_irqs = bcm6358_irqs;
 362                break;
 363        case BCM6362_CPU_ID:
 364                bcm63xx_regs_base = bcm6362_regs_base;
 365                bcm63xx_irqs = bcm6362_irqs;
 366                break;
 367        case BCM6368_CPU_ID:
 368                bcm63xx_regs_base = bcm6368_regs_base;
 369                bcm63xx_irqs = bcm6368_irqs;
 370                break;
 371        default:
 372                panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
 373                break;
 374        }
 375
 376        bcm63xx_cpu_freq = detect_cpu_clock();
 377        bcm63xx_memory_size = detect_memory_size();
 378
 379        pr_info("Detected Broadcom 0x%04x CPU revision %02x\n",
 380                bcm63xx_cpu_id, bcm63xx_cpu_rev);
 381        pr_info("CPU frequency is %u MHz\n",
 382                bcm63xx_cpu_freq / 1000000);
 383        pr_info("%uMB of RAM installed\n",
 384                bcm63xx_memory_size >> 20);
 385}
 386