root/arch/mips/bcm63xx/cpu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bcm63xx_get_cpu_rev
  2. bcm63xx_get_cpu_freq
  3. bcm63xx_get_memory_size
  4. detect_cpu_clock
  5. detect_memory_size
  6. bcm63xx_cpu_init

   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 
  21 const unsigned long *bcm63xx_regs_base;
  22 EXPORT_SYMBOL(bcm63xx_regs_base);
  23 
  24 const int *bcm63xx_irqs;
  25 EXPORT_SYMBOL(bcm63xx_irqs);
  26 
  27 u16 bcm63xx_cpu_id __read_mostly;
  28 EXPORT_SYMBOL(bcm63xx_cpu_id);
  29 
  30 static u8 bcm63xx_cpu_rev;
  31 static unsigned int bcm63xx_cpu_freq;
  32 static unsigned int bcm63xx_memory_size;
  33 
  34 static const unsigned long bcm3368_regs_base[] = {
  35         __GEN_CPU_REGS_TABLE(3368)
  36 };
  37 
  38 static const int bcm3368_irqs[] = {
  39         __GEN_CPU_IRQ_TABLE(3368)
  40 };
  41 
  42 static const unsigned long bcm6328_regs_base[] = {
  43         __GEN_CPU_REGS_TABLE(6328)
  44 };
  45 
  46 static const int bcm6328_irqs[] = {
  47         __GEN_CPU_IRQ_TABLE(6328)
  48 };
  49 
  50 static const unsigned long bcm6338_regs_base[] = {
  51         __GEN_CPU_REGS_TABLE(6338)
  52 };
  53 
  54 static const int bcm6338_irqs[] = {
  55         __GEN_CPU_IRQ_TABLE(6338)
  56 };
  57 
  58 static const unsigned long bcm6345_regs_base[] = {
  59         __GEN_CPU_REGS_TABLE(6345)
  60 };
  61 
  62 static const int bcm6345_irqs[] = {
  63         __GEN_CPU_IRQ_TABLE(6345)
  64 };
  65 
  66 static const unsigned long bcm6348_regs_base[] = {
  67         __GEN_CPU_REGS_TABLE(6348)
  68 };
  69 
  70 static const int bcm6348_irqs[] = {
  71         __GEN_CPU_IRQ_TABLE(6348)
  72 
  73 };
  74 
  75 static const unsigned long bcm6358_regs_base[] = {
  76         __GEN_CPU_REGS_TABLE(6358)
  77 };
  78 
  79 static const int bcm6358_irqs[] = {
  80         __GEN_CPU_IRQ_TABLE(6358)
  81 
  82 };
  83 
  84 static const unsigned long bcm6362_regs_base[] = {
  85         __GEN_CPU_REGS_TABLE(6362)
  86 };
  87 
  88 static const int bcm6362_irqs[] = {
  89         __GEN_CPU_IRQ_TABLE(6362)
  90 
  91 };
  92 
  93 static const unsigned long bcm6368_regs_base[] = {
  94         __GEN_CPU_REGS_TABLE(6368)
  95 };
  96 
  97 static const int bcm6368_irqs[] = {
  98         __GEN_CPU_IRQ_TABLE(6368)
  99 
 100 };
 101 
 102 u8 bcm63xx_get_cpu_rev(void)
 103 {
 104         return bcm63xx_cpu_rev;
 105 }
 106 
 107 EXPORT_SYMBOL(bcm63xx_get_cpu_rev);
 108 
 109 unsigned int bcm63xx_get_cpu_freq(void)
 110 {
 111         return bcm63xx_cpu_freq;
 112 }
 113 
 114 unsigned int bcm63xx_get_memory_size(void)
 115 {
 116         return bcm63xx_memory_size;
 117 }
 118 
 119 static 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  */
 256 static 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 
 294 void __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                 /* fall-through */
 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 }

/* [<][>][^][v][top][bottom][index][help] */