1/* 2 * Northstar DMU (Device Management Unit), 3 * i.e. clocks, I/O pads, GPIO etc. 4 * SoC-specific hardware support features. 5 * 6 * Documents: 7 * Northstar_top_power_uarch_v1_0.pdf 8 * 9 * Copyright (C) 2014, Broadcom Corporation. All Rights Reserved. 10 * 11 * Permission to use, copy, modify, and/or distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 * $Id: $ 24 */ 25#include <linux/kernel.h> 26#include <linux/init.h> 27#include <linux/module.h> 28#include <linux/errno.h> 29#include <linux/err.h> 30#include <linux/clk.h> 31#include <linux/io.h> 32#include <linux/ioport.h> 33#include <linux/delay.h> 34#include <linux/proc_fs.h> 35 36#include <asm/clkdev.h> 37#include <mach/clkdev.h> 38#include <mach/io_map.h> 39#include <plat/plat-bcm5301x.h> 40 41#ifdef CONFIG_PROC_FS 42#define DMU_PROC_NAME "dmu" 43#endif /* CONFIG_PROC_FS */ 44 45static struct resource dmu_regs = { 46 .name = "dmu_regs", 47 .start = SOC_DMU_BASE_PA, 48 .end = SOC_DMU_BASE_PA + SZ_4K -1, 49 .flags = IORESOURCE_MEM, 50}; 51 52/* 53 * Clock management scheme is a provisional implementation 54 * only intended to retreive the pre-set frequencies for each 55 * of the clocks. 56 * Better handling of post-dividers and fractional part of 57 * feedbeck dividers need to be added. 58 * Need to understand what diagnostics from CRU registers could 59 * be handy, and export that via a sysfs interface. 60 */ 61 62/* 63 * The CRU contains two similar PLLs: LCPLL and GENPLL, 64 * both with several output channels divided from the PLL 65 * output 66 */ 67 68/* 69 * Get PLL running status and update output frequency 70 */ 71static int lcpll_status(struct clk * clk) 72{ 73 u32 reg; 74 u64 x; 75 unsigned pdiv, ndiv_int, ndiv_frac; 76 77 if (clk->type != CLK_PLL) 78 return -EINVAL; 79 80 /* read status register */ 81 reg = readl(clk->regs_base + 0x10); 82 83 /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ 84 if ((reg & (1 << 12)) == 0) { 85 clk->rate = 0; 86 } 87 88 /* Update PLL frequency */ 89 90 /* control1 register */ 91 reg = readl(clk->regs_base + 0x04); 92 93 /* feedback divider integer and fraction parts */ 94 pdiv = (reg >> 28) & 7; 95 ndiv_int = (reg >> 20) & 0xff; 96 ndiv_frac = reg & ((1<<20)-1); 97 98 if (pdiv == 0) 99 return -EIO; 100 101 x = clk->parent->rate / pdiv; 102 103 x = x * ((u64) ndiv_int << 20 | ndiv_frac); 104 105 clk->rate = x >> 20; 106 107 return 0; 108} 109 110static const struct clk_ops lcpll_ops = { 111 .status = lcpll_status, 112}; 113 114static int lcpll_chan_status(struct clk * clk) 115{ 116 void * __iomem base; 117 u32 reg; 118 unsigned enable; 119 unsigned mdiv; 120 121 if (clk->parent == NULL || clk->type != CLK_DIV) 122 return -EINVAL; 123 124 /* Register address is only stored in PLL structure */ 125 base = clk->parent->regs_base; 126 BUG_ON(base == NULL); 127 128 /* enable bit is in enableb_ch[] inversed */ 129 enable = ((readl(base + 0) >> 6) & 7) ^ 7; 130 131 if ((enable & (1 << clk->chan)) == 0) { 132 clk->rate = 0; 133 return -EIO; 134 } 135 136 /* get divider */ 137 reg = readl(base + 0x08); 138 139 mdiv = 0xff & (reg >> ((0x3^clk->chan) << 3)); 140 141 /* when divisor is 0, it behaves as max+1 */ 142 if (mdiv == 0) 143 mdiv = 1 << 8; 144 145 clk->rate = (clk->parent->rate / mdiv); 146 return 0; 147} 148 149 150static const struct clk_ops lcpll_chan_ops = { 151 .status = lcpll_chan_status, 152}; 153 154/* 155 * LCPLL has 4 output channels 156 */ 157static struct clk clk_lcpll = { 158 .ops = &lcpll_ops, 159 .name = "LCPLL", 160 .type = CLK_PLL, 161 .chan = 4, 162}; 163 164/* 165 * LCPLL output clocks - 166 * chan 0 - PCIe ref clock, should be 1 GHz, 167 * chan 1 - SDIO clock, e.g. 200 MHz, 168 * chan 2 - DDR clock, typical 166.667 MHz for DDR667, 169 * chan 3 - Unknown 170 */ 171 172static struct clk clk_lcpll_ch[4] = { 173 {.ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 174 .name = "lcpll_ch0", .chan = 0}, 175 {.ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 176 .name = "lcpll_ch1", .chan = 1}, 177 {.ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 178 .name = "lcpll_ch2", .chan = 2}, 179 {.ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 180 .name = "lcpll_ch3", .chan = 3}, 181}; 182 183/* 184 * Get PLL running status and update output frequency 185 */ 186static int genpll_status(struct clk * clk) 187{ 188 u32 reg; 189 u64 x; 190 unsigned pdiv, ndiv_int, ndiv_frac; 191 192 if (clk->type != CLK_PLL) 193 return -EINVAL; 194 195 /* Offset of the PLL status register */ 196 reg = readl(clk->regs_base + 0x20); 197 198 /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ 199 if ((reg & (1 << 12)) == 0) { 200 clk->rate = 0; 201 return -EIO; 202 } 203 204 /* Update PLL frequency */ 205 206 /* get PLL feedback divider values from control5 */ 207 reg = readl(clk->regs_base + 0x14); 208 209 /* feedback divider integer and fraction parts */ 210 ndiv_int = reg >> 20; 211 ndiv_frac = reg & ((1<<20)-1); 212 213 /* get pdiv */ 214 reg = readl(clk->regs_base + 0x18); 215 pdiv = (reg >> 24) & 7; 216 217 if (pdiv == 0) 218 return -EIO; 219 220 x = clk->parent->rate / pdiv; 221 222 x = x * ((u64)ndiv_int << 20 | ndiv_frac); 223 224 clk->rate = x >> 20; 225 226 return 0; 227} 228 229static const struct clk_ops genpll_ops = { 230 .status = genpll_status, 231}; 232 233static int genpll_chan_status(struct clk * clk) 234{ 235 void * __iomem base; 236 u32 reg; 237 unsigned enable; 238 unsigned mdiv; 239 unsigned off, shift; 240 241 if (clk->parent == NULL || clk->type != CLK_DIV) 242 return -EINVAL; 243 244 /* Register address is only stored in PLL structure */ 245 base = clk->parent->regs_base; 246 247 BUG_ON(base == NULL); 248 249 /* enable bit is in enableb_ch[0..5] inversed */ 250 enable = ((readl(base + 0x04) >> 12) & 0x3f) ^ 0x3f; 251 252 if ((enable & (1 << clk->chan)) == 0) { 253 clk->rate = 0; 254 return -EIO; 255 } 256 257 /* GENPLL has the 6 channels spread over two regs */ 258 switch (clk->chan) 259 { 260 case 0: 261 off = 0x18; shift = 16; 262 break; 263 264 case 1: 265 off = 0x18; shift = 8; 266 break; 267 268 case 2: 269 off = 0x18; shift = 0; 270 break; 271 272 case 3: 273 off = 0x1c; shift = 16; 274 break; 275 276 case 4: 277 off = 0x1c; shift = 8; 278 break; 279 280 case 5: 281 off = 0x1c; shift = 0; 282 break; 283 284 default: 285 BUG_ON(clk->chan); 286 off = shift = 0; /* fend off warnings */ 287 } 288 289 reg = readl(base + off); 290 291 mdiv = 0xff & (reg >> shift); 292 293 /* when divisor is 0, it behaves as max+1 */ 294 if (mdiv == 0) 295 mdiv = 1 << 8; 296 297 clk->rate = clk->parent->rate / mdiv; 298 return 0; 299} 300 301 302static const struct clk_ops genpll_chan_ops = { 303 .status = genpll_chan_status, 304}; 305 306 307/* 308 * GENPLL has 6 output channels 309 */ 310static struct clk clk_genpll = { 311 .ops = &genpll_ops, 312 .name = "GENPLL", 313 .type = CLK_PLL, 314 .chan = 6, 315}; 316 317/* 318 * chan 0 - Ethernet switch and MAC, RGMII, need 250 MHz 319 * chan 1 - Ethernet switch slow clock, 150 Mhz 320 * chan 2 - USB PHY clock, need 30 MHz 321 * chan 3 - iProc N MHz clock, set from OTP 322 * chan 4 - iProc N/2 MHz clock, set from OTP 323 * chan 5 - iProc N/4 MHz clock, set from OTP 324 * 325 */ 326 327static struct clk clk_genpll_ch[6] = { 328 {.ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 329 .name = "genpll_ch0", .chan = 0}, 330 {.ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 331 .name = "genpll_ch1", .chan = 1}, 332 {.ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 333 .name = "genpll_ch2", .chan = 2}, 334 {.ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 335 .name = "genpll_ch3", .chan = 3}, 336 {.ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 337 .name = "genpll_ch4", .chan = 4}, 338 {.ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 339 .name = "genpll_ch5", .chan = 5} 340}; 341 342/* 343 * This table is used to locate clock sources 344 * from device drivers 345 */ 346 347static struct clk_lookup soc_clk_lookups[] = { 348 /* a.k.a. "c_clk100" */ 349 {.con_id = "pcie_clk", .clk = &clk_lcpll_ch[0]}, 350 /* a.k.a. "c_clk200" */ 351 {.con_id = "sdio_clk", .clk = &clk_lcpll_ch[1]}, 352 /* a.k.a. "c_clk400" */ 353 {.con_id = "ddr_clk", .clk = &clk_lcpll_ch[2]}, 354 /* unassigned ? */ 355 {.con_id = "c_clk120", .clk = &clk_lcpll_ch[3]}, 356 /* "c_clk250" */ 357 {.con_id = "en_phy_clk", .clk = &clk_genpll_ch[0]}, 358 /* "c_clk150" */ 359 {.con_id = "en_clk", .clk = &clk_genpll_ch[1]}, 360 /* "c_clk30" */ 361 {.con_id = "usb_phy_clk", .clk = &clk_genpll_ch[2]}, 362 /* "c_clk500" */ 363 {.con_id = "iproc_fast_clk", .clk = &clk_genpll_ch[3]}, 364 /* "c_clk250" */ 365 {.con_id = "iproc_med_clk", .clk = &clk_genpll_ch[4]}, 366 /* "c_clk125" */ 367 {.con_id = "iproc_slow_clk", .clk = &clk_genpll_ch[5]} 368}; 369 370void dmu_gpiomux_init(void) 371{ 372#ifdef CONFIG_PLAT_MUX_CONSOLE 373 void * __iomem reg_addr; 374 u32 reg; 375 376 /* CRU_RESET register */ 377 reg_addr = (void *)(SOC_DMU_BASE_VA + 0x1c0); 378 379 /* set iproc_reset_n to 0 to use UART1, but it never comes back */ 380 reg = readl(reg_addr); 381 reg &= ~((u32)0xf << 12); 382 writel(reg, reg_addr); 383#endif /* CONFIG_PLAT_MUX_CONSOLE */ 384} 385 386/* 387 * Install above clocks into clock lookup table 388 * and initialize the register base address for each 389*/ 390static void __init soc_clocks_init(void * __iomem cru_regs_base, 391 struct clk * clk_ref) 392{ 393 void * __iomem reg; 394 u32 val; 395 396 /* registers are already mapped with the rest of DMU block */ 397 /* Update register base address */ 398 clk_lcpll.regs_base = cru_regs_base + 0x00; 399 clk_genpll.regs_base = cru_regs_base + 0x40; 400 401 /* Set parent as reference ckock */ 402 clk_lcpll.parent = clk_ref; 403 clk_genpll.parent = clk_ref; 404 405#ifdef __DEPRECATED__ 406 { 407 int i; 408 /* We need to clear dev_id fields in the lookups, 409 * because if it is set, it will not match by con_id 410 */ 411 for (i = 0; i < ARRAY_SIZE(soc_clk_lookups); i++) 412 soc_clk_lookups[i].dev_id = NULL; 413 } 414#endif 415 416 /* Install clock sources into the lookup table */ 417 clkdev_add_table(soc_clk_lookups, ARRAY_SIZE(soc_clk_lookups)); 418 419 /* Correct GMAC 2.66G line rate issue, it should be 2Gbps */ 420 /* This incorrect setting only exist in OTP present 4708 chip */ 421 /* is a OTPed 4708 chip which Ndiv == 0x50 */ 422 reg = clk_genpll.regs_base + 0x14; 423 val = readl(reg); 424 if (((val >> 20) & 0x3ff) == 0x50) { 425 /* CRU_CLKSET_KEY, unlock */ 426 reg = clk_genpll.regs_base + 0x40; 427 val = 0x0000ea68; 428 writel(val, reg); 429 430 /* Change CH0_MDIV to 8 */ 431 /* After changing the CH0_MDIV to 8, the customer has been reporting that 432 * there are differences between input throughput vs. output throughput. 433 * The output throughput is slightly lower (927.537 mbps input rate vs. 927.49 434 * mbps output rate). Below is the solution to fix it. 435 * 1. Change the oscillator on WLAN reference board from 25.000 to 25.001 436 * 2. Change the CH0_MDIV to 7 437 */ 438 reg = clk_genpll.regs_base + 0x18; 439 val = readl(reg); 440 val &= ~((u32)0xff << 16); 441 val |= ((u32)0x7 << 16); 442 writel(val, reg); 443 444 /* Load Enable CH0 */ 445 reg = clk_genpll.regs_base + 0x4; 446 val = readl(reg); 447 val &= ~(u32)0x1; 448 writel(val, reg); 449 val |= (u32)0x1; 450 writel(val, reg); 451 val &= ~(u32)0x1; 452 writel(val, reg); 453 454 /* CRU_CLKSET_KEY, lock */ 455 reg = clk_genpll.regs_base + 0x40; 456 val = 0x0; 457 writel(val, reg); 458 } 459} 460 461void __init soc_dmu_init(struct clk *clk_ref) 462{ 463 void * __iomem reg_base; 464 465 if (IS_ERR_OR_NULL(clk_ref)) { 466 printk(KERN_ERR "DMU no clock source - skip init\n"); 467 return; 468 } 469 470 BUG_ON(request_resource(&iomem_resource, &dmu_regs)); 471 472 /* DMU regs are mapped as part of the fixed mapping with CCA+CCB */ 473 reg_base = (void *)SOC_DMU_BASE_VA; 474 475 BUG_ON(IS_ERR_OR_NULL(reg_base)); 476 477 /* Initialize clocks */ 478 soc_clocks_init(reg_base + 0x100, clk_ref); /* CRU LCPLL control0 */ 479 480 dmu_gpiomux_init(); 481} 482 483 484 485 486 487 488void soc_clocks_show(void) 489{ 490 unsigned i; 491 492 printk("DMU Clocks:\n"); 493 for (i = 0; i < ARRAY_SIZE(soc_clk_lookups); i++) { 494 printk("%s, %s: (%s) %lu\n", 495 soc_clk_lookups[i].con_id, 496 soc_clk_lookups[i].dev_id, 497 soc_clk_lookups[i].clk->name, 498 clk_get_rate(soc_clk_lookups[i].clk)); 499 } 500 501 printk("DMU Clocks# %u\n", i); 502} 503 504#ifdef CONFIG_PROC_FS 505static int dmu_temperature_status(char * buffer, char **start, 506 off_t offset, int length, int * eof, void * data) 507{ 508 int len; 509 off_t pos, begin; 510 void *__iomem pvtmon_base; 511 u32 pvtmon_control0, pvtmon_status; 512 int temperature; 513 514 len = 0; 515 pos = begin = 0; 516 517 pvtmon_base = (void *)(SOC_DMU_BASE_VA + 0x2c0); /* PVTMON control0 */ 518 519 pvtmon_control0 = readl(pvtmon_base); 520 if (pvtmon_control0 & 0xf) { 521 pvtmon_control0 &= ~0xf; 522 writel(pvtmon_control0, pvtmon_base); 523 } 524 525 pvtmon_status = readl(pvtmon_base + 0x8); 526 temperature = 418 - ((5556 * pvtmon_status) / 10000); 527 528 len += sprintf(buffer + len, "CPU temperature\t: %d%cC\n\n", 529 temperature, 0xF8); 530 531 pos = begin + len; 532 533 if (pos < offset) { 534 len = 0; 535 begin = pos; 536 } 537 538 *eof = 1; 539 540 *start = buffer + (offset - begin); 541 len -= (offset - begin); 542 543 if (len > length) 544 len = length; 545 546 return len; 547} 548 549static void __init dmu_proc_init(void) 550{ 551 struct proc_dir_entry *dmu, *dmu_temp; 552 553 dmu = proc_mkdir(DMU_PROC_NAME, NULL); 554 555 if (!dmu) { 556 printk(KERN_ERR "DMU create proc directory failed.\n"); 557 return; 558 } 559 560 dmu_temp = create_proc_read_entry(DMU_PROC_NAME "/temperature", 0, NULL, 561 dmu_temperature_status, NULL); 562 563 if (!dmu_temp) 564 printk(KERN_ERR "DMU create proc entry failed.\n"); 565} 566fs_initcall(dmu_proc_init); 567#endif /* CONFIG_PROC_FS */ 568