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