18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights 38c2ecf20Sopenharmony_ci * reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 68c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the NetLogic 98c2ecf20Sopenharmony_ci * license below: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 128c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 138c2ecf20Sopenharmony_ci * are met: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 168c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 178c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 188c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 198c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 208c2ecf20Sopenharmony_ci * distribution. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR 238c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE 268c2ecf20Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 298c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 308c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 318c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 328c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/types.h> 368c2ecf20Sopenharmony_ci#include <linux/kernel.h> 378c2ecf20Sopenharmony_ci#include <linux/mm.h> 388c2ecf20Sopenharmony_ci#include <linux/delay.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include <asm/mipsregs.h> 418c2ecf20Sopenharmony_ci#include <asm/time.h> 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#include <asm/netlogic/common.h> 448c2ecf20Sopenharmony_ci#include <asm/netlogic/haldefs.h> 458c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/iomap.h> 468c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/xlp.h> 478c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/bridge.h> 488c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/pic.h> 498c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/sys.h> 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* Main initialization */ 528c2ecf20Sopenharmony_civoid nlm_node_init(int node) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct nlm_soc_info *nodep; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci nodep = nlm_get_node(node); 578c2ecf20Sopenharmony_ci if (node == 0) 588c2ecf20Sopenharmony_ci nodep->coremask = 1; /* node 0, boot cpu */ 598c2ecf20Sopenharmony_ci nodep->sysbase = nlm_get_sys_regbase(node); 608c2ecf20Sopenharmony_ci nodep->picbase = nlm_get_pic_regbase(node); 618c2ecf20Sopenharmony_ci nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE; 628c2ecf20Sopenharmony_ci if (cpu_is_xlp9xx()) 638c2ecf20Sopenharmony_ci nodep->socbus = xlp9xx_get_socbus(node); 648c2ecf20Sopenharmony_ci else 658c2ecf20Sopenharmony_ci nodep->socbus = 0; 668c2ecf20Sopenharmony_ci spin_lock_init(&nodep->piclock); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int xlp9xx_irq_to_irt(int irq) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci switch (irq) { 728c2ecf20Sopenharmony_ci case PIC_GPIO_IRQ: 738c2ecf20Sopenharmony_ci return 12; 748c2ecf20Sopenharmony_ci case PIC_I2C_0_IRQ: 758c2ecf20Sopenharmony_ci return 125; 768c2ecf20Sopenharmony_ci case PIC_I2C_1_IRQ: 778c2ecf20Sopenharmony_ci return 126; 788c2ecf20Sopenharmony_ci case PIC_I2C_2_IRQ: 798c2ecf20Sopenharmony_ci return 127; 808c2ecf20Sopenharmony_ci case PIC_I2C_3_IRQ: 818c2ecf20Sopenharmony_ci return 128; 828c2ecf20Sopenharmony_ci case PIC_9XX_XHCI_0_IRQ: 838c2ecf20Sopenharmony_ci return 114; 848c2ecf20Sopenharmony_ci case PIC_9XX_XHCI_1_IRQ: 858c2ecf20Sopenharmony_ci return 115; 868c2ecf20Sopenharmony_ci case PIC_9XX_XHCI_2_IRQ: 878c2ecf20Sopenharmony_ci return 116; 888c2ecf20Sopenharmony_ci case PIC_UART_0_IRQ: 898c2ecf20Sopenharmony_ci return 133; 908c2ecf20Sopenharmony_ci case PIC_UART_1_IRQ: 918c2ecf20Sopenharmony_ci return 134; 928c2ecf20Sopenharmony_ci case PIC_SATA_IRQ: 938c2ecf20Sopenharmony_ci return 143; 948c2ecf20Sopenharmony_ci case PIC_NAND_IRQ: 958c2ecf20Sopenharmony_ci return 151; 968c2ecf20Sopenharmony_ci case PIC_SPI_IRQ: 978c2ecf20Sopenharmony_ci return 152; 988c2ecf20Sopenharmony_ci case PIC_MMC_IRQ: 998c2ecf20Sopenharmony_ci return 153; 1008c2ecf20Sopenharmony_ci case PIC_PCIE_LINK_LEGACY_IRQ(0): 1018c2ecf20Sopenharmony_ci case PIC_PCIE_LINK_LEGACY_IRQ(1): 1028c2ecf20Sopenharmony_ci case PIC_PCIE_LINK_LEGACY_IRQ(2): 1038c2ecf20Sopenharmony_ci case PIC_PCIE_LINK_LEGACY_IRQ(3): 1048c2ecf20Sopenharmony_ci return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci return -1; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic int xlp_irq_to_irt(int irq) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci uint64_t pcibase; 1128c2ecf20Sopenharmony_ci int devoff, irt; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci devoff = 0; 1158c2ecf20Sopenharmony_ci switch (irq) { 1168c2ecf20Sopenharmony_ci case PIC_UART_0_IRQ: 1178c2ecf20Sopenharmony_ci devoff = XLP_IO_UART0_OFFSET(0); 1188c2ecf20Sopenharmony_ci break; 1198c2ecf20Sopenharmony_ci case PIC_UART_1_IRQ: 1208c2ecf20Sopenharmony_ci devoff = XLP_IO_UART1_OFFSET(0); 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci case PIC_MMC_IRQ: 1238c2ecf20Sopenharmony_ci devoff = XLP_IO_MMC_OFFSET(0); 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci case PIC_I2C_0_IRQ: /* I2C will be fixed up */ 1268c2ecf20Sopenharmony_ci case PIC_I2C_1_IRQ: 1278c2ecf20Sopenharmony_ci case PIC_I2C_2_IRQ: 1288c2ecf20Sopenharmony_ci case PIC_I2C_3_IRQ: 1298c2ecf20Sopenharmony_ci if (cpu_is_xlpii()) 1308c2ecf20Sopenharmony_ci devoff = XLP2XX_IO_I2C_OFFSET(0); 1318c2ecf20Sopenharmony_ci else 1328c2ecf20Sopenharmony_ci devoff = XLP_IO_I2C0_OFFSET(0); 1338c2ecf20Sopenharmony_ci break; 1348c2ecf20Sopenharmony_ci case PIC_SATA_IRQ: 1358c2ecf20Sopenharmony_ci devoff = XLP_IO_SATA_OFFSET(0); 1368c2ecf20Sopenharmony_ci break; 1378c2ecf20Sopenharmony_ci case PIC_GPIO_IRQ: 1388c2ecf20Sopenharmony_ci devoff = XLP_IO_GPIO_OFFSET(0); 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci case PIC_NAND_IRQ: 1418c2ecf20Sopenharmony_ci devoff = XLP_IO_NAND_OFFSET(0); 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case PIC_SPI_IRQ: 1448c2ecf20Sopenharmony_ci devoff = XLP_IO_SPI_OFFSET(0); 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci default: 1478c2ecf20Sopenharmony_ci if (cpu_is_xlpii()) { 1488c2ecf20Sopenharmony_ci switch (irq) { 1498c2ecf20Sopenharmony_ci /* XLP2XX has three XHCI USB controller */ 1508c2ecf20Sopenharmony_ci case PIC_2XX_XHCI_0_IRQ: 1518c2ecf20Sopenharmony_ci devoff = XLP2XX_IO_USB_XHCI0_OFFSET(0); 1528c2ecf20Sopenharmony_ci break; 1538c2ecf20Sopenharmony_ci case PIC_2XX_XHCI_1_IRQ: 1548c2ecf20Sopenharmony_ci devoff = XLP2XX_IO_USB_XHCI1_OFFSET(0); 1558c2ecf20Sopenharmony_ci break; 1568c2ecf20Sopenharmony_ci case PIC_2XX_XHCI_2_IRQ: 1578c2ecf20Sopenharmony_ci devoff = XLP2XX_IO_USB_XHCI2_OFFSET(0); 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci } else { 1618c2ecf20Sopenharmony_ci switch (irq) { 1628c2ecf20Sopenharmony_ci case PIC_EHCI_0_IRQ: 1638c2ecf20Sopenharmony_ci devoff = XLP_IO_USB_EHCI0_OFFSET(0); 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case PIC_EHCI_1_IRQ: 1668c2ecf20Sopenharmony_ci devoff = XLP_IO_USB_EHCI1_OFFSET(0); 1678c2ecf20Sopenharmony_ci break; 1688c2ecf20Sopenharmony_ci case PIC_OHCI_0_IRQ: 1698c2ecf20Sopenharmony_ci devoff = XLP_IO_USB_OHCI0_OFFSET(0); 1708c2ecf20Sopenharmony_ci break; 1718c2ecf20Sopenharmony_ci case PIC_OHCI_1_IRQ: 1728c2ecf20Sopenharmony_ci devoff = XLP_IO_USB_OHCI1_OFFSET(0); 1738c2ecf20Sopenharmony_ci break; 1748c2ecf20Sopenharmony_ci case PIC_OHCI_2_IRQ: 1758c2ecf20Sopenharmony_ci devoff = XLP_IO_USB_OHCI2_OFFSET(0); 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci case PIC_OHCI_3_IRQ: 1788c2ecf20Sopenharmony_ci devoff = XLP_IO_USB_OHCI3_OFFSET(0); 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (devoff != 0) { 1858c2ecf20Sopenharmony_ci uint32_t val; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci pcibase = nlm_pcicfg_base(devoff); 1888c2ecf20Sopenharmony_ci val = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG); 1898c2ecf20Sopenharmony_ci if (val == 0xffffffff) { 1908c2ecf20Sopenharmony_ci irt = -1; 1918c2ecf20Sopenharmony_ci } else { 1928c2ecf20Sopenharmony_ci irt = val & 0xffff; 1938c2ecf20Sopenharmony_ci /* HW weirdness, I2C IRT entry has to be fixed up */ 1948c2ecf20Sopenharmony_ci switch (irq) { 1958c2ecf20Sopenharmony_ci case PIC_I2C_1_IRQ: 1968c2ecf20Sopenharmony_ci irt = irt + 1; break; 1978c2ecf20Sopenharmony_ci case PIC_I2C_2_IRQ: 1988c2ecf20Sopenharmony_ci irt = irt + 2; break; 1998c2ecf20Sopenharmony_ci case PIC_I2C_3_IRQ: 2008c2ecf20Sopenharmony_ci irt = irt + 3; break; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) && 2048c2ecf20Sopenharmony_ci irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) { 2058c2ecf20Sopenharmony_ci /* HW bug, PCI IRT entries are bad on early silicon, fix */ 2068c2ecf20Sopenharmony_ci irt = PIC_IRT_PCIE_LINK_INDEX(irq - 2078c2ecf20Sopenharmony_ci PIC_PCIE_LINK_LEGACY_IRQ_BASE); 2088c2ecf20Sopenharmony_ci } else { 2098c2ecf20Sopenharmony_ci irt = -1; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci return irt; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ciint nlm_irq_to_irt(int irq) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci /* return -2 for irqs without 1-1 mapping */ 2178c2ecf20Sopenharmony_ci if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3)) 2188c2ecf20Sopenharmony_ci return -2; 2198c2ecf20Sopenharmony_ci if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3)) 2208c2ecf20Sopenharmony_ci return -2; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (cpu_is_xlp9xx()) 2238c2ecf20Sopenharmony_ci return xlp9xx_irq_to_irt(irq); 2248c2ecf20Sopenharmony_ci else 2258c2ecf20Sopenharmony_ci return xlp_irq_to_irt(irq); 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic unsigned int nlm_xlp2_get_core_frequency(int node, int core) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom; 2318c2ecf20Sopenharmony_ci uint64_t num, sysbase, clockbase; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (cpu_is_xlp9xx()) { 2348c2ecf20Sopenharmony_ci clockbase = nlm_get_clock_regbase(node); 2358c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(clockbase, 2368c2ecf20Sopenharmony_ci SYS_9XX_CPU_PLL_CTRL0(core)); 2378c2ecf20Sopenharmony_ci ctrl_val1 = nlm_read_sys_reg(clockbase, 2388c2ecf20Sopenharmony_ci SYS_9XX_CPU_PLL_CTRL1(core)); 2398c2ecf20Sopenharmony_ci } else { 2408c2ecf20Sopenharmony_ci sysbase = nlm_get_node(node)->sysbase; 2418c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(sysbase, 2428c2ecf20Sopenharmony_ci SYS_CPU_PLL_CTRL0(core)); 2438c2ecf20Sopenharmony_ci ctrl_val1 = nlm_read_sys_reg(sysbase, 2448c2ecf20Sopenharmony_ci SYS_CPU_PLL_CTRL1(core)); 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* Find PLL post divider value */ 2488c2ecf20Sopenharmony_ci switch ((ctrl_val0 >> 24) & 0x7) { 2498c2ecf20Sopenharmony_ci case 1: 2508c2ecf20Sopenharmony_ci pll_post_div = 2; 2518c2ecf20Sopenharmony_ci break; 2528c2ecf20Sopenharmony_ci case 3: 2538c2ecf20Sopenharmony_ci pll_post_div = 4; 2548c2ecf20Sopenharmony_ci break; 2558c2ecf20Sopenharmony_ci case 7: 2568c2ecf20Sopenharmony_ci pll_post_div = 8; 2578c2ecf20Sopenharmony_ci break; 2588c2ecf20Sopenharmony_ci case 6: 2598c2ecf20Sopenharmony_ci pll_post_div = 16; 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci case 0: 2628c2ecf20Sopenharmony_ci default: 2638c2ecf20Sopenharmony_ci pll_post_div = 1; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f)); 2688c2ecf20Sopenharmony_ci denom = 3 * pll_post_div; 2698c2ecf20Sopenharmony_ci do_div(num, denom); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return (unsigned int)num; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic unsigned int nlm_xlp_get_core_frequency(int node, int core) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci unsigned int pll_divf, pll_divr, dfs_div, ext_div; 2778c2ecf20Sopenharmony_ci unsigned int rstval, dfsval, denom; 2788c2ecf20Sopenharmony_ci uint64_t num, sysbase; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci sysbase = nlm_get_node(node)->sysbase; 2818c2ecf20Sopenharmony_ci rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); 2828c2ecf20Sopenharmony_ci dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); 2838c2ecf20Sopenharmony_ci pll_divf = ((rstval >> 10) & 0x7f) + 1; 2848c2ecf20Sopenharmony_ci pll_divr = ((rstval >> 8) & 0x3) + 1; 2858c2ecf20Sopenharmony_ci ext_div = ((rstval >> 30) & 0x3) + 1; 2868c2ecf20Sopenharmony_ci dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci num = 800000000ULL * pll_divf; 2898c2ecf20Sopenharmony_ci denom = 3 * pll_divr * ext_div * dfs_div; 2908c2ecf20Sopenharmony_ci do_div(num, denom); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci return (unsigned int)num; 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ciunsigned int nlm_get_core_frequency(int node, int core) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci if (cpu_is_xlpii()) 2988c2ecf20Sopenharmony_ci return nlm_xlp2_get_core_frequency(node, core); 2998c2ecf20Sopenharmony_ci else 3008c2ecf20Sopenharmony_ci return nlm_xlp_get_core_frequency(node, core); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/* 3048c2ecf20Sopenharmony_ci * Calculate PIC frequency from PLL registers. 3058c2ecf20Sopenharmony_ci * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) / 3068c2ecf20Sopenharmony_ci * ((2^ctrl0[7:5]) * Table(ctrl0[26:24])) 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_cistatic unsigned int nlm_xlp2_get_pic_frequency(int node) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx; 3118c2ecf20Sopenharmony_ci u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div; 3128c2ecf20Sopenharmony_ci u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci sysbase = nlm_get_node(node)->sysbase; 3158c2ecf20Sopenharmony_ci clockbase = nlm_get_clock_regbase(node); 3168c2ecf20Sopenharmony_ci cpu_xlp9xx = cpu_is_xlp9xx(); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* Find ref_clk_base */ 3198c2ecf20Sopenharmony_ci if (cpu_xlp9xx) 3208c2ecf20Sopenharmony_ci ref_clk_select = (nlm_read_sys_reg(sysbase, 3218c2ecf20Sopenharmony_ci SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3; 3228c2ecf20Sopenharmony_ci else 3238c2ecf20Sopenharmony_ci ref_clk_select = (nlm_read_sys_reg(sysbase, 3248c2ecf20Sopenharmony_ci SYS_POWER_ON_RESET_CFG) >> 18) & 0x3; 3258c2ecf20Sopenharmony_ci switch (ref_clk_select) { 3268c2ecf20Sopenharmony_ci case 0: 3278c2ecf20Sopenharmony_ci ref_clk = 200000000ULL; 3288c2ecf20Sopenharmony_ci ref_div = 3; 3298c2ecf20Sopenharmony_ci break; 3308c2ecf20Sopenharmony_ci case 1: 3318c2ecf20Sopenharmony_ci ref_clk = 100000000ULL; 3328c2ecf20Sopenharmony_ci ref_div = 1; 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci case 2: 3358c2ecf20Sopenharmony_ci ref_clk = 125000000ULL; 3368c2ecf20Sopenharmony_ci ref_div = 1; 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci case 3: 3398c2ecf20Sopenharmony_ci ref_clk = 400000000ULL; 3408c2ecf20Sopenharmony_ci ref_div = 3; 3418c2ecf20Sopenharmony_ci break; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* Find the clock source PLL device for PIC */ 3458c2ecf20Sopenharmony_ci if (cpu_xlp9xx) { 3468c2ecf20Sopenharmony_ci reg_select = nlm_read_sys_reg(clockbase, 3478c2ecf20Sopenharmony_ci SYS_9XX_CLK_DEV_SEL_REG) & 0x3; 3488c2ecf20Sopenharmony_ci switch (reg_select) { 3498c2ecf20Sopenharmony_ci case 0: 3508c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(clockbase, 3518c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL0); 3528c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(clockbase, 3538c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL2); 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci case 1: 3568c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(clockbase, 3578c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL0_DEVX(0)); 3588c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(clockbase, 3598c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL2_DEVX(0)); 3608c2ecf20Sopenharmony_ci break; 3618c2ecf20Sopenharmony_ci case 2: 3628c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(clockbase, 3638c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL0_DEVX(1)); 3648c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(clockbase, 3658c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL2_DEVX(1)); 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci case 3: 3688c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(clockbase, 3698c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL0_DEVX(2)); 3708c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(clockbase, 3718c2ecf20Sopenharmony_ci SYS_9XX_PLL_CTRL2_DEVX(2)); 3728c2ecf20Sopenharmony_ci break; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci } else { 3758c2ecf20Sopenharmony_ci reg_select = (nlm_read_sys_reg(sysbase, 3768c2ecf20Sopenharmony_ci SYS_CLK_DEV_SEL_REG) >> 22) & 0x3; 3778c2ecf20Sopenharmony_ci switch (reg_select) { 3788c2ecf20Sopenharmony_ci case 0: 3798c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(sysbase, 3808c2ecf20Sopenharmony_ci SYS_PLL_CTRL0); 3818c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(sysbase, 3828c2ecf20Sopenharmony_ci SYS_PLL_CTRL2); 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci case 1: 3858c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(sysbase, 3868c2ecf20Sopenharmony_ci SYS_PLL_CTRL0_DEVX(0)); 3878c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(sysbase, 3888c2ecf20Sopenharmony_ci SYS_PLL_CTRL2_DEVX(0)); 3898c2ecf20Sopenharmony_ci break; 3908c2ecf20Sopenharmony_ci case 2: 3918c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(sysbase, 3928c2ecf20Sopenharmony_ci SYS_PLL_CTRL0_DEVX(1)); 3938c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(sysbase, 3948c2ecf20Sopenharmony_ci SYS_PLL_CTRL2_DEVX(1)); 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci case 3: 3978c2ecf20Sopenharmony_ci ctrl_val0 = nlm_read_sys_reg(sysbase, 3988c2ecf20Sopenharmony_ci SYS_PLL_CTRL0_DEVX(2)); 3998c2ecf20Sopenharmony_ci ctrl_val2 = nlm_read_sys_reg(sysbase, 4008c2ecf20Sopenharmony_ci SYS_PLL_CTRL2_DEVX(2)); 4018c2ecf20Sopenharmony_ci break; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci vco_post_div = (ctrl_val0 >> 5) & 0x7; 4068c2ecf20Sopenharmony_ci pll_post_div = (ctrl_val0 >> 24) & 0x7; 4078c2ecf20Sopenharmony_ci mdiv = ctrl_val2 & 0xff; 4088c2ecf20Sopenharmony_ci fdiv = (ctrl_val2 >> 8) & 0x1fff; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* Find PLL post divider value */ 4118c2ecf20Sopenharmony_ci switch (pll_post_div) { 4128c2ecf20Sopenharmony_ci case 1: 4138c2ecf20Sopenharmony_ci pll_post_div = 2; 4148c2ecf20Sopenharmony_ci break; 4158c2ecf20Sopenharmony_ci case 3: 4168c2ecf20Sopenharmony_ci pll_post_div = 4; 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci case 7: 4198c2ecf20Sopenharmony_ci pll_post_div = 8; 4208c2ecf20Sopenharmony_ci break; 4218c2ecf20Sopenharmony_ci case 6: 4228c2ecf20Sopenharmony_ci pll_post_div = 16; 4238c2ecf20Sopenharmony_ci break; 4248c2ecf20Sopenharmony_ci case 0: 4258c2ecf20Sopenharmony_ci default: 4268c2ecf20Sopenharmony_ci pll_post_div = 1; 4278c2ecf20Sopenharmony_ci break; 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci fdiv = fdiv/(1 << 13); 4318c2ecf20Sopenharmony_ci pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv; 4328c2ecf20Sopenharmony_ci pll_out_freq_den = (1 << vco_post_div) * pll_post_div * ref_div; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (pll_out_freq_den > 0) 4358c2ecf20Sopenharmony_ci do_div(pll_out_freq_num, pll_out_freq_den); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* PIC post divider, which happens after PLL */ 4388c2ecf20Sopenharmony_ci if (cpu_xlp9xx) 4398c2ecf20Sopenharmony_ci pic_div = nlm_read_sys_reg(clockbase, 4408c2ecf20Sopenharmony_ci SYS_9XX_CLK_DEV_DIV_REG) & 0x3; 4418c2ecf20Sopenharmony_ci else 4428c2ecf20Sopenharmony_ci pic_div = (nlm_read_sys_reg(sysbase, 4438c2ecf20Sopenharmony_ci SYS_CLK_DEV_DIV_REG) >> 22) & 0x3; 4448c2ecf20Sopenharmony_ci do_div(pll_out_freq_num, 1 << pic_div); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci return pll_out_freq_num; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ciunsigned int nlm_get_pic_frequency(int node) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci if (cpu_is_xlpii()) 4528c2ecf20Sopenharmony_ci return nlm_xlp2_get_pic_frequency(node); 4538c2ecf20Sopenharmony_ci else 4548c2ecf20Sopenharmony_ci return 133333333; 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ciunsigned int nlm_get_cpu_frequency(void) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci return nlm_get_core_frequency(0, 0); 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/* 4638c2ecf20Sopenharmony_ci * Fills upto 8 pairs of entries containing the DRAM map of a node 4648c2ecf20Sopenharmony_ci * if node < 0, get dram map for all nodes 4658c2ecf20Sopenharmony_ci */ 4668c2ecf20Sopenharmony_ciint nlm_get_dram_map(int node, uint64_t *dram_map, int nentries) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci uint64_t bridgebase, base, lim; 4698c2ecf20Sopenharmony_ci uint32_t val; 4708c2ecf20Sopenharmony_ci unsigned int barreg, limreg, xlatreg; 4718c2ecf20Sopenharmony_ci int i, n, rv; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* Look only at mapping on Node 0, we don't handle crazy configs */ 4748c2ecf20Sopenharmony_ci bridgebase = nlm_get_bridge_regbase(0); 4758c2ecf20Sopenharmony_ci rv = 0; 4768c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 4778c2ecf20Sopenharmony_ci if (rv + 1 >= nentries) 4788c2ecf20Sopenharmony_ci break; 4798c2ecf20Sopenharmony_ci if (cpu_is_xlp9xx()) { 4808c2ecf20Sopenharmony_ci barreg = BRIDGE_9XX_DRAM_BAR(i); 4818c2ecf20Sopenharmony_ci limreg = BRIDGE_9XX_DRAM_LIMIT(i); 4828c2ecf20Sopenharmony_ci xlatreg = BRIDGE_9XX_DRAM_NODE_TRANSLN(i); 4838c2ecf20Sopenharmony_ci } else { 4848c2ecf20Sopenharmony_ci barreg = BRIDGE_DRAM_BAR(i); 4858c2ecf20Sopenharmony_ci limreg = BRIDGE_DRAM_LIMIT(i); 4868c2ecf20Sopenharmony_ci xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i); 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci if (node >= 0) { 4898c2ecf20Sopenharmony_ci /* node specified, get node mapping of BAR */ 4908c2ecf20Sopenharmony_ci val = nlm_read_bridge_reg(bridgebase, xlatreg); 4918c2ecf20Sopenharmony_ci n = (val >> 1) & 0x3; 4928c2ecf20Sopenharmony_ci if (n != node) 4938c2ecf20Sopenharmony_ci continue; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci val = nlm_read_bridge_reg(bridgebase, barreg); 4968c2ecf20Sopenharmony_ci val = (val >> 12) & 0xfffff; 4978c2ecf20Sopenharmony_ci base = (uint64_t) val << 20; 4988c2ecf20Sopenharmony_ci val = nlm_read_bridge_reg(bridgebase, limreg); 4998c2ecf20Sopenharmony_ci val = (val >> 12) & 0xfffff; 5008c2ecf20Sopenharmony_ci if (val == 0) /* BAR not used */ 5018c2ecf20Sopenharmony_ci continue; 5028c2ecf20Sopenharmony_ci lim = ((uint64_t)val + 1) << 20; 5038c2ecf20Sopenharmony_ci dram_map[rv] = base; 5048c2ecf20Sopenharmony_ci dram_map[rv + 1] = lim; 5058c2ecf20Sopenharmony_ci rv += 2; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci return rv; 5088c2ecf20Sopenharmony_ci} 509