root/arch/mips/netlogic/xlp/nlm_hal.c

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

DEFINITIONS

This source file includes following definitions.
  1. nlm_node_init
  2. xlp9xx_irq_to_irt
  3. xlp_irq_to_irt
  4. nlm_irq_to_irt
  5. nlm_xlp2_get_core_frequency
  6. nlm_xlp_get_core_frequency
  7. nlm_get_core_frequency
  8. nlm_xlp2_get_pic_frequency
  9. nlm_get_pic_frequency
  10. nlm_get_cpu_frequency
  11. nlm_get_dram_map

   1 /*
   2  * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
   3  * reserved.
   4  *
   5  * This software is available to you under a choice of one of two
   6  * licenses.  You may choose to be licensed under the terms of the GNU
   7  * General Public License (GPL) Version 2, available from the file
   8  * COPYING in the main directory of this source tree, or the NetLogic
   9  * license below:
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  *
  15  * 1. Redistributions of source code must retain the above copyright
  16  *    notice, this list of conditions and the following disclaimer.
  17  * 2. Redistributions in binary form must reproduce the above copyright
  18  *    notice, this list of conditions and the following disclaimer in
  19  *    the documentation and/or other materials provided with the
  20  *    distribution.
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
  23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25  * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
  26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  29  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  32  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33  */
  34 
  35 #include <linux/types.h>
  36 #include <linux/kernel.h>
  37 #include <linux/mm.h>
  38 #include <linux/delay.h>
  39 
  40 #include <asm/mipsregs.h>
  41 #include <asm/time.h>
  42 
  43 #include <asm/netlogic/common.h>
  44 #include <asm/netlogic/haldefs.h>
  45 #include <asm/netlogic/xlp-hal/iomap.h>
  46 #include <asm/netlogic/xlp-hal/xlp.h>
  47 #include <asm/netlogic/xlp-hal/bridge.h>
  48 #include <asm/netlogic/xlp-hal/pic.h>
  49 #include <asm/netlogic/xlp-hal/sys.h>
  50 
  51 /* Main initialization */
  52 void nlm_node_init(int node)
  53 {
  54         struct nlm_soc_info *nodep;
  55 
  56         nodep = nlm_get_node(node);
  57         if (node == 0)
  58                 nodep->coremask = 1;    /* node 0, boot cpu */
  59         nodep->sysbase = nlm_get_sys_regbase(node);
  60         nodep->picbase = nlm_get_pic_regbase(node);
  61         nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
  62         if (cpu_is_xlp9xx())
  63                 nodep->socbus = xlp9xx_get_socbus(node);
  64         else
  65                 nodep->socbus = 0;
  66         spin_lock_init(&nodep->piclock);
  67 }
  68 
  69 static int xlp9xx_irq_to_irt(int irq)
  70 {
  71         switch (irq) {
  72         case PIC_GPIO_IRQ:
  73                 return 12;
  74         case PIC_I2C_0_IRQ:
  75                 return 125;
  76         case PIC_I2C_1_IRQ:
  77                 return 126;
  78         case PIC_I2C_2_IRQ:
  79                 return 127;
  80         case PIC_I2C_3_IRQ:
  81                 return 128;
  82         case PIC_9XX_XHCI_0_IRQ:
  83                 return 114;
  84         case PIC_9XX_XHCI_1_IRQ:
  85                 return 115;
  86         case PIC_9XX_XHCI_2_IRQ:
  87                 return 116;
  88         case PIC_UART_0_IRQ:
  89                 return 133;
  90         case PIC_UART_1_IRQ:
  91                 return 134;
  92         case PIC_SATA_IRQ:
  93                 return 143;
  94         case PIC_NAND_IRQ:
  95                 return 151;
  96         case PIC_SPI_IRQ:
  97                 return 152;
  98         case PIC_MMC_IRQ:
  99                 return 153;
 100         case PIC_PCIE_LINK_LEGACY_IRQ(0):
 101         case PIC_PCIE_LINK_LEGACY_IRQ(1):
 102         case PIC_PCIE_LINK_LEGACY_IRQ(2):
 103         case PIC_PCIE_LINK_LEGACY_IRQ(3):
 104                 return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
 105         }
 106         return -1;
 107 }
 108 
 109 static int xlp_irq_to_irt(int irq)
 110 {
 111         uint64_t pcibase;
 112         int devoff, irt;
 113 
 114         devoff = 0;
 115         switch (irq) {
 116         case PIC_UART_0_IRQ:
 117                 devoff = XLP_IO_UART0_OFFSET(0);
 118                 break;
 119         case PIC_UART_1_IRQ:
 120                 devoff = XLP_IO_UART1_OFFSET(0);
 121                 break;
 122         case PIC_MMC_IRQ:
 123                 devoff = XLP_IO_MMC_OFFSET(0);
 124                 break;
 125         case PIC_I2C_0_IRQ:     /* I2C will be fixed up */
 126         case PIC_I2C_1_IRQ:
 127         case PIC_I2C_2_IRQ:
 128         case PIC_I2C_3_IRQ:
 129                 if (cpu_is_xlpii())
 130                         devoff = XLP2XX_IO_I2C_OFFSET(0);
 131                 else
 132                         devoff = XLP_IO_I2C0_OFFSET(0);
 133                 break;
 134         case PIC_SATA_IRQ:
 135                 devoff = XLP_IO_SATA_OFFSET(0);
 136                 break;
 137         case PIC_GPIO_IRQ:
 138                 devoff = XLP_IO_GPIO_OFFSET(0);
 139                 break;
 140         case PIC_NAND_IRQ:
 141                 devoff = XLP_IO_NAND_OFFSET(0);
 142                 break;
 143         case PIC_SPI_IRQ:
 144                 devoff = XLP_IO_SPI_OFFSET(0);
 145                 break;
 146         default:
 147                 if (cpu_is_xlpii()) {
 148                         switch (irq) {
 149                                 /* XLP2XX has three XHCI USB controller */
 150                         case PIC_2XX_XHCI_0_IRQ:
 151                                 devoff = XLP2XX_IO_USB_XHCI0_OFFSET(0);
 152                                 break;
 153                         case PIC_2XX_XHCI_1_IRQ:
 154                                 devoff = XLP2XX_IO_USB_XHCI1_OFFSET(0);
 155                                 break;
 156                         case PIC_2XX_XHCI_2_IRQ:
 157                                 devoff = XLP2XX_IO_USB_XHCI2_OFFSET(0);
 158                                 break;
 159                         }
 160                 } else {
 161                         switch (irq) {
 162                         case PIC_EHCI_0_IRQ:
 163                                 devoff = XLP_IO_USB_EHCI0_OFFSET(0);
 164                                 break;
 165                         case PIC_EHCI_1_IRQ:
 166                                 devoff = XLP_IO_USB_EHCI1_OFFSET(0);
 167                                 break;
 168                         case PIC_OHCI_0_IRQ:
 169                                 devoff = XLP_IO_USB_OHCI0_OFFSET(0);
 170                                 break;
 171                         case PIC_OHCI_1_IRQ:
 172                                 devoff = XLP_IO_USB_OHCI1_OFFSET(0);
 173                                 break;
 174                         case PIC_OHCI_2_IRQ:
 175                                 devoff = XLP_IO_USB_OHCI2_OFFSET(0);
 176                                 break;
 177                         case PIC_OHCI_3_IRQ:
 178                                 devoff = XLP_IO_USB_OHCI3_OFFSET(0);
 179                                 break;
 180                         }
 181                 }
 182         }
 183 
 184         if (devoff != 0) {
 185                 uint32_t val;
 186 
 187                 pcibase = nlm_pcicfg_base(devoff);
 188                 val = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG);
 189                 if (val == 0xffffffff) {
 190                         irt = -1;
 191                 } else {
 192                         irt = val & 0xffff;
 193                         /* HW weirdness, I2C IRT entry has to be fixed up */
 194                         switch (irq) {
 195                         case PIC_I2C_1_IRQ:
 196                                 irt = irt + 1; break;
 197                         case PIC_I2C_2_IRQ:
 198                                 irt = irt + 2; break;
 199                         case PIC_I2C_3_IRQ:
 200                                 irt = irt + 3; break;
 201                         }
 202                 }
 203         } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) &&
 204                         irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) {
 205                 /* HW bug, PCI IRT entries are bad on early silicon, fix */
 206                 irt = PIC_IRT_PCIE_LINK_INDEX(irq -
 207                                         PIC_PCIE_LINK_LEGACY_IRQ_BASE);
 208         } else {
 209                 irt = -1;
 210         }
 211         return irt;
 212 }
 213 
 214 int nlm_irq_to_irt(int irq)
 215 {
 216         /* return -2 for irqs without 1-1 mapping */
 217         if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
 218                 return -2;
 219         if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
 220                 return -2;
 221 
 222         if (cpu_is_xlp9xx())
 223                 return xlp9xx_irq_to_irt(irq);
 224         else
 225                 return xlp_irq_to_irt(irq);
 226 }
 227 
 228 static unsigned int nlm_xlp2_get_core_frequency(int node, int core)
 229 {
 230         unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom;
 231         uint64_t num, sysbase, clockbase;
 232 
 233         if (cpu_is_xlp9xx()) {
 234                 clockbase = nlm_get_clock_regbase(node);
 235                 ctrl_val0 = nlm_read_sys_reg(clockbase,
 236                                         SYS_9XX_CPU_PLL_CTRL0(core));
 237                 ctrl_val1 = nlm_read_sys_reg(clockbase,
 238                                         SYS_9XX_CPU_PLL_CTRL1(core));
 239         } else {
 240                 sysbase = nlm_get_node(node)->sysbase;
 241                 ctrl_val0 = nlm_read_sys_reg(sysbase,
 242                                                 SYS_CPU_PLL_CTRL0(core));
 243                 ctrl_val1 = nlm_read_sys_reg(sysbase,
 244                                                 SYS_CPU_PLL_CTRL1(core));
 245         }
 246 
 247         /* Find PLL post divider value */
 248         switch ((ctrl_val0 >> 24) & 0x7) {
 249         case 1:
 250                 pll_post_div = 2;
 251                 break;
 252         case 3:
 253                 pll_post_div = 4;
 254                 break;
 255         case 7:
 256                 pll_post_div = 8;
 257                 break;
 258         case 6:
 259                 pll_post_div = 16;
 260                 break;
 261         case 0:
 262         default:
 263                 pll_post_div = 1;
 264                 break;
 265         }
 266 
 267         num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f));
 268         denom = 3 * pll_post_div;
 269         do_div(num, denom);
 270 
 271         return (unsigned int)num;
 272 }
 273 
 274 static unsigned int nlm_xlp_get_core_frequency(int node, int core)
 275 {
 276         unsigned int pll_divf, pll_divr, dfs_div, ext_div;
 277         unsigned int rstval, dfsval, denom;
 278         uint64_t num, sysbase;
 279 
 280         sysbase = nlm_get_node(node)->sysbase;
 281         rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
 282         dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
 283         pll_divf = ((rstval >> 10) & 0x7f) + 1;
 284         pll_divr = ((rstval >> 8)  & 0x3) + 1;
 285         ext_div  = ((rstval >> 30) & 0x3) + 1;
 286         dfs_div  = ((dfsval >> (core * 4)) & 0xf) + 1;
 287 
 288         num = 800000000ULL * pll_divf;
 289         denom = 3 * pll_divr * ext_div * dfs_div;
 290         do_div(num, denom);
 291 
 292         return (unsigned int)num;
 293 }
 294 
 295 unsigned int nlm_get_core_frequency(int node, int core)
 296 {
 297         if (cpu_is_xlpii())
 298                 return nlm_xlp2_get_core_frequency(node, core);
 299         else
 300                 return nlm_xlp_get_core_frequency(node, core);
 301 }
 302 
 303 /*
 304  * Calculate PIC frequency from PLL registers.
 305  * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
 306  *              ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
 307  */
 308 static unsigned int nlm_xlp2_get_pic_frequency(int node)
 309 {
 310         u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx;
 311         u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
 312         u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk;
 313 
 314         sysbase = nlm_get_node(node)->sysbase;
 315         clockbase = nlm_get_clock_regbase(node);
 316         cpu_xlp9xx = cpu_is_xlp9xx();
 317 
 318         /* Find ref_clk_base */
 319         if (cpu_xlp9xx)
 320                 ref_clk_select = (nlm_read_sys_reg(sysbase,
 321                                 SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3;
 322         else
 323                 ref_clk_select = (nlm_read_sys_reg(sysbase,
 324                                         SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
 325         switch (ref_clk_select) {
 326         case 0:
 327                 ref_clk = 200000000ULL;
 328                 ref_div = 3;
 329                 break;
 330         case 1:
 331                 ref_clk = 100000000ULL;
 332                 ref_div = 1;
 333                 break;
 334         case 2:
 335                 ref_clk = 125000000ULL;
 336                 ref_div = 1;
 337                 break;
 338         case 3:
 339                 ref_clk = 400000000ULL;
 340                 ref_div = 3;
 341                 break;
 342         }
 343 
 344         /* Find the clock source PLL device for PIC */
 345         if (cpu_xlp9xx) {
 346                 reg_select = nlm_read_sys_reg(clockbase,
 347                                 SYS_9XX_CLK_DEV_SEL_REG) & 0x3;
 348                 switch (reg_select) {
 349                 case 0:
 350                         ctrl_val0 = nlm_read_sys_reg(clockbase,
 351                                         SYS_9XX_PLL_CTRL0);
 352                         ctrl_val2 = nlm_read_sys_reg(clockbase,
 353                                         SYS_9XX_PLL_CTRL2);
 354                         break;
 355                 case 1:
 356                         ctrl_val0 = nlm_read_sys_reg(clockbase,
 357                                         SYS_9XX_PLL_CTRL0_DEVX(0));
 358                         ctrl_val2 = nlm_read_sys_reg(clockbase,
 359                                         SYS_9XX_PLL_CTRL2_DEVX(0));
 360                         break;
 361                 case 2:
 362                         ctrl_val0 = nlm_read_sys_reg(clockbase,
 363                                         SYS_9XX_PLL_CTRL0_DEVX(1));
 364                         ctrl_val2 = nlm_read_sys_reg(clockbase,
 365                                         SYS_9XX_PLL_CTRL2_DEVX(1));
 366                         break;
 367                 case 3:
 368                         ctrl_val0 = nlm_read_sys_reg(clockbase,
 369                                         SYS_9XX_PLL_CTRL0_DEVX(2));
 370                         ctrl_val2 = nlm_read_sys_reg(clockbase,
 371                                         SYS_9XX_PLL_CTRL2_DEVX(2));
 372                         break;
 373                 }
 374         } else {
 375                 reg_select = (nlm_read_sys_reg(sysbase,
 376                                         SYS_CLK_DEV_SEL_REG) >> 22) & 0x3;
 377                 switch (reg_select) {
 378                 case 0:
 379                         ctrl_val0 = nlm_read_sys_reg(sysbase,
 380                                         SYS_PLL_CTRL0);
 381                         ctrl_val2 = nlm_read_sys_reg(sysbase,
 382                                         SYS_PLL_CTRL2);
 383                         break;
 384                 case 1:
 385                         ctrl_val0 = nlm_read_sys_reg(sysbase,
 386                                         SYS_PLL_CTRL0_DEVX(0));
 387                         ctrl_val2 = nlm_read_sys_reg(sysbase,
 388                                         SYS_PLL_CTRL2_DEVX(0));
 389                         break;
 390                 case 2:
 391                         ctrl_val0 = nlm_read_sys_reg(sysbase,
 392                                         SYS_PLL_CTRL0_DEVX(1));
 393                         ctrl_val2 = nlm_read_sys_reg(sysbase,
 394                                         SYS_PLL_CTRL2_DEVX(1));
 395                         break;
 396                 case 3:
 397                         ctrl_val0 = nlm_read_sys_reg(sysbase,
 398                                         SYS_PLL_CTRL0_DEVX(2));
 399                         ctrl_val2 = nlm_read_sys_reg(sysbase,
 400                                         SYS_PLL_CTRL2_DEVX(2));
 401                         break;
 402                 }
 403         }
 404 
 405         vco_post_div = (ctrl_val0 >> 5) & 0x7;
 406         pll_post_div = (ctrl_val0 >> 24) & 0x7;
 407         mdiv = ctrl_val2 & 0xff;
 408         fdiv = (ctrl_val2 >> 8) & 0x1fff;
 409 
 410         /* Find PLL post divider value */
 411         switch (pll_post_div) {
 412         case 1:
 413                 pll_post_div = 2;
 414                 break;
 415         case 3:
 416                 pll_post_div = 4;
 417                 break;
 418         case 7:
 419                 pll_post_div = 8;
 420                 break;
 421         case 6:
 422                 pll_post_div = 16;
 423                 break;
 424         case 0:
 425         default:
 426                 pll_post_div = 1;
 427                 break;
 428         }
 429 
 430         fdiv = fdiv/(1 << 13);
 431         pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv;
 432         pll_out_freq_den = (1 << vco_post_div) * pll_post_div * ref_div;
 433 
 434         if (pll_out_freq_den > 0)
 435                 do_div(pll_out_freq_num, pll_out_freq_den);
 436 
 437         /* PIC post divider, which happens after PLL */
 438         if (cpu_xlp9xx)
 439                 pic_div = nlm_read_sys_reg(clockbase,
 440                                 SYS_9XX_CLK_DEV_DIV_REG) & 0x3;
 441         else
 442                 pic_div = (nlm_read_sys_reg(sysbase,
 443                                         SYS_CLK_DEV_DIV_REG) >> 22) & 0x3;
 444         do_div(pll_out_freq_num, 1 << pic_div);
 445 
 446         return pll_out_freq_num;
 447 }
 448 
 449 unsigned int nlm_get_pic_frequency(int node)
 450 {
 451         if (cpu_is_xlpii())
 452                 return nlm_xlp2_get_pic_frequency(node);
 453         else
 454                 return 133333333;
 455 }
 456 
 457 unsigned int nlm_get_cpu_frequency(void)
 458 {
 459         return nlm_get_core_frequency(0, 0);
 460 }
 461 
 462 /*
 463  * Fills upto 8 pairs of entries containing the DRAM map of a node
 464  * if node < 0, get dram map for all nodes
 465  */
 466 int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries)
 467 {
 468         uint64_t bridgebase, base, lim;
 469         uint32_t val;
 470         unsigned int barreg, limreg, xlatreg;
 471         int i, n, rv;
 472 
 473         /* Look only at mapping on Node 0, we don't handle crazy configs */
 474         bridgebase = nlm_get_bridge_regbase(0);
 475         rv = 0;
 476         for (i = 0; i < 8; i++) {
 477                 if (rv + 1 >= nentries)
 478                         break;
 479                 if (cpu_is_xlp9xx()) {
 480                         barreg = BRIDGE_9XX_DRAM_BAR(i);
 481                         limreg = BRIDGE_9XX_DRAM_LIMIT(i);
 482                         xlatreg = BRIDGE_9XX_DRAM_NODE_TRANSLN(i);
 483                 } else {
 484                         barreg = BRIDGE_DRAM_BAR(i);
 485                         limreg = BRIDGE_DRAM_LIMIT(i);
 486                         xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i);
 487                 }
 488                 if (node >= 0) {
 489                         /* node specified, get node mapping of BAR */
 490                         val = nlm_read_bridge_reg(bridgebase, xlatreg);
 491                         n = (val >> 1) & 0x3;
 492                         if (n != node)
 493                                 continue;
 494                 }
 495                 val = nlm_read_bridge_reg(bridgebase, barreg);
 496                 val = (val >>  12) & 0xfffff;
 497                 base = (uint64_t) val << 20;
 498                 val = nlm_read_bridge_reg(bridgebase, limreg);
 499                 val = (val >>  12) & 0xfffff;
 500                 if (val == 0)   /* BAR not used */
 501                         continue;
 502                 lim = ((uint64_t)val + 1) << 20;
 503                 dram_map[rv] = base;
 504                 dram_map[rv + 1] = lim;
 505                 rv += 2;
 506         }
 507         return rv;
 508 }

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