/*
 * Copyright 2007,2009-2014 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <command.h>
#include <pci.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/fsl_pci.h>
#include <asm/io.h>
#include <libfdt.h>
#include <fdt_support.h>
#include <netdev.h>
#include <fdtdec.h>
#include <errno.h>
#include <malloc.h>

DECLARE_GLOBAL_DATA_PTR;

static void *get_fdt_virt(void)
{
	return (void *)CONFIG_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;

	/*
	 * To be able to read the FDT we need to create a temporary TLB
	 * map for it.
	 */
	map_fdt_as(10);
	r = fdt_get_base_address(fdt, fdt_path_offset(fdt, "/soc"));
	disable_tlb(10);

	return r;
}

int board_early_init_f(void)
{
	return 0;
}

int checkboard(void)
{
	return 0;
}

static int pci_map_region(void *fdt, int pci_node, int range_id,
			  phys_size_t *ppaddr, pci_addr_t *pvaddr,
			  pci_size_t *psize, ulong *pmap_addr)
{
	uint64_t addr;
	uint64_t size;
	ulong map_addr;
	int r;

	r = fdt_read_range(fdt, pci_node, 0, NULL, &addr, &size);
	if (r)
		return r;

	if (ppaddr)
		*ppaddr = addr;
	if (psize)
		*psize = size;

	if (!pmap_addr)
		return 0;

	map_addr = *pmap_addr;

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

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

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

	if (pvaddr)
		*pvaddr = map_addr;

	return 0;
}

void pci_init_board(void)
{
	struct pci_controller *pci_hoses;
	void *fdt = get_fdt_virt();
	int pci_node = -1;
	int pci_num = 0;
	int pci_count = 0;
	ulong map_addr;

	puts("\n");

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

	/* Count and allocate PCI buses */
	pci_node = fdt_node_offset_by_prop_value(fdt, pci_node,
			"device_type", "pci", 4);
	while (pci_node != -FDT_ERR_NOTFOUND) {
		pci_node = fdt_node_offset_by_prop_value(fdt, pci_node,
				"device_type", "pci", 4);
		pci_count++;
	}

	if (pci_count) {
		pci_hoses = malloc(sizeof(struct pci_controller) * pci_count);
	} else {
		printf("PCI: disabled\n\n");
		return;
	}

	/* Spawn PCI buses based on device tree */
	pci_node = fdt_node_offset_by_prop_value(fdt, pci_node,
			"device_type", "pci", 4);
	while (pci_node != -FDT_ERR_NOTFOUND) {
		struct fsl_pci_info pci_info = { };
		const fdt32_t *reg;
		int r;

		reg = fdt_getprop(fdt, pci_node, "reg", NULL);
		pci_info.regs = fdt_translate_address(fdt, pci_node, reg);

		/* Map MMIO range */
		r = pci_map_region(fdt, pci_node, 0, &pci_info.mem_phys, NULL,
				   &pci_info.mem_size, &map_addr);
		if (r)
			break;

		/* Map PIO range */
		r = pci_map_region(fdt, pci_node, 1, &pci_info.io_phys, NULL,
				   &pci_info.io_size, &map_addr);
		if (r)
			break;

		/*
		 * The PCI framework finds virtual addresses for the buses
		 * through our address map, so tell it the physical addresses.
		 */
		pci_info.mem_bus = pci_info.mem_phys;
		pci_info.io_bus = pci_info.io_phys;

		/* Instantiate */
		pci_info.pci_num = pci_num + 1;

		fsl_setup_hose(&pci_hoses[pci_num], pci_info.regs);
		printf("PCI: base address %lx\n", pci_info.regs);

		fsl_pci_init_port(&pci_info, &pci_hoses[pci_num], pci_num);

		/* Jump to next PCI node */
		pci_node = fdt_node_offset_by_prop_value(fdt, pci_node,
				"device_type", "pci", 4);
		pci_num++;
	}

	puts("\n");
}

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))
		setenv_hex("qemu_kernel_addr", *prop);

	/* Give the user a variable for the host fdt */
	setenv_hex("fdt_addr_r", (ulong)fdt);

	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");
}

int board_eth_init(bd_t *bis)
{
	return pci_eth_init(bis);
}

#if defined(CONFIG_OF_BOARD_SETUP)
void ft_board_setup(void *blob, bd_t *bd)
{
	FT_FSL_PCI_SETUP;
}
#endif

void print_laws(void)
{
	/* We don't emulate LAWs yet */
}

phys_size_t fixed_sdram(void)
{
	return get_linear_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(CONFIG_SYS_CCSRBAR, CONFIG_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));
}

void init_laws(void)
{
	/* We don't emulate LAWs yet */
}

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;
}
