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) 2015, 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 { 86 clk->rate = 0; 87 } 88 89 /* Update PLL frequency */ 90 91 /* control1 register */ 92 reg = readl( clk->regs_base + 0x04); 93 94 /* feedback divider integer and fraction parts */ 95 pdiv = ( reg >> 28 ) & 7 ; 96 ndiv_int = ( reg >> 20) & 0xff; 97 ndiv_frac = reg & ((1<<20)-1); 98 99 if( pdiv == 0 ) 100 return -EIO; 101 102 x = clk->parent->rate / pdiv ; 103 104 x = x * ( (u64) ndiv_int << 20 | ndiv_frac ) ; 105 106 clk->rate = x >> 20 ; 107 108 return 0; 109} 110 111static const struct clk_ops lcpll_ops = { 112 .status = lcpll_status, 113}; 114 115static int lcpll_chan_status(struct clk * clk) 116{ 117 void * __iomem base; 118 u32 reg; 119 unsigned enable; 120 unsigned mdiv; 121 122 if( clk->parent == NULL || clk->type != CLK_DIV ) 123 return -EINVAL; 124 125 /* Register address is only stored in PLL structure */ 126 base = clk->parent->regs_base; 127 BUG_ON( base == NULL ); 128 129 /* enable bit is in enableb_ch[] inversed */ 130 enable = ((readl( base + 0 ) >> 6) & 7) ^ 7; 131 132 if( 0 == (enable & (1 << clk->chan))) 133 { 134 clk->rate = 0; 135 return -EIO; 136 } 137 138 /* get divider */ 139 reg = readl(base + 0x08 ); 140 141 mdiv = 0xff & ( reg >> ((0x3^clk->chan) << 3) ); 142 143 /* when divisor is 0, it behaves as max+1 */ 144 if( mdiv == 0 ) 145 mdiv = 1 << 8; 146 147 clk->rate = ( clk->parent->rate / mdiv); 148 return 0; 149} 150 151 152static const struct clk_ops lcpll_chan_ops = { 153 .status = lcpll_chan_status, 154}; 155 156/* 157 * LCPLL has 4 output channels 158 */ 159static struct clk clk_lcpll = { 160 .ops = &lcpll_ops, 161 .name = "LCPLL", 162 .type = CLK_PLL, 163 .chan = 4, 164}; 165 166/* 167 * LCPLL output clocks - 168 * chan 0 - PCIe ref clock, should be 1 GHz, 169 * chan 1 - SDIO clock, e.g. 200 MHz, 170 * chan 2 - DDR clock, typical 166.667 MHz for DDR667, 171 * chan 3 - Unknown 172 */ 173 174static struct clk clk_lcpll_ch[4] = { 175 { .ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 176 .name = "lcpll_ch0", .chan = 0, }, 177 { .ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 178 .name = "lcpll_ch1", .chan = 1, }, 179 { .ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 180 .name = "lcpll_ch2", .chan = 2, }, 181 { .ops = &lcpll_chan_ops, .parent = &clk_lcpll, .type = CLK_DIV, 182 .name = "lcpll_ch3", .chan = 3, }, 183}; 184 185/* 186 * Get PLL running status and update output frequency 187 */ 188static int genpll_status(struct clk * clk) 189{ 190 u32 reg; 191 u64 x; 192 unsigned pdiv, ndiv_int, ndiv_frac; 193 194 if( clk->type != CLK_PLL) 195 return -EINVAL; 196 197 /* Offset of the PLL status register */ 198 reg = readl( clk->regs_base + 0x20 ); 199 200 /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ 201 if( (reg & (1 << 12)) == 0 ) 202 { 203 clk->rate = 0; 204 return -EIO; 205 } 206 207 /* Update PLL frequency */ 208 209 /* get PLL feedback divider values from control5 */ 210 reg = readl( clk->regs_base + 0x14); 211 212 /* feedback divider integer and fraction parts */ 213 ndiv_int = reg >> 20; 214 ndiv_frac = reg & ((1<<20)-1); 215 216 /* get pdiv */ 217 reg = readl( clk->regs_base + 0x18); 218 pdiv = (reg >> 24) & 7; 219 220 if( pdiv == 0 ) 221 return -EIO; 222 223 x = clk->parent->rate / pdiv ; 224 225 x = x * ( (u64) ndiv_int << 20 | ndiv_frac ) ; 226 227 clk->rate = x >> 20 ; 228 229 return 0; 230} 231 232static const struct clk_ops genpll_ops = { 233 .status = genpll_status, 234}; 235 236static int genpll_chan_status(struct clk * clk) 237{ 238 void * __iomem base; 239 u32 reg; 240 unsigned enable; 241 unsigned mdiv; 242 unsigned off, shift; 243 244 if( clk->parent == NULL || clk->type != CLK_DIV ) 245 return -EINVAL; 246 247 /* Register address is only stored in PLL structure */ 248 base = clk->parent->regs_base; 249 250 BUG_ON( base == NULL ); 251 252 /* enable bit is in enableb_ch[0..5] inversed */ 253 enable = ((readl( base + 0x04 ) >> 12) & 0x3f) ^ 0x3f ; 254 255 if( 0 == (enable & (1 << clk->chan))) 256 { 257 clk->rate = 0; 258 return -EIO; 259 } 260 261 /* GENPLL has the 6 channels spread over two regs */ 262 switch( clk->chan ) 263 { 264 case 0: 265 off = 0x18; shift = 16; 266 break; 267 268 case 1: 269 off = 0x18; shift = 8; 270 break; 271 272 case 2: 273 off = 0x18; shift = 0; 274 break; 275 276 case 3: 277 off = 0x1c; shift = 16; 278 break; 279 280 case 4: 281 off = 0x1c; shift = 8; 282 break; 283 284 case 5: 285 off = 0x1c; shift = 0; 286 break; 287 288 default: 289 BUG_ON(clk->chan); 290 off = shift = 0; /* fend off warnings */ 291 } 292 293 reg = readl( base + off ); 294 295 mdiv = 0xff & ( reg >> shift ); 296 297 /* when divisor is 0, it behaves as max+1 */ 298 if( mdiv == 0 ) 299 mdiv = 1 << 8; 300 301 clk->rate = clk->parent->rate / mdiv; 302 return 0; 303} 304 305 306static const struct clk_ops genpll_chan_ops = { 307 .status = genpll_chan_status, 308}; 309 310 311/* 312 * GENPLL has 6 output channels 313 */ 314static struct clk clk_genpll = { 315 .ops = &genpll_ops, 316 .name = "GENPLL", 317 .type = CLK_PLL, 318 .chan = 6, 319}; 320 321/* 322 * chan 0 - Ethernet switch and MAC, RGMII, need 250 MHz 323 * chan 1 - Ethernet switch slow clock, 150 Mhz 324 * chan 2 - USB PHY clock, need 30 MHz 325 * chan 3 - iProc N MHz clock, set from OTP 326 * chan 4 - iProc N/2 MHz clock, set from OTP 327 * chan 5 - iProc N/4 MHz clock, set from OTP 328 * 329 */ 330 331static struct clk clk_genpll_ch[6] = { 332 { .ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 333 .name = "genpll_ch0", .chan = 0, }, 334 { .ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 335 .name = "genpll_ch1", .chan = 1, }, 336 { .ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 337 .name = "genpll_ch2", .chan = 2, }, 338 { .ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 339 .name = "genpll_ch3", .chan = 3, }, 340 { .ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 341 .name = "genpll_ch4", .chan = 4, }, 342 { .ops = &genpll_chan_ops, .parent = &clk_genpll, .type = CLK_DIV, 343 .name = "genpll_ch5", .chan = 5, }, 344}; 345 346/* 347 * This table is used to locate clock sources 348 * from device drivers 349 */ 350 351static struct clk_lookup soc_clk_lookups[] = { 352 { 353 .con_id = "pcie_clk", /* a.k.a. "c_clk100" */ 354 .clk = &clk_lcpll_ch[0], 355 },{ 356 .con_id = "sdio_clk", /* a.k.a. "c_clk200" */ 357 .clk = &clk_lcpll_ch[1], 358 },{ 359 .con_id = "ddr_clk", /* a.k.a. "c_clk400" */ 360 .clk = &clk_lcpll_ch[2], 361 },{ 362 .con_id = "c_clk120", /* unassigned ? */ 363 .clk = &clk_lcpll_ch[3], 364 },{ 365 .con_id = "en_phy_clk", /* "c_clk250" */ 366 .clk = &clk_genpll_ch[0], 367 },{ 368 .con_id = "en_clk", /* "c_clk150" */ 369 .clk = &clk_genpll_ch[1], 370 },{ 371 .con_id = "usb_phy_clk", /* "c_clk30" */ 372 .clk = &clk_genpll_ch[2], 373 },{ 374 .con_id = "iproc_fast_clk", /* "c_clk500" */ 375 .clk = &clk_genpll_ch[3], 376 },{ 377 .con_id = "iproc_med_clk", /* "c_clk250" */ 378 .clk = &clk_genpll_ch[4], 379 },{ 380 .con_id = "iproc_slow_clk", /* "c_clk125" */ 381 .clk = &clk_genpll_ch[5], 382 } 383}; 384void dmu_gpiomux_init(void) 385{ 386#if defined(CONFIG_PLAT_MUX_CONSOLE) || defined(CONFIG_PLAT_MUX_CONSOLE_CCB) || \ 387 defined(CONFIG_SOUND) || defined(CONFIG_SPI_BCM5301X) || defined(CONFIG_I2C_BCM5301X) 388 void * __iomem reg_addr; 389 u32 reg; 390 391 /* CRU_RESET register */ 392 reg_addr = (void *)(SOC_DMU_BASE_VA + 0x1c0); 393#endif /* CONFIG_PLAT_MUX_CONSOLE || CONFIG_PLAT_MUX_CONSOLE_CCB || CONFIG_SOUND || CONFIG_SPI_BCM5301X || CONFIG_I2C_BCM5301X */ 394 395#ifdef CONFIG_PLAT_MUX_CONSOLE 396 /* set iproc_reset_n to 0 to use UART1, but it never comes back */ 397 reg = readl(reg_addr); 398 reg &= ~((u32)0xf << 12); 399 writel(reg, reg_addr); 400#endif /* CONFIG_PLAT_MUX_CONSOLE */ 401#ifdef CONFIG_PLAT_MUX_CONSOLE_CCB 402 /* UART port 2 (ChipCommonB UART0) is multiplexed with GPIO[16:17] */ 403 reg = readl(reg_addr); 404 reg &= ~((u32)0x3 << 16); 405 writel(reg, reg_addr); 406#endif /* CONFIG_PLAT_MUX_CONSOLE_CCB */ 407#ifdef CONFIG_SOUND 408 /* I2S XTAL out */ 409 reg = readl(reg_addr); 410 reg &= ~((u32)0x1 << 18); 411 writel(reg, reg_addr); 412#endif /* CONFIG_SOUND */ 413#ifdef CONFIG_SPI_BCM5301X 414 /* SPI out */ 415 reg = readl(reg_addr); 416 reg &= ~((u32)0xF << 0); 417 writel(reg, reg_addr); 418#endif /* CONFIG_SPI_BCM5301X */ 419#ifdef CONFIG_I2C_BCM5301X 420 /* I2C out */ 421 reg = readl(reg_addr); 422 reg &= ~((u32)0x3 << 4); 423 writel(reg, reg_addr); 424#endif /* CONFIG_I2C_BCM5301X */ 425} 426 427/* 428 * Install above clocks into clock lookup table 429 * and initialize the register base address for each 430*/ 431static void __init soc_clocks_init(void * __iomem cru_regs_base, 432 struct clk * clk_ref) 433{ 434 void * __iomem reg; 435 u32 val; 436 437 /* registers are already mapped with the rest of DMU block */ 438 /* Update register base address */ 439 clk_lcpll.regs_base = cru_regs_base + 0x00 ; 440 clk_genpll.regs_base = cru_regs_base + 0x40 ; 441 442 /* Set parent as reference ckock */ 443 clk_lcpll.parent = clk_ref; 444 clk_genpll.parent = clk_ref; 445 446#ifdef __DEPRECATED__ 447 { 448 int i ; 449 /* We need to clear dev_id fields in the lookups, 450 because if it is set, it will not match by con_id */ 451 for(i = 0; i < ARRAY_SIZE(soc_clk_lookups); i++ ) 452 soc_clk_lookups[i].dev_id = NULL; 453 } 454#endif 455 456 /* Install clock sources into the lookup table */ 457 clkdev_add_table(soc_clk_lookups, ARRAY_SIZE(soc_clk_lookups)); 458 459 /* Correct GMAC 2.66G line rate issue, it should be 2Gbps */ 460 /* This incorrect setting only exist in OTP present 4708 chip */ 461 /* is a OTPed 4708 chip which Ndiv == 0x50 */ 462 reg = clk_genpll.regs_base + 0x14; 463 val = readl(reg); 464 if (((val >> 20) & 0x3ff) == 0x50) { 465 /* CRU_CLKSET_KEY, unlock */ 466 reg = clk_genpll.regs_base + 0x40; 467 val = 0x0000ea68; 468 writel(val, reg); 469 470 /* Change CH0_MDIV to 8 */ 471 /* After changing the CH0_MDIV to 8, the customer has been reporting that 472 * there are differences between input throughput vs. output throughput. 473 * The output throughput is slightly lower (927.537 mbps input rate vs. 927.49 474 * mbps output rate). Below is the solution to fix it. 475 * 1. Change the oscillator on WLAN reference board from 25.000 to 25.001 476 * 2. Change the CH0_MDIV to 7 477 */ 478 reg = clk_genpll.regs_base + 0x18; 479 val = readl(reg); 480 val &= ~((u32)0xff << 16); 481 val |= ((u32)0x7 << 16); 482 writel(val, reg); 483 484 /* Load Enable CH0 */ 485 reg = clk_genpll.regs_base + 0x4; 486 val = readl(reg); 487 val &= ~(u32)0x1; 488 writel(val, reg); 489 val |= (u32)0x1; 490 writel(val, reg); 491 val &= ~(u32)0x1; 492 writel(val, reg); 493 494 /* CRU_CLKSET_KEY, lock */ 495 reg = clk_genpll.regs_base + 0x40; 496 val = 0x0; 497 writel(val, reg); 498 } 499} 500 501void __init soc_dmu_init( struct clk * clk_ref ) 502{ 503 void * __iomem reg_base; 504 505 if( IS_ERR_OR_NULL( clk_ref )) 506 { 507 printk( KERN_ERR "DMU no clock source - skip init\n"); 508 return; 509 } 510 511 BUG_ON( request_resource( &iomem_resource, &dmu_regs )); 512 513 /* DMU regs are mapped as part of the fixed mapping with CCA+CCB */ 514 reg_base = (void *) SOC_DMU_BASE_VA; 515 516 BUG_ON( IS_ERR_OR_NULL(reg_base )); 517 518 /* Initialize clocks */ 519 soc_clocks_init( reg_base + 0x100, clk_ref ); /* CRU LCPLL control0 */ 520 521 dmu_gpiomux_init(); 522} 523 524 525 526 527 528 529 530void soc_clocks_show( void ) 531{ 532 unsigned i; 533 534 printk( "DMU Clocks:\n" ); 535 for(i = 0; i < ARRAY_SIZE( soc_clk_lookups); i++ ) 536 { 537 printk( "%s, %s: (%s) %lu\n", 538 soc_clk_lookups[i].con_id, 539 soc_clk_lookups[i].dev_id, 540 soc_clk_lookups[i].clk->name, 541 clk_get_rate( soc_clk_lookups[i].clk ) 542 ); 543 } 544 printk( "DMU Clocks# %u\n", i ); 545} 546 547#ifdef CONFIG_PROC_FS 548static int dmu_temperature_status(char * buffer, char **start, 549 off_t offset, int length, int * eof, void * data) 550{ 551 int len; 552 off_t pos, begin; 553 void *__iomem pvtmon_base; 554 u32 pvtmon_control0, pvtmon_status; 555 int temperature; 556 557 len = 0; 558 pos = begin = 0; 559 560 pvtmon_base = (void *)(SOC_DMU_BASE_VA + 0x2c0); /* PVTMON control0 */ 561 562 pvtmon_control0 = readl(pvtmon_base); 563 if (pvtmon_control0 & 0xf) { 564 pvtmon_control0 &= ~0xf; 565 writel(pvtmon_control0, pvtmon_base); 566 } 567 568 pvtmon_status = readl(pvtmon_base + 0x8); 569 temperature = 418 - ((5556 * pvtmon_status) / 10000); 570 571 len += sprintf(buffer + len, "CPU temperature\t: %d%cC\n\n", 572 temperature, 0xF8); 573 574 pos = begin + len; 575 576 if (pos < offset) { 577 len = 0; 578 begin = pos; 579 } 580 581 *eof = 1; 582 583 *start = buffer + (offset - begin); 584 len -= (offset - begin); 585 586 if (len > length) 587 len = length; 588 589 return len; 590} 591 592static void __init dmu_proc_init(void) 593{ 594 struct proc_dir_entry *dmu, *dmu_temp; 595 596 dmu = proc_mkdir(DMU_PROC_NAME, NULL); 597 598 if (!dmu) { 599 printk(KERN_ERR "DMU create proc directory failed.\n"); 600 return; 601 } 602 603 dmu_temp = create_proc_read_entry(DMU_PROC_NAME "/temperature", 0, NULL, 604 dmu_temperature_status, NULL); 605 606 if (!dmu_temp) 607 printk(KERN_ERR "DMU create proc entry failed.\n"); 608} 609fs_initcall(dmu_proc_init); 610#endif /* CONFIG_PROC_FS */ 611