// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2007,2009-2014 Freescale Semiconductor, Inc.
 * Copyright (C) 2021, Bin Meng <bmeng.cn@gmail.com>
 */

#include <common.h>
#include <command.h>
#include <cpu_func.h>
#include <dm.h>
#include <env.h>
#include <init.h>
#include <log.h>
#include <net.h>
#include <pci.h>
#include <time.h>
#include <dm/simple_bus.h>
#include <dm/uclass-internal.h>
#include <asm/global_data.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/fsl_pci.h>
#include <asm/io.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <netdev.h>
#include <fdtdec.h>
#include <errno.h>
#include <malloc.h>
#include <virtio_types.h>
#include <virtio.h>

DECLARE_GLOBAL_DATA_PTR;

/* Virtual address range for PCI region maps */
#define SYS_PCI_MAP_START	0x80000000
#define SYS_PCI_MAP_END		0xe0000000

static void *get_fdt_virt(void)
{
	if (gd->flags & GD_FLG_RELOC)
		return (void *)gd->fdt_blob;
	else
		return (void *)CFG_SYS_TMPVIRT;
}

static uint64_t get_fdt_phys(void)
{
	return (uint64_t)(uintptr_t)gd->fdt_blob;
}

static void map_fdt_as(int esel)
{
	u32 mas0, mas1, mas2, mas3, mas7;
	uint64_t fdt_phys = get_fdt_phys();
	unsigned long fdt_phys_tlb = fdt_phys & ~0xffffful;
	unsigned long fdt_virt_tlb = (ulong)get_fdt_virt() & ~0xffffful;

	mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(esel);
	mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_1M);
	mas2 = FSL_BOOKE_MAS2(fdt_virt_tlb, 0);
	mas3 = FSL_BOOKE_MAS3(fdt_phys_tlb, 0, MAS3_SW|MAS3_SR);
	mas7 = FSL_BOOKE_MAS7(fdt_phys_tlb);

	write_tlb(mas0, mas1, mas2, mas3, mas7);
}

uint64_t get_phys_ccsrbar_addr_early(void)
{
	void *fdt = get_fdt_virt();
	uint64_t r;
	int size, node;
	u32 naddr;
	const fdt32_t *prop;

	/*
	 * To be able to read the FDT we need to create a temporary TLB
	 * map for it.
	 */
	map_fdt_as(10);
	node = fdt_path_offset(fdt, "/soc");
	naddr = fdt_address_cells(fdt, node);
	prop = fdt_getprop(fdt, node, "ranges", &size);
	r = fdt_translate_address(fdt, node, prop + naddr);
	disable_tlb(10);

	return r;
}

int checkboard(void)
{
	return 0;
}

static int pci_map_region(phys_addr_t paddr, phys_size_t size, ulong *pmap_addr)
{
	ulong map_addr;

	if (!pmap_addr)
		return 0;

	map_addr = *pmap_addr;

	/* Align map_addr */
	map_addr += size - 1;
	map_addr &= ~(size - 1);

	if (map_addr + size >= SYS_PCI_MAP_END)
		return -1;

	/* Map virtual memory for range */
	assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
	*pmap_addr = map_addr + size;

	return 0;
}

static void platform_bus_map_region(ulong map_addr, phys_addr_t paddr,
				    phys_size_t size)
{
	/* Align map_addr */
	map_addr += size - 1;
	map_addr &= ~(size - 1);

	/* Map virtual memory for range */
	assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
}

int misc_init_r(void)
{
	struct udevice *dev;
	struct pci_region *io;
	struct pci_region *mem;
	struct pci_region *pre;
	ulong map_addr;
	int ret;

	/* Ensure PCI is probed */
	uclass_first_device(UCLASS_PCI, &dev);

	pci_get_regions(dev, &io, &mem, &pre);

	/* Start MMIO and PIO range maps above RAM */
	map_addr = SYS_PCI_MAP_START;

	/* Map MMIO range */
	ret = pci_map_region(mem->phys_start, mem->size, &map_addr);
	if (ret)
		return ret;

	/* Map PIO range */
	ret = pci_map_region(io->phys_start, io->size, &map_addr);
	if (ret)
		return ret;

	/*
	 * Make sure virtio bus is enumerated so that peripherals
	 * on the virtio bus can be discovered by their drivers.
	 */
	virtio_init();

	/*
	 * U-Boot is relocated to RAM already, let's delete the temporary FDT
	 * virtual-physical mapping that was used in the pre-relocation phase.
	 */
	disable_tlb(find_tlb_idx((void *)CFG_SYS_TMPVIRT, 1));

	/*
	 * Detect the presence of the platform bus node, and
	 * create a virtual memory mapping for it.
	 */
	for (ret = uclass_find_first_device(UCLASS_SIMPLE_BUS, &dev);
	     dev;
	     ret = uclass_find_next_device(&dev)) {
		if (device_is_compatible(dev, "qemu,platform")) {
			struct simple_bus_plat *plat = dev_get_uclass_plat(dev);

			platform_bus_map_region(CONFIG_PLATFORM_BUS_MAP_ADDR,
						plat->target, plat->size);
			break;
		}
	}

	return 0;
}

int last_stage_init(void)
{
	void *fdt = get_fdt_virt();
	int len = 0;
	const uint64_t *prop;
	int chosen;

	chosen = fdt_path_offset(fdt, "/chosen");
	if (chosen < 0) {
		printf("Couldn't find /chosen node in fdt\n");
		return -EIO;
	}

	/* -kernel boot */
	prop = fdt_getprop(fdt, chosen, "qemu,boot-kernel", &len);
	if (prop && (len >= 8))
		env_set_hex("qemu_kernel_addr", *prop);

	return 0;
}

static uint64_t get_linear_ram_size(void)
{
	void *fdt = get_fdt_virt();
	const void *prop;
	int memory;
	int len;

	memory = fdt_path_offset(fdt, "/memory");
	prop = fdt_getprop(fdt, memory, "reg", &len);

	if (prop && len >= 16)
		return *(uint64_t *)(prop+8);

	panic("Couldn't determine RAM size");
}

phys_size_t fsl_ddr_sdram_size(void)
{
	return get_linear_ram_size();
}

void init_tlbs(void)
{
	phys_size_t ram_size;

	/*
	 * Create a temporary AS=1 map for the fdt
	 *
	 * We use ESEL=0 here to overwrite the previous AS=0 map for ourselves
	 * which was only 4k big. This way we don't have to clear any other maps.
	 */
	map_fdt_as(0);

	/* Fetch RAM size from the fdt */
	ram_size = get_linear_ram_size();

	/* And remove our fdt map again */
	disable_tlb(0);

	/* Create an internal map of manually created TLB maps */
	init_used_tlb_cams();

	/* Create a dynamic AS=0 CCSRBAR mapping */
	assert(!tlb_map_range(CFG_SYS_CCSRBAR, CFG_SYS_CCSRBAR_PHYS,
			      1024 * 1024, TLB_MAP_IO));

	/* Create a RAM map that spans all accessible RAM */
	setup_ddr_tlbs(ram_size >> 20);

	/* Create a map for the TLB */
	assert(!tlb_map_range((ulong)get_fdt_virt(), get_fdt_phys(),
			      1024 * 1024, TLB_MAP_RAM));
}

static uint32_t get_cpu_freq(void)
{
	void *fdt = get_fdt_virt();
	int cpus_node = fdt_path_offset(fdt, "/cpus");
	int cpu_node = fdt_first_subnode(fdt, cpus_node);
	const char *prop = "clock-frequency";
	return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
}

void get_sys_info(sys_info_t *sys_info)
{
	int freq = get_cpu_freq();

	memset(sys_info, 0, sizeof(sys_info_t));
	sys_info->freq_systembus = freq;
	sys_info->freq_ddrbus = freq;
	sys_info->freq_processor[0] = freq;
}

int get_clocks(void)
{
	sys_info_t sys_info;

	get_sys_info(&sys_info);

	gd->cpu_clk = sys_info.freq_processor[0];
	gd->bus_clk = sys_info.freq_systembus;
	gd->mem_clk = sys_info.freq_ddrbus;
	gd->arch.lbc_clk = sys_info.freq_ddrbus;

	return 0;
}

unsigned long get_tbclk(void)
{
	void *fdt = get_fdt_virt();
	int cpus_node = fdt_path_offset(fdt, "/cpus");
	int cpu_node = fdt_first_subnode(fdt, cpus_node);
	const char *prop = "timebase-frequency";
	return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
}

/********************************************
 * get_bus_freq
 * return system bus freq in Hz
 *********************************************/
ulong get_bus_freq(ulong dummy)
{
	sys_info_t sys_info;
	get_sys_info(&sys_info);
	return sys_info.freq_systembus;
}

/*
 * Return the number of cores on this SOC.
 */
int cpu_numcores(void)
{
	/*
	 * The QEMU u-boot target only needs to drive the first core,
	 * spinning and device tree nodes get driven by QEMU itself
	 */
	return 1;
}

/*
 * Return a 32-bit mask indicating which cores are present on this SOC.
 */
u32 cpu_mask(void)
{
	return (1 << cpu_numcores()) - 1;
}

/**
 * Return the virtual address of FDT that was passed by QEMU
 *
 * Return: virtual address of FDT received from QEMU in r3 register
 */
void *board_fdt_blob_setup(int *err)
{
	*err = 0;
	return get_fdt_virt();
}

/* See CFG_SYS_NS16550_CLK in arch/powerpc/include/asm/config.h */
int get_serial_clock(void)
{
	return get_bus_freq(0);
}
