/*
 * Amlogic A113 PCI Express Root-Complex driver
 *
 * Copyright (C) 2017 Yue Wang <yue.wang@amlogic.com>
 *
 * Based on Linux kernel driver:
 * pcie-amlogic.c:
 *
 */
#include <common.h>
#include <pci.h>
#include <asm/arch/clock.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <linux/sizes.h>
#include <errno.h>
#include "pcie_amlogic.h"
#include <asm/arch-axg/pci.h>

static t_pl_region_regs *pcieA_pl_region_regs =
	(t_pl_region_regs *)(PCIE_A_PORT_LOGIC_BASE_ADDR);
static t_pl_region_regs *pcieB_pl_region_regs =
	(t_pl_region_regs *)(PCIE_B_PORT_LOGIC_BASE_ADDR);
static t_pcie_user_cfg *pcieA_user_cfg =
	(t_pcie_user_cfg *)(PCIE_A_USER_CFG_BASE_ADDR);
static t_pcie_user_cfg *pcieB_user_cfg =
	(t_pcie_user_cfg *)(PCIE_B_USER_CFG_BASE_ADDR);
static t_pcie_user_status *pcieA_user_status  =
	(t_pcie_user_status *)(PCIE_A_USER_STATUS_BASE_ADDR);
static t_pcie_user_status *pcieB_user_status  =
	(t_pcie_user_status *)(PCIE_B_USER_STATUS_BASE_ADDR);
static t_pcie_cap_regs *pcieA_pcie_cap_regs  =
	(t_pcie_cap_regs *)(PCIE_A_PCIE_CAP_BASE_ADDR);
static t_pcie_cap_regs *pcieB_pcie_cap_regs  =
	(t_pcie_cap_regs *)(PCIE_B_PCIE_CAP_BASE_ADDR);
static t_type1_hdr_regs *pcieA_type1_hdr_regs =
	(t_type1_hdr_regs *)(PCIE_A_HDR_BASE_ADDR);
static t_type1_hdr_regs *pcieB_type1_hdr_regs =
	(t_type1_hdr_regs *)(PCIE_B_HDR_BASE_ADDR);

static u8 dw_pcie_iatu_unroll_enabled(e_pcieDev pcie_dev)
{
	u32 val;
	u64 amlogic_dbi_addr;

	if (pcie_dev == PCIE_A)
		amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
	else
		amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;

	val = readl(amlogic_dbi_addr+PCIE_ATU_VIEWPORT);
	if (val == 0xffffffff)
		return 1;

	return 0;
}

static void dw_pcie_writel_unroll(e_pcieDev pcie_dev, u32 index, u32 reg,
				  u32 val)
{
	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
	u64 amlogic_dbi_addr;

	if (pcie_dev == PCIE_A)
		amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
	else
		amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;

	writel(val, amlogic_dbi_addr + offset + reg);
}

static void dw_pcie_prog_outbound_atu(e_pcieDev pcie_dev, int index,
		int type, u64 cpu_addr, u64 pci_addr, u32 size)
{
	u64 amlogic_dbi_addr;

	if (pcie_dev == PCIE_A)
		amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
	else
		amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;

	if (iatu_unroll_enabled) {
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_LOWER_BASE,
			lower_32_bits(cpu_addr));
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_UPPER_BASE,
			upper_32_bits(cpu_addr));
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_LIMIT,
			lower_32_bits(size - 1));
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_LOWER_TARGET,
			lower_32_bits(pci_addr));
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_UPPER_TARGET,
			upper_32_bits(pci_addr));
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_REGION_CTRL1,
			type);
		dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_REGION_CTRL2,
			PCIE_ATU_ENABLE);
	} else {
		writel(PCIE_ATU_REGION_OUTBOUND | index,
			amlogic_dbi_addr + PCIE_ATU_VIEWPORT);
		writel(lower_32_bits(cpu_addr),
			amlogic_dbi_addr + PCIE_ATU_LOWER_BASE);
		writel(upper_32_bits(cpu_addr),
			amlogic_dbi_addr + PCIE_ATU_UPPER_BASE);
		writel(lower_32_bits(cpu_addr + size - 1),
			amlogic_dbi_addr + PCIE_ATU_LIMIT);
		writel(lower_32_bits(pci_addr),
			amlogic_dbi_addr + PCIE_ATU_LOWER_TARGET);
		writel(upper_32_bits(pci_addr),
			amlogic_dbi_addr + PCIE_ATU_UPPER_TARGET);
		writel(type, amlogic_dbi_addr + PCIE_ATU_CR1);
		writel(PCIE_ATU_ENABLE, amlogic_dbi_addr + PCIE_ATU_CR2);
	}
}

/*
 * iATU region setup
 */
static int amlogic_pcie_regions_setup(e_pcieDev pcie_dev)
{
	u64 amlogic_dbi_addr;
	u32 high_2m_base_addr;
	u32 high_2m_limit;
	u64 target_base_addr;
	int type;

	if (pcie_dev == PCIE_A) {
		amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
		high_2m_base_addr = EP_A_BASE_ADDR + 0x200000;
		high_2m_limit     = high_2m_base_addr + 0x1fffff;
	} else {
		amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;
		high_2m_base_addr = EP_B_BASE_ADDR + 0x200000;
		high_2m_limit     = high_2m_base_addr + 0x1fffff;
	}

	/* CMD reg:I/O space, MEM space, and Bus Master Enable */
	/* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
	setbits_le32(amlogic_dbi_addr + PCI_CLASS_REVISION,
		     PCI_CLASS_BRIDGE_PCI << 16);

	iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pcie_dev);

	target_base_addr  = high_2m_base_addr & 0x3fffff;
	type = PCIE_ATU_TYPE_MEM;
	if (type == PCIE_ATU_TYPE_CFG0 || type == PCIE_ATU_TYPE_CFG1) {
		target_base_addr  =   (0 & 0xff) << 24 |
							  (0 & 0x1F) << 19 |
							  (0 & 0x7) << 16;
	} else if (type == PCIE_ATU_TYPE_MEM)
		target_base_addr &= (~0xfff);

	dw_pcie_prog_outbound_atu(pcie_dev, PCIE_ATU_REGION_INDEX1,
					  PCIE_ATU_TYPE_MEM, high_2m_base_addr,
					  target_base_addr, high_2m_limit);

	return 0;
}

static int amlogic_pcie_read_config
	(struct pci_controller *hose, pci_dev_t d, int where, u32 *val)
{
	int type;
	e_pcieDev pcie_dev = *(int *)hose->priv_data;
	u64 ep_type0_hdr_regs;
	u32 ep_cfg_base_addr;
	u32 ep_cfg_addr_limit;
	u64 target_base_addr;

	if (pcie_dev == PCIE_A) {
		ep_type0_hdr_regs  = EP_A_BASE_ADDR;
		ep_cfg_base_addr   = EP_A_BASE_ADDR;
		ep_cfg_addr_limit  = EP_A_BASE_ADDR + 0x1fffff;
	} else {
		ep_type0_hdr_regs  = EP_B_BASE_ADDR;
		ep_cfg_base_addr   = EP_B_BASE_ADDR;
		ep_cfg_addr_limit  = EP_B_BASE_ADDR + 0x1fffff;
	}

	target_base_addr  = ep_cfg_base_addr & 0x3fffff;
	type = TYPE_CFG0;

	if (type == TYPE_CFG0 || type == TYPE_CFG1) {
		target_base_addr = (0 & 0xff) << 24 |
							(0 & 0x1F) << 19 |
							(0 & 0x7) << 16;
	} else if (type == TYPE_MEM)
		target_base_addr &= (~0xfff);

	dw_pcie_prog_outbound_atu(pcie_dev, PCIE_ATU_REGION_INDEX0,
					type, ep_cfg_base_addr,
					target_base_addr, ep_cfg_addr_limit);

	*val = readl(ep_type0_hdr_regs + where);

	return 0;
}


static int amlogic_pcie_write_config(struct pci_controller *hose, pci_dev_t d,
			int where, u32 val)
{
	int type;
	e_pcieDev pcie_dev = *(int *)hose->priv_data;
	u64 ep_type0_hdr_regs;
	u32 ep_cfg_base_addr;
	u32 ep_cfg_addr_limit;
	u64 target_base_addr;

	if (pcie_dev == PCIE_A) {
		ep_type0_hdr_regs  = EP_A_BASE_ADDR;
		ep_cfg_base_addr   = EP_A_BASE_ADDR;
		ep_cfg_addr_limit  = EP_A_BASE_ADDR + 0x1fffff;
	} else {
		ep_type0_hdr_regs  = EP_B_BASE_ADDR;
		ep_cfg_base_addr   = EP_B_BASE_ADDR;
		ep_cfg_addr_limit  = EP_B_BASE_ADDR + 0x1fffff;
	}

	target_base_addr  = ep_cfg_base_addr & 0x3fffff;
	type = TYPE_CFG0;

	if (type == TYPE_CFG0 || type == TYPE_CFG1) {
		target_base_addr  = (0 & 0xff) << 24 |
							(0 & 0x1F) << 19 |
							(0 & 0x7) << 16;
	} else if (type == TYPE_MEM)
		target_base_addr &= (~0xfff);

	dw_pcie_prog_outbound_atu(pcie_dev, PCIE_ATU_REGION_INDEX0,
					type, ep_cfg_base_addr,
					target_base_addr, ep_cfg_addr_limit);

	writel(val, ep_type0_hdr_regs + where);
	return 0;
}

static void amlogic_pcie_init_PLL(e_pcieDev pcie_dev)
{
	if (pcie_dev == PCIE_A) {
		*PCIE_PHY_BASE = 0x1d;
		mdelay(1);
		*PCIE_PHY_BASE = 0x1c;
		mdelay(1);
		*P_RESET0_LEVEL &= ~((0x3<<6) | (0x3<<1));
		mdelay(1);
		*PCIE_CTRL_6 &= ~(0X3 << 3);
		*MIPI_CTRL &= ~((0x1 << 26) | (0x1 << 29));
		mdelay(1);

		*PCIE_CTRL_0 = 0x400106c8;
		*PCIE_CTRL_1 = 0x0084a2aa;
		*PCIE_CTRL_2 = 0xb75020be;
		*PCIE_CTRL_3 = 0x0a47488e;
		*PCIE_CTRL_4 = 0xc000004d;
		*PCIE_CTRL_5 = 0x00078000;
		*PCIE_CTRL_6 = 0x002323c6;
		mdelay(1);

		writel(readl(PCIE_CTRL_0) | 1<<29, PCIE_CTRL_0);
		mdelay(1);
		writel(readl(PCIE_CTRL_0) & ~(1<<29), PCIE_CTRL_0);

		*P_RESET0_LEVEL |=	  (0x3<<6);
		mdelay(1);

		*CLK81_HIGH |= (0x1 << 26);
	}

	mdelay(1);
	if (pcie_dev == PCIE_A)
		*CLK81_LOW |= (0x1 << 16);
	else
		*CLK81_LOW |= (0x1 << 17);
	mdelay(1);

	if (pcie_dev == PCIE_A)
		*P_RESET0_LEVEL |=	  (0x1 << 1);
	else
		*P_RESET0_LEVEL |=	  (0x1 << 2);
	mdelay(1);

	if (pcie_dev == PCIE_A)
		*MIPI_CTRL |= ((0x1 << 26) | (0x1 << 29));
	mdelay(1);

	if (pcie_dev == PCIE_A)
		*PCIE_CTRL_6 |= (0x1 << 4);
	else
		*PCIE_CTRL_6 |= (0x1 << 3);
	mdelay(1);
}

static int amlogic_pcie_init_dw(e_pcieDev pcie_dev)
{
	t_pl_region_regs  *pl_region_regs;
	t_type1_hdr_regs  *type1_hdr_regs;

	if (pcie_dev == PCIE_A) {
		pl_region_regs = pcieA_pl_region_regs;
		type1_hdr_regs = pcieA_type1_hdr_regs;
		pcieA_user_cfg->cfg0 |= (1<<7);
	} else {
		pl_region_regs = pcieB_pl_region_regs;
		type1_hdr_regs = pcieB_type1_hdr_regs;
		pcieB_user_cfg->cfg0 |= (1<<7);
	}

	pl_region_regs->port_link_ctrl_off_reg |= 1<<7;

	pl_region_regs->port_link_ctrl_off_reg &= ~(0x3f<<16);
	pl_region_regs->port_link_ctrl_off_reg |= 0x1<<16;

	pl_region_regs->gen2_ctrl_off_reg &= ~(0x1f<<8);
	pl_region_regs->gen2_ctrl_off_reg |= 0x1<<8;

	pl_region_regs->gen2_ctrl_off_reg |= (1<<17);

	type1_hdr_regs->base_addr0_reg = 0x0;
	type1_hdr_regs->base_addr1_reg = 0x0;

	return 0;
}

void amlogic_wait_linkup(e_pcieDev pcie_dev)
{
	t_pcie_user_status   *user_status;
	int   smlh_up = 0;
	int   rdlh_up = 0;
	int   ltssm_up = 0;
	int   speed_okay = 0;
	int   current_data_rate;
	int   cnt = 0;

	if (pcie_dev == PCIE_A)
		user_status = pcieA_user_status;
	else
		user_status = pcieB_user_status;

	while (smlh_up == 0 || rdlh_up == 0 ||
		ltssm_up == 0 || speed_okay == 0) {
		smlh_up = (user_status->status12 >> 6) & 0x1;
		rdlh_up = (user_status->status12 >> 16) & 0x1;
		ltssm_up = ((user_status->status12 >> 10)
			& 0x1f) == 0x11 ? 1 : 0;
		current_data_rate = (user_status->status17>> 7) & 0x1;

		if (current_data_rate == PCIE_GEN2 ||
			current_data_rate == PCIE_GEN1)
		speed_okay = 1;

		cnt++;

		if (cnt >= WAIT_LINKUP_TIMEOUT) {
			if (pcie_dev == PCIE_A)
				printf("Error:PCIE A Wait linkup timeout.\n");
			else
				printf("Error:PCIE B Wait linkup timeout.\n");
			return;
		}

		udelay(20);
	}

	if (pcie_dev == PCIE_A)
		printf("PCIE A linkup success\n");
	else
		printf("PCIE B linkup success\n");
}

void amlogic_set_max_payload(e_pcieDev pcie_dev, int size)
{
	int max_payload_size = 1;

	switch (size) {
	case 128:
		max_payload_size = 0;
		break;
	case 256:
		max_payload_size = 1;
		break;
	case 512:
		max_payload_size = 2;
		break;
	case 1024:
		max_payload_size = 3;
		break;
	case 2048:
		max_payload_size = 4;
		break;
	case 4096:
		max_payload_size = 5;
		break;
	}

	if (pcie_dev == PCIE_A) {
		pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<5);
		pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_payload_size<<5);
	} else {
		pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<5);
		pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_payload_size<<5);
	}
}

void amlogic_set_max_rd_req_size(e_pcieDev pcie_dev, int size)
{
	int max_rd_req_size = 1;

	switch (size) {
	case 128:
		max_rd_req_size = 0;
		break;
	case 256:
		max_rd_req_size = 1;
		break;
	case 512:
		max_rd_req_size = 2;
		break;
	case 1024:
		max_rd_req_size = 3;
		break;
	case 2048:
		max_rd_req_size = 4;
		break;
	case 4096:
		max_rd_req_size = 5;
		break;
	}

	if (pcie_dev == PCIE_A) {
		pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<12);
		pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_rd_req_size<<12);
	} else {
		pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<12);
		pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_rd_req_size<<12);
	}
}

void amlogic_configure_dsp_memory_map(e_pcieDev pcie_dev)
{
	t_type1_hdr_regs  *type1_hdr_regs;
	u32 io_base_addr;
	u32 io_limit;
	u32 mem_base_addr;
	u32 mem_limit;
	u32 pref_mem_base_addr;
	u32 pref_mem_limit;

	if (pcie_dev == PCIE_A) {
		type1_hdr_regs      = pcieA_type1_hdr_regs;
		io_base_addr        = PCIE_A_IO_BASE_ADDR;
		io_limit            = PCIE_A_IO_LIMIT;
		mem_base_addr       = PCIE_A_MEM_BASE_ADDR;
		mem_limit           = PCIE_A_MEM_LIMIT;
		pref_mem_base_addr  = PCIE_A_PREF_MEM_BASE_ADDR;
		pref_mem_limit      = PCIE_A_PREF_MEM_LIMIT;
	} else {
		type1_hdr_regs      = pcieB_type1_hdr_regs;
		io_base_addr        = PCIE_B_IO_BASE_ADDR;
		io_limit            = PCIE_B_IO_LIMIT;
		mem_base_addr       = PCIE_B_MEM_BASE_ADDR;
		mem_limit           = PCIE_B_MEM_LIMIT;
		pref_mem_base_addr  = PCIE_B_PREF_MEM_BASE_ADDR;
		pref_mem_limit      = PCIE_B_PREF_MEM_LIMIT;
	}
	type1_hdr_regs->io_limit_base_reg = (((io_base_addr >> 12) & 0xF) << 4)
									| (1 << 0) | (1 << 8) |
									(((io_limit >> 12) & 0XF) << 12);

	type1_hdr_regs->io_limit_base_upper_reg = ((io_base_addr >> 16) & 0xFFFF)
								<< 0 | ((io_limit >> 16) & 0XFFFF) << 16;

	type1_hdr_regs->pref_mem_limit_base_reg = 0x00010001;
	type1_hdr_regs->pref_base_upper_reg	= 0;
	type1_hdr_regs->pref_limit_upper_reg = 0;
	type1_hdr_regs->pref_mem_limit_base_reg =
		((pref_mem_base_addr >> 20) & 0xFFF) << 4 |
		((pref_mem_limit >> 20) & 0xFFF) << 20;

	type1_hdr_regs->mem_limit_base_reg =
		((mem_base_addr >> 20) & 0xFFF) << 4 |
		((mem_limit >> 20) & 0xFFF) << 20;
}

void amlogic_enable_memory_space(e_pcieDev pcie_dev)
{
	t_type1_hdr_regs  *type1_hdr_regs;

	if (pcie_dev == PCIE_A)
		type1_hdr_regs = pcieA_type1_hdr_regs;
	else
		type1_hdr_regs = pcieB_type1_hdr_regs;

	type1_hdr_regs->stus_cmd_reg = 7;
}

static int amlogic_pcie_link_up(e_pcieDev pcie_dev)
{
	amlogic_pcie_init_dw(pcie_dev);

	amlogic_set_max_payload(pcie_dev, 256);
	amlogic_set_max_rd_req_size(pcie_dev, 256);

	amlogic_pcie_regions_setup(pcie_dev);

	amlogic_configure_dsp_memory_map(pcie_dev);
	amlogic_enable_memory_space(pcie_dev);

	amlogic_pcie_init_reset_pin(pcie_dev);
	amlogic_wait_linkup(pcie_dev);

	return 0;
}

void amlogic_pcie_PLL_disable(void)
{
	amlogic_pcie_disable();

	*PCIE_PHY_BASE = 0x1d;

	mdelay(1);
	*P_RESET0_LEVEL &= ~((0x3<<6) | (0x3<<1));
	mdelay(1);

	*PCIE_CTRL_0 = 0x80000000;
	*PCIE_CTRL_1 = 0x0;
	*PCIE_CTRL_2 = 0x0;
	*PCIE_CTRL_3 = 0x0;
	*PCIE_CTRL_4 = 0x0;
	*PCIE_CTRL_5 = 0x0;
	*PCIE_CTRL_6 = 0x0;

	*CLK81_LOW &= ~(0x1 << 16);
	*CLK81_LOW &= ~(0x1 << 17);

	*MIPI_CTRL &= ~((0x1 << 26) | (0x1 << 29));
	*PCIE_CTRL_6 &= ~(0X3 << 3);
}

void amlogic_pcie_init(e_pcieDev pcie_dev)
{
	/* Static instance of the controller. */
	static struct pci_controller	pcc;
	struct pci_controller		*hose = &pcc;
	int ret;

	amlogic_pcie_init_PLL(pcie_dev);

	memset(&pcc, 0, sizeof(pcc));
	if (pcie_dev == PCIE_A) {
		/* PCI I/O space */
		pci_set_region(&hose->regions[0],
		       PCIE_A_IO_BASE_ADDR, PCIE_A_IO_BASE_ADDR,
		       0xff, PCI_REGION_IO);

		/* PCI memory space */
		pci_set_region(&hose->regions[1],
		       PCIE_A_MEM_BASE_ADDR, PCIE_A_MEM_BASE_ADDR,
		       0x6fffffff, PCI_REGION_MEM);

		/* System memory space */
		pci_set_region(&hose->regions[2],
		       EP_A_PREF_MEM_BASE_ADDR, EP_A_PREF_MEM_BASE_ADDR,
		       0x7fffff, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
	} else {
		/* PCI I/O space */
		pci_set_region(&hose->regions[0],
		       PCIE_B_IO_BASE_ADDR, PCIE_B_IO_BASE_ADDR,
		       0xff, PCI_REGION_IO);

		/* PCI memory space */
		pci_set_region(&hose->regions[1],
		       PCIE_B_MEM_BASE_ADDR, PCIE_B_MEM_BASE_ADDR,
		       0x6fffffff, PCI_REGION_MEM);

		/* System memory space */
		pci_set_region(&hose->regions[2],
		       EP_B_PREF_MEM_BASE_ADDR, EP_B_PREF_MEM_BASE_ADDR,
		       0x7fffff, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
	}

	hose->region_count = 3;
	pcie_type = pcie_dev;
	hose->priv_data = &pcie_type;

	pci_set_ops(hose,
		pci_hose_read_config_byte_via_dword,
		pci_hose_read_config_word_via_dword,
		amlogic_pcie_read_config,
		pci_hose_write_config_byte_via_dword,
		pci_hose_write_config_word_via_dword,
		amlogic_pcie_write_config);

	/* Start the controller. */
	ret = amlogic_pcie_link_up(pcie_dev);
	if (!ret) {
		pci_register_hose(hose);
		hose->last_busno = pci_hose_scan(hose);
	}
	if (pcie_dev == PCIE_B)
		amlogic_pcie_PLL_disable();
}

/* Probe function. */
void pci_init_board(void)
{
	amlogic_pcie_init(PCIE_A);
	amlogic_pcie_init(PCIE_B);
}
