xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/spl_pcie_ep_boot.c (revision 7cee23c8a91d0cfdfd0d659dfcc65762b56661a8)
14c8e468bSKever Yang // SPDX-License-Identifier: GPL-2.0+
24c8e468bSKever Yang /*
34c8e468bSKever Yang  * Copyright (c) 2023 Rockchip Electronics Co., Ltd
44c8e468bSKever Yang  */
54c8e468bSKever Yang 
64c8e468bSKever Yang #include <common.h>
74c8e468bSKever Yang #include <spl.h>
84c8e468bSKever Yang #include <asm/io.h>
94c8e468bSKever Yang #include <asm/arch/cpu.h>
104c8e468bSKever Yang #include <asm/arch/hardware.h>
114c8e468bSKever Yang #include <asm/arch/ioc_rk3588.h>
124c8e468bSKever Yang #include <dt-bindings/clock/rk3588-cru.h>
134c8e468bSKever Yang #include <pci.h>
144c8e468bSKever Yang #include <asm/arch/rk_atags.h>
154c8e468bSKever Yang 
164c8e468bSKever Yang #ifndef CONFIG_SPL_LOAD_FIT_ADDRESS
174c8e468bSKever Yang #error "SPL_LOAD_FIT_ADDRESS not defined!"
184c8e468bSKever Yang #endif
194c8e468bSKever Yang 
204c8e468bSKever Yang #define printep(fmt, ...) \
214c8e468bSKever Yang 		do { \
224c8e468bSKever Yang 			printf("RKEP: %d - ", readl(CONFIG_ROCKCHIP_STIMER_BASE + 0x2c) / 24); \
232f33b98fSJon Lin 			printf(fmt, ##__VA_ARGS__); \
244c8e468bSKever Yang 		} while (0)
254c8e468bSKever Yang 
26*7cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
27*7cee23c8SJon Lin #define PCIE_SNPS_DBI_BASE	0xf5000000
28*7cee23c8SJon Lin #define PCIE_SNPS_APB_BASE	0xfe150000
29*7cee23c8SJon Lin #define PCIE_SNPS_IATU_BASE	0xa40300000
30*7cee23c8SJon Lin 
31*7cee23c8SJon Lin #define PCI_RESBAR		0x2e8
32*7cee23c8SJon Lin #elif CONFIG_ROCKCHIP_RK3568
33*7cee23c8SJon Lin #define PCIE_SNPS_DBI_BASE	0xf6000000
34*7cee23c8SJon Lin #define PCIE_SNPS_APB_BASE	0xfe280000
35*7cee23c8SJon Lin #define PCIE_SNPS_IATU_BASE	0x3c0b00000
36*7cee23c8SJon Lin 
37*7cee23c8SJon Lin #define PCI_RESBAR		0x2b8
38*7cee23c8SJon Lin #else
39*7cee23c8SJon Lin #error "this soc is not support pcie ep!"
40*7cee23c8SJon Lin #endif
41*7cee23c8SJon Lin 
424c8e468bSKever Yang #define RKEP_BAR0_ADDR		0x3c000000
434c8e468bSKever Yang #define RKEP_BAR2_ADDR		CONFIG_SPL_LOAD_FIT_ADDRESS
444c8e468bSKever Yang #define RKEP_BAR0_CMD_ADDR	(RKEP_BAR0_ADDR + 0x400)
454c8e468bSKever Yang #define RKEP_BOOT_MAGIC		0x524b4550 /* RKEP */
464c8e468bSKever Yang #define RKEP_CMD_LOADER_RUN	0x524b4501
474c8e468bSKever Yang 
482f33b98fSJon Lin #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
492f33b98fSJon Lin #define PCI_EXP_LNKCTL2		48	/* Link Control 2 */
502f33b98fSJon Lin #define PCI_EXP_LNKCTL2_TLS		0x000f
512f33b98fSJon Lin #define PCI_EXP_LNKCAP_SLS		0x0000000f
522f33b98fSJon Lin 
532f33b98fSJon Lin #define PCI_EXP_LNKCTL2_TLS_2_5GT	0x0001 /* Supported Speed 2.5GT/s */
542f33b98fSJon Lin #define PCI_EXP_LNKCTL2_TLS_5_0GT	0x0002 /* Supported Speed 5GT/s */
552f33b98fSJon Lin #define PCI_EXP_LNKCTL2_TLS_8_0GT	0x0003 /* Supported Speed 8GT/s */
562f33b98fSJon Lin 
572f33b98fSJon Lin /* Synopsys-specific PCIe configuration registers */
582f33b98fSJon Lin #define PCIE_PORT_LINK_CONTROL		0x710
592f33b98fSJon Lin #define PORT_LINK_MODE_MASK		(0x3f << 16)
602f33b98fSJon Lin #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
612f33b98fSJon Lin #define PORT_LINK_MODE_2_LANES		(0x3 << 16)
622f33b98fSJon Lin #define PORT_LINK_MODE_4_LANES		(0x7 << 16)
632f33b98fSJon Lin #define PORT_LINK_MODE_8_LANES		(0xf << 16)
642f33b98fSJon Lin 
652f33b98fSJon Lin #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C
662f33b98fSJon Lin #define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
672f33b98fSJon Lin #define PORT_LOGIC_LINK_WIDTH_MASK	(0x1f << 8)
682f33b98fSJon Lin #define PORT_LOGIC_LINK_WIDTH_1_LANES	(0x1 << 8)
692f33b98fSJon Lin #define PORT_LOGIC_LINK_WIDTH_2_LANES	(0x2 << 8)
702f33b98fSJon Lin #define PORT_LOGIC_LINK_WIDTH_4_LANES	(0x4 << 8)
712f33b98fSJon Lin #define PORT_LOGIC_LINK_WIDTH_8_LANES	(0x8 << 8)
722f33b98fSJon Lin 
732f33b98fSJon Lin #define PCIE_DIRECT_SPEED_CHANGE	(0x1 << 17)
742f33b98fSJon Lin 
754c8e468bSKever Yang #define LINK_WAIT_IATU			10000
764c8e468bSKever Yang #define PCIE_ATU_ENABLE			(0x1 << 31)
774c8e468bSKever Yang #define PCIE_ATU_BAR_MODE_ENABLE	(0x1 << 30 | 1 << 19)
784c8e468bSKever Yang #define PCIE_ATU_UNR_REGION_CTRL1	0x00
794c8e468bSKever Yang #define PCIE_ATU_UNR_REGION_CTRL2	0x04
804c8e468bSKever Yang #define PCIE_ATU_CPU_ADDR_LOW		0x14
814c8e468bSKever Yang #define PCIE_ATU_CPU_ADDR_HIGH		0x18
824c8e468bSKever Yang 
832f33b98fSJon Lin /* SRNS: Use Separate refclk(internal clock) instead of from RC */
844c8e468bSKever Yang // #define PCIE_ENABLE_SRNS_PLL_REFCLK
854c8e468bSKever Yang 
864c8e468bSKever Yang struct rkpcie_cmd {
874c8e468bSKever Yang 	u32 cmd;
884c8e468bSKever Yang 	u32 size;
894c8e468bSKever Yang 	u32 data[6];
904c8e468bSKever Yang };
914c8e468bSKever Yang 
926fa0195bSXiao Ya peng /* rkep device mode status definition */
934c8e468bSKever Yang #define RKEP_MODE_BOOTROM	1
944c8e468bSKever Yang #define RKEP_MODE_LOADER	2
956fa0195bSXiao Ya peng #define RKEP_MODE_KERNEL	3
966fa0195bSXiao Ya peng 
976fa0195bSXiao Ya peng /* Common status */
984c8e468bSKever Yang #define RKEP_SMODE_INIT		0
996fa0195bSXiao Ya peng #define RKEP_SMODE_LNKRDY	1
1006fa0195bSXiao Ya peng #define RKEP_SMODE_LNKUP	2
1016fa0195bSXiao Ya peng #define RKEP_SMODE_ERR		0xff
1026fa0195bSXiao Ya peng /* Firmware download status */
1036fa0195bSXiao Ya peng #define RKEP_SMODE_FWDLRDY	0x10
1046fa0195bSXiao Ya peng #define RKEP_SMODE_FWDLDONE	0x11
1056fa0195bSXiao Ya peng /* Application status*/
1066fa0195bSXiao Ya peng #define RKEP_SMODE_APPRDY	0x20
1074c8e468bSKever Yang 
1084c8e468bSKever Yang struct rkpcie_boot {
1094c8e468bSKever Yang 	/* magic: "RKEP" */
1104c8e468bSKever Yang 	u32 magic;
1114c8e468bSKever Yang 	u32 version;
1124c8e468bSKever Yang 	struct {
1134c8e468bSKever Yang 		u16 mode;
1144c8e468bSKever Yang 		u16 submode;
1154c8e468bSKever Yang 	} devmode;
1164c8e468bSKever Yang 	/* Size of ATAGS for cap */
1174c8e468bSKever Yang 	u32 cap_size;
1184c8e468bSKever Yang 	struct {
1194c8e468bSKever Yang 		u8 cmd;
1204c8e468bSKever Yang 		u8 status;
1214c8e468bSKever Yang 		/* Error code for current CMD */
1224c8e468bSKever Yang 		u16 opcode;
1234c8e468bSKever Yang 	} cmd_status;
1244c8e468bSKever Yang 	u32 reserved[2];
1254c8e468bSKever Yang 	/* RK ATAGS, for mem and other info */
1264c8e468bSKever Yang 	struct tag cap;
1274c8e468bSKever Yang 	/* offset 0x400 */
1284c8e468bSKever Yang 	struct rkpcie_cmd cmd;
1294c8e468bSKever Yang };
1304c8e468bSKever Yang 
1314c8e468bSKever Yang static void pcie_inbound_config(void)
1324c8e468bSKever Yang {
1334c8e468bSKever Yang 	u64 base = PCIE_SNPS_IATU_BASE + 0x100;
1344c8e468bSKever Yang 	u32 val;
1354c8e468bSKever Yang 	char i;
1364c8e468bSKever Yang 
1374c8e468bSKever Yang 	/* BAR0: RKEP_BAR0_ADDR */
1384c8e468bSKever Yang 	writel(RKEP_BAR0_ADDR, base + PCIE_ATU_CPU_ADDR_LOW);
1394c8e468bSKever Yang 	writel(0, base + PCIE_ATU_CPU_ADDR_HIGH);
1404c8e468bSKever Yang 	writel(0, base + PCIE_ATU_UNR_REGION_CTRL1);
1414c8e468bSKever Yang 	/* PCIE_ATU_UNR_REGION_CTRL2 */
1424c8e468bSKever Yang 	writel(PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE | (0 << 8),
1434c8e468bSKever Yang 	       base + PCIE_ATU_UNR_REGION_CTRL2);
1444c8e468bSKever Yang 	for (i = 0; i < 5; i++) {
1454c8e468bSKever Yang 		val = readl(base + PCIE_ATU_UNR_REGION_CTRL2);
1464c8e468bSKever Yang 		if (val & PCIE_ATU_ENABLE)
1474c8e468bSKever Yang 			break;
1484c8e468bSKever Yang 		udelay(LINK_WAIT_IATU);
1494c8e468bSKever Yang 	}
1504c8e468bSKever Yang 	printep("BAR0: 0x%x\n", RKEP_BAR0_ADDR);
1514c8e468bSKever Yang 
1524c8e468bSKever Yang 	/* BAR2: RKEP_BAR2_ADDR */
1534c8e468bSKever Yang 	writel(RKEP_BAR2_ADDR, base + PCIE_ATU_CPU_ADDR_LOW + 0x200);
1544c8e468bSKever Yang 	writel(0, base + PCIE_ATU_CPU_ADDR_HIGH + 0x200);
1554c8e468bSKever Yang 	writel(0, base + PCIE_ATU_UNR_REGION_CTRL1 + 0x200);
1564c8e468bSKever Yang 	writel(PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE | (2 << 8),
1574c8e468bSKever Yang 	       base + PCIE_ATU_UNR_REGION_CTRL2 + 0x200);
1584c8e468bSKever Yang 	for (i = 0; i < 5; i++) {
1594c8e468bSKever Yang 		val = readl(base + PCIE_ATU_UNR_REGION_CTRL2 + 0x200);
1604c8e468bSKever Yang 		if (val & PCIE_ATU_ENABLE)
1614c8e468bSKever Yang 			break;
1624c8e468bSKever Yang 		udelay(LINK_WAIT_IATU);
1634c8e468bSKever Yang 	}
1644c8e468bSKever Yang 	printep("BAR2: 0x%x%x\n", 0, RKEP_BAR2_ADDR);
1654c8e468bSKever Yang 
1664c8e468bSKever Yang 	/* BAR4 is wired reg, no need iATU */
1674c8e468bSKever Yang }
1684c8e468bSKever Yang 
1694c8e468bSKever Yang static int rockchip_pcie_ep_set_bar_flag(void *dbi_base, u32 barno, int flags)
1704c8e468bSKever Yang {
1714c8e468bSKever Yang 	u32 reg;
1724c8e468bSKever Yang 
1734c8e468bSKever Yang 	reg = PCI_BASE_ADDRESS_0 + (4 * barno);
1744c8e468bSKever Yang 
1754c8e468bSKever Yang 	/* Disabled the upper 32bits BAR to make a 64bits bar pair */
1764c8e468bSKever Yang 	if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
1774c8e468bSKever Yang 		writel(0, dbi_base + reg + 0x100000 + 4);
1784c8e468bSKever Yang 
1794c8e468bSKever Yang 	writel(flags, dbi_base + reg);
1804c8e468bSKever Yang 	if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
1814c8e468bSKever Yang 		writel(0, dbi_base + reg + 4);
1824c8e468bSKever Yang 
1834c8e468bSKever Yang 	return 0;
1844c8e468bSKever Yang }
1854c8e468bSKever Yang 
1864c8e468bSKever Yang static void pcie_bar_init(void *dbi_base)
1874c8e468bSKever Yang {
1884c8e468bSKever Yang 	void *resbar_base;
1894c8e468bSKever Yang 
1904c8e468bSKever Yang 	writel(0, dbi_base + 0x10);
1914c8e468bSKever Yang 	writel(0, dbi_base + 0x14);
1924c8e468bSKever Yang 	writel(0, dbi_base + 0x18);
1934c8e468bSKever Yang 	writel(0, dbi_base + 0x1c);
1944c8e468bSKever Yang 	writel(0, dbi_base + 0x20);
1954c8e468bSKever Yang 	writel(0, dbi_base + 0x24);
1964c8e468bSKever Yang 
1974c8e468bSKever Yang 	/* Resize BAR0 to support 4M 32bits */
198*7cee23c8SJon Lin 	resbar_base = dbi_base + PCI_RESBAR;
1994c8e468bSKever Yang 	writel(0xfffff0, resbar_base + 0x4);
2004c8e468bSKever Yang 	writel(0x2c0, resbar_base + 0x8);
2014c8e468bSKever Yang 	/* BAR2: 64M 64bits */
2024c8e468bSKever Yang 	writel(0xfffff0, resbar_base + 0x14);
2034c8e468bSKever Yang 	writel(0x6c0, resbar_base + 0x18);
2044c8e468bSKever Yang 	/* BAR4: Fixed for EP wired register, 1M 32bits */
2054c8e468bSKever Yang 	writel(0xfffff0, resbar_base + 0x24);
2064c8e468bSKever Yang 	writel(0xc0, resbar_base + 0x28);
2074c8e468bSKever Yang 	/* Set flags */
2084c8e468bSKever Yang 	rockchip_pcie_ep_set_bar_flag(dbi_base, 0, PCI_BASE_ADDRESS_MEM_TYPE_32);
2092f33b98fSJon Lin 	rockchip_pcie_ep_set_bar_flag(dbi_base, 2,
2102f33b98fSJon Lin 				      PCI_BASE_ADDRESS_MEM_PREFETCH | PCI_BASE_ADDRESS_MEM_TYPE_64);
2114c8e468bSKever Yang 	rockchip_pcie_ep_set_bar_flag(dbi_base, 4, PCI_BASE_ADDRESS_MEM_TYPE_32);
2124c8e468bSKever Yang 
2134c8e468bSKever Yang 	/* Close bar1 bar3 bar5 */
2144c8e468bSKever Yang 	writel(0x0, dbi_base + 0x100000 + 0x14);
2154c8e468bSKever Yang 	//writel(0x0, dbi_base + 0x100000 + 0x18);
2164c8e468bSKever Yang 	writel(0x0, dbi_base + 0x100000 + 0x1c);
2174c8e468bSKever Yang 	//writel(0x0, dbi_base + 0x100000 + 0x20);
2184c8e468bSKever Yang 	writel(0x0, dbi_base + 0x100000 + 0x24);
2194c8e468bSKever Yang 	/* Close ROM BAR */
2204c8e468bSKever Yang 	writel(0x0, dbi_base + 0x100000 + 0x30);
2214c8e468bSKever Yang }
2224c8e468bSKever Yang 
2234c8e468bSKever Yang static void pcie_bar0_header_init(void)
2244c8e468bSKever Yang {
2254c8e468bSKever Yang 	struct rkpcie_boot *bh = (struct rkpcie_boot *)RKEP_BAR0_ADDR;
2264c8e468bSKever Yang 
2274c8e468bSKever Yang 	bh->magic = RKEP_BOOT_MAGIC;
2284c8e468bSKever Yang 	bh->version = 0x100;
2294c8e468bSKever Yang 	bh->devmode.mode = RKEP_MODE_LOADER;
2304c8e468bSKever Yang 	bh->devmode.submode = RKEP_SMODE_INIT;
2314c8e468bSKever Yang 	bh->cap_size = 0;
2324c8e468bSKever Yang 
2334c8e468bSKever Yang 	memset((char *)RKEP_BAR0_CMD_ADDR, 0, sizeof(struct rkpcie_cmd));
2344c8e468bSKever Yang }
2354c8e468bSKever Yang 
2362f33b98fSJon Lin static void pcie_link_set_max_speed(void *dbi_base, u32 link_gen)
2372f33b98fSJon Lin {
2382f33b98fSJon Lin 	u32 cap, ctrl2, link_speed;
2392f33b98fSJon Lin 	u8 offset = 0x70;
2402f33b98fSJon Lin 
2412f33b98fSJon Lin 	cap = readl(dbi_base + offset + PCI_EXP_LNKCAP);
2422f33b98fSJon Lin 	ctrl2 = readl(dbi_base + offset + PCI_EXP_LNKCTL2);
2432f33b98fSJon Lin 	ctrl2 &= ~PCI_EXP_LNKCTL2_TLS;
2442f33b98fSJon Lin 
2452f33b98fSJon Lin 	link_speed = link_gen;
2462f33b98fSJon Lin 
2472f33b98fSJon Lin 	cap &= ~((u32)PCI_EXP_LNKCAP_SLS);
2482f33b98fSJon Lin 	writel(ctrl2 | link_speed, dbi_base + offset + PCI_EXP_LNKCTL2);
2492f33b98fSJon Lin 	writel(cap | link_speed, dbi_base + offset + PCI_EXP_LNKCAP);
2502f33b98fSJon Lin }
2512f33b98fSJon Lin 
2522f33b98fSJon Lin static void pcie_link_set_lanes(void *dbi_base, u32 lanes)
2532f33b98fSJon Lin {
2542f33b98fSJon Lin 	u32 val;
2552f33b98fSJon Lin 
2562f33b98fSJon Lin 	/* Set the number of lanes */
2572f33b98fSJon Lin 	val = readl(dbi_base + PCIE_PORT_LINK_CONTROL);
2582f33b98fSJon Lin 	val &= ~PORT_LINK_MODE_MASK;
2592f33b98fSJon Lin 	switch (lanes) {
2602f33b98fSJon Lin 	case 1:
2612f33b98fSJon Lin 		val |= PORT_LINK_MODE_1_LANES;
2622f33b98fSJon Lin 		break;
2632f33b98fSJon Lin 	case 2:
2642f33b98fSJon Lin 		val |= PORT_LINK_MODE_2_LANES;
2652f33b98fSJon Lin 		break;
2662f33b98fSJon Lin 	case 4:
2672f33b98fSJon Lin 		val |= PORT_LINK_MODE_4_LANES;
2682f33b98fSJon Lin 		break;
2692f33b98fSJon Lin 	default:
270*7cee23c8SJon Lin 		printf("RKEP: num-lanes %u: invalid value\n", lanes);
2712f33b98fSJon Lin 		return;
2722f33b98fSJon Lin 	}
2732f33b98fSJon Lin 	writel(val, dbi_base + PCIE_PORT_LINK_CONTROL);
2742f33b98fSJon Lin 
2752f33b98fSJon Lin 	/* Set link width speed control register */
2762f33b98fSJon Lin 	val = readl(dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
2772f33b98fSJon Lin 	val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
2782f33b98fSJon Lin 	switch (lanes) {
2792f33b98fSJon Lin 	case 1:
2802f33b98fSJon Lin 		val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
2812f33b98fSJon Lin 		break;
2822f33b98fSJon Lin 	case 2:
2832f33b98fSJon Lin 		val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
2842f33b98fSJon Lin 		break;
2852f33b98fSJon Lin 	case 4:
2862f33b98fSJon Lin 		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
2872f33b98fSJon Lin 		break;
2882f33b98fSJon Lin 	}
2892f33b98fSJon Lin 
2902f33b98fSJon Lin 	val |= PCIE_DIRECT_SPEED_CHANGE;
2912f33b98fSJon Lin 
2922f33b98fSJon Lin 	writel(val, dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
2932f33b98fSJon Lin }
2942f33b98fSJon Lin 
2956fa0195bSXiao Ya peng static void pcie_devmode_update(int mode, int submode)
2966fa0195bSXiao Ya peng {
2976fa0195bSXiao Ya peng 	struct rkpcie_boot *bh = (struct rkpcie_boot *)RKEP_BAR0_ADDR;
2986fa0195bSXiao Ya peng 
2996fa0195bSXiao Ya peng 	bh->devmode.mode = mode;
3006fa0195bSXiao Ya peng 	bh->devmode.submode = submode;
30126d59203SXiao Ya peng 	flush_dcache_range(RKEP_BAR0_ADDR, RKEP_BAR0_ADDR + 64);
3026fa0195bSXiao Ya peng }
3036fa0195bSXiao Ya peng 
3044c8e468bSKever Yang #ifdef CONFIG_SPL_RAM_DEVICE
3054c8e468bSKever Yang static void pcie_wait_for_fw(void)
3064c8e468bSKever Yang {
3074c8e468bSKever Yang 	struct rkpcie_cmd *cmd = (struct rkpcie_cmd *)(RKEP_BAR0_CMD_ADDR);
3084c8e468bSKever Yang 	int val;
3094c8e468bSKever Yang 	int i = 0;
3104c8e468bSKever Yang 
3114c8e468bSKever Yang 	printep("Link ready! Waiting RC to download Firmware:\n");
3124c8e468bSKever Yang 	printep("Download uboot.img  to BAR2+0\n");
3134c8e468bSKever Yang 	printep("Download boot.img   to BAR2+0x400000\n");
3144c8e468bSKever Yang 	printep("Send CMD_LOADER_RUN to BAR0+0x400\n");
3154c8e468bSKever Yang 	while (1) {
3164c8e468bSKever Yang 		invalidate_dcache_range(RKEP_BAR0_CMD_ADDR,
3174c8e468bSKever Yang 					RKEP_BAR0_CMD_ADDR + 32);
3184c8e468bSKever Yang 		val = readl(&cmd->cmd);
3194c8e468bSKever Yang 		if (val == RKEP_CMD_LOADER_RUN)
3204c8e468bSKever Yang 			break;
3214c8e468bSKever Yang 		i++;
3224c8e468bSKever Yang 		if (!(i % 10))
3234c8e468bSKever Yang 			printep("Waiting for FW, CMD: %x\n", val);
3242f33b98fSJon Lin 		mdelay(100);
3254c8e468bSKever Yang 	}
3264c8e468bSKever Yang 	/* Invalidate Cache for firmware area: BAR2, 64MB */
3274c8e468bSKever Yang 	invalidate_dcache_range(RKEP_BAR2_ADDR, RKEP_BAR2_ADDR + 0x4000000);
3284c8e468bSKever Yang 	printep("Firmware Download complete!\n");
3294c8e468bSKever Yang }
3304c8e468bSKever Yang 
3314c8e468bSKever Yang static void pcie_update_atags(void)
3324c8e468bSKever Yang {
3334c8e468bSKever Yang 	struct tag_ram_partition t_ram_part;
3344c8e468bSKever Yang 
3354c8e468bSKever Yang 	if (!atags_is_available()) {
336*7cee23c8SJon Lin 		printf("RKEP: No ATAGS data found, create new!\n");
3374c8e468bSKever Yang 		atags_destroy();
3384c8e468bSKever Yang 	}
3394c8e468bSKever Yang 
3404c8e468bSKever Yang 	/* ram partition */
3414c8e468bSKever Yang 	memset(&t_ram_part, 0, sizeof(t_ram_part));
3424c8e468bSKever Yang 	t_ram_part.version = 0;
3434c8e468bSKever Yang 	t_ram_part.count = 1;
3444c8e468bSKever Yang 	strcpy(t_ram_part.part[0].name, "boot");
3454c8e468bSKever Yang 	t_ram_part.part[0].start = RKEP_BAR2_ADDR + 0x400000;	/* 4M offset */
3464c8e468bSKever Yang 	t_ram_part.part[0].size  = 0x3c00000;	/* 60M size */
3474c8e468bSKever Yang 	atags_set_tag(ATAG_RAM_PARTITION, &t_ram_part);
3484c8e468bSKever Yang }
3494c8e468bSKever Yang 
3504c8e468bSKever Yang void rockchip_pcie_ep_get_firmware(void)
3514c8e468bSKever Yang {
3526fa0195bSXiao Ya peng 	pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_FWDLRDY);
3534c8e468bSKever Yang 	pcie_wait_for_fw();
3544c8e468bSKever Yang 	pcie_update_atags();
3556fa0195bSXiao Ya peng 	pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_FWDLDONE);
3564c8e468bSKever Yang }
3574c8e468bSKever Yang #endif
3584c8e468bSKever Yang 
359*7cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
360*7cee23c8SJon Lin #define BUS_IOC_GPIO3D_IOMUX_SEL_H	0xfd5f807c
361*7cee23c8SJon Lin #define GPIO3_BASE			0xfec40000
362*7cee23c8SJon Lin #define GPIO3_SWPORT_DR_H		(GPIO3_BASE + 0x4)
363*7cee23c8SJon Lin #define GPIO3_SWPORT_DDR_H		(GPIO3_BASE + 0xc)
364*7cee23c8SJon Lin 
365*7cee23c8SJon Lin static void pcie_board_init(void)
366*7cee23c8SJon Lin {
367*7cee23c8SJon Lin 	/* Enable AU5426 buffer chip on EVB4v10 */
368*7cee23c8SJon Lin 	/* Set GPIO3D4 to gpio output HIGH mode PCIE20_CLK_PWREN */
369*7cee23c8SJon Lin 	writel(0xf << 16, BUS_IOC_GPIO3D_IOMUX_SEL_H);
370*7cee23c8SJon Lin 	writel(0x10001000, GPIO3_SWPORT_DDR_H);
371*7cee23c8SJon Lin 	writel(0x10001000, GPIO3_SWPORT_DR_H);
372*7cee23c8SJon Lin 	udelay(100);
373*7cee23c8SJon Lin }
374*7cee23c8SJon Lin 
375*7cee23c8SJon Lin #define PHY_MODE_PCIE_AGGREGATION 4	/* PCIe3x4 */
376*7cee23c8SJon Lin #define PHY_MODE_PCIE_NANBNB	0	/* P1:PCIe3x2  +  P0:PCIe3x2 */
377*7cee23c8SJon Lin #define PHY_MODE_PCIE_NANBBI	1	/* P1:PCIe3x2  +  P0:PCIe3x1*2 */
378*7cee23c8SJon Lin #define PHY_MODE_PCIE_NABINB	2	/* P1:PCIe3x1*2 + P0:PCIe3x2 */
379*7cee23c8SJon Lin #define PHY_MODE_PCIE_NABIBI	3	/* P1:PCIe3x1*2 + P0:PCIe3x1*2 */
380*7cee23c8SJon Lin 
381*7cee23c8SJon Lin #define CRU_BASE_ADDR			0xfd7c0000
382*7cee23c8SJon Lin #define CRU_SOFTRST_CON32		(CRU_BASE_ADDR + 0x0a80)
383*7cee23c8SJon Lin #define CRU_SOFTRST_CON33		(CRU_BASE_ADDR + 0x0a84)
384*7cee23c8SJon Lin #define CRU_SOFTRST_CON34		(CRU_BASE_ADDR + 0x0a88)
385*7cee23c8SJon Lin #define CRU_GATE_CON32			(CRU_BASE_ADDR + 0x0880)
386*7cee23c8SJon Lin #define CRU_GATE_CON33			(CRU_BASE_ADDR + 0x0884)
387*7cee23c8SJon Lin #define CRU_GATE_CON34			(CRU_BASE_ADDR + 0x0888)
388*7cee23c8SJon Lin #define CRU_GATE_CON38			(CRU_BASE_ADDR + 0x0898)
389*7cee23c8SJon Lin #define CRU_GATE_CON39			(CRU_BASE_ADDR + 0x089c)
390*7cee23c8SJon Lin #define PHPTOPCRU_BASE_ADDR		0xfd7c8000
391*7cee23c8SJon Lin #define PHPTOPCRU_SOFTRST_CON00		(PHPTOPCRU_BASE_ADDR + 0x0a00)
392*7cee23c8SJon Lin #define PHPTOPCRU_GATE_CON00		(PHPTOPCRU_BASE_ADDR + 0x0800)
393*7cee23c8SJon Lin #define PCIE3PHY_GRF_BASE		0xfd5b8000
394*7cee23c8SJon Lin #define RK3588_PCIE3PHY_GRF_CMN_CON0	(PCIE3PHY_GRF_BASE + 0x0000)
395*7cee23c8SJon Lin #define PCIE3PHY_GRF_PHY0_CON6		(PCIE3PHY_GRF_BASE + 0x0118)
396*7cee23c8SJon Lin #define PCIE3PHY_GRF_PHY1_CON6		(PCIE3PHY_GRF_BASE + 0x0218)
397*7cee23c8SJon Lin #define PCIE3PHY_GRF_PHY0_LN0_CON1	(PCIE3PHY_GRF_BASE + 0x1004)
398*7cee23c8SJon Lin #define PCIE3PHY_GRF_PHY0_LN1_CON1	(PCIE3PHY_GRF_BASE + 0x1104)
399*7cee23c8SJon Lin #define PCIE3PHY_GRF_PHY1_LN0_CON1	(PCIE3PHY_GRF_BASE + 0x2004)
400*7cee23c8SJon Lin #define PCIE3PHY_GRF_PHY1_LN1_CON1	(PCIE3PHY_GRF_BASE + 0x2104)
401*7cee23c8SJon Lin #define FIREWALL_PCIE_MASTER_SEC	0xfe0300f0
402*7cee23c8SJon Lin #define FIREWALL_PCIE_ACCESS		0xfe586040
403*7cee23c8SJon Lin #define CRU_PHYREF_ALT_GATE_CON		(CRU_BASE_ADDR + 0x0c38)
404*7cee23c8SJon Lin #define PMU_PWR_GATE_SFTCON1		0xfd8d8150
405*7cee23c8SJon Lin static void pcie_cru_init(void)
406*7cee23c8SJon Lin {
407*7cee23c8SJon Lin 	u32 phy0_mplla, phy1_mplla, t0 = 0, t1 = 0;
408*7cee23c8SJon Lin 	u32 i, timeout = 500;
409*7cee23c8SJon Lin 
410*7cee23c8SJon Lin 	/* Enable power domain: PD_PCIE & PD_PHP */
411*7cee23c8SJon Lin 	writel(0x1 << 23 | 0x1 << 21, PMU_PWR_GATE_SFTCON1);
412*7cee23c8SJon Lin 
413*7cee23c8SJon Lin 	/* FixMe init 3.0 PHY */
414*7cee23c8SJon Lin 	/* Phy mode: Aggregation NBNB */
415*7cee23c8SJon Lin 	writel((0x7 << 16) | PHY_MODE_PCIE_AGGREGATION, RK3588_PCIE3PHY_GRF_CMN_CON0);
416*7cee23c8SJon Lin 	printep("PHY Mode 0x%x\n", readl(RK3588_PCIE3PHY_GRF_CMN_CON0) & 7);
417*7cee23c8SJon Lin 	/* Enable clock and sfreset for Controller and PHY */
418*7cee23c8SJon Lin 	writel(0xffff0000, CRU_SOFTRST_CON32);
419*7cee23c8SJon Lin 	writel(0xffff0000, CRU_SOFTRST_CON33);
420*7cee23c8SJon Lin 	writel(0xffff0000, CRU_SOFTRST_CON34);
421*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON32);
422*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON33);
423*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON34);
424*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON38);
425*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON39);
426*7cee23c8SJon Lin 
427*7cee23c8SJon Lin 	writel((0x1 << 24), PHPTOPCRU_SOFTRST_CON00);
428*7cee23c8SJon Lin 	writel(0xffff0000, PHPTOPCRU_GATE_CON00);
429*7cee23c8SJon Lin 
430*7cee23c8SJon Lin 	/* PHY Reset */
431*7cee23c8SJon Lin 	writel((0x1 << 10) | (0x1 << 26), PHPTOPCRU_SOFTRST_CON00);
432*7cee23c8SJon Lin 
433*7cee23c8SJon Lin 	udelay(1);
434*7cee23c8SJon Lin 
435*7cee23c8SJon Lin #ifdef PCIE_ENABLE_SRNS_PLL_REFCLK
436*7cee23c8SJon Lin 	writel(0x000f0000, CRU_PHYREF_ALT_GATE_CON);
437*7cee23c8SJon Lin 
438*7cee23c8SJon Lin 	/* PHY0 & PHY1  use internal clock */
439*7cee23c8SJon Lin 	writel(0x0 | (0x1 << 18), PCIE3PHY_GRF_PHY0_CON6);
440*7cee23c8SJon Lin 	writel(0x0 | (0x1 << 18), PCIE3PHY_GRF_PHY1_CON6);
441*7cee23c8SJon Lin 
442*7cee23c8SJon Lin 	/* phy0_rx0_cmn_refclk_mod */
443*7cee23c8SJon Lin 	writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY0_LN0_CON1);
444*7cee23c8SJon Lin 	/* phy1_rx0_cmn_refclk_mod */
445*7cee23c8SJon Lin 	writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY0_LN1_CON1);
446*7cee23c8SJon Lin 	/* phy0_rx0_cmn_refclk_mod */
447*7cee23c8SJon Lin 	writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY1_LN0_CON1);
448*7cee23c8SJon Lin 	/* phy1_rx0_cmn_refclk_mod */
449*7cee23c8SJon Lin 	writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY1_LN1_CON1);
450*7cee23c8SJon Lin #endif
451*7cee23c8SJon Lin 
452*7cee23c8SJon Lin 	udelay(1000);
453*7cee23c8SJon Lin 
454*7cee23c8SJon Lin 	/* Deassert PCIe PMA output clamp mode */
455*7cee23c8SJon Lin 	writel((0x1 << 8) | (0x1 << 24), RK3588_PCIE3PHY_GRF_CMN_CON0);
456*7cee23c8SJon Lin 
457*7cee23c8SJon Lin 	/* Deassert PHY Reset */
458*7cee23c8SJon Lin 	writel((0x1 << 26), PHPTOPCRU_SOFTRST_CON00);
459*7cee23c8SJon Lin 
460*7cee23c8SJon Lin 	/* S-Phy: waiting for phy locked */
461*7cee23c8SJon Lin 	for (i = 0; i < timeout; i++) {
462*7cee23c8SJon Lin 		phy0_mplla = readl(PCIE3PHY_GRF_BASE + 0x904);
463*7cee23c8SJon Lin 		phy1_mplla = readl(PCIE3PHY_GRF_BASE + 0xA04);
464*7cee23c8SJon Lin 
465*7cee23c8SJon Lin 		if (phy0_mplla != t0 || phy1_mplla != t1) {
466*7cee23c8SJon Lin 			printf("RKEP: GRF:904=%x, a04=%x...\n", phy0_mplla, phy1_mplla);
467*7cee23c8SJon Lin 
468*7cee23c8SJon Lin 			t0 = phy0_mplla;
469*7cee23c8SJon Lin 			t1 = phy1_mplla;
470*7cee23c8SJon Lin 			if (phy0_mplla == 0xF && phy1_mplla == 0xF)
471*7cee23c8SJon Lin 				break;
472*7cee23c8SJon Lin 		}
473*7cee23c8SJon Lin 
474*7cee23c8SJon Lin 		udelay(10);
475*7cee23c8SJon Lin 	}
476*7cee23c8SJon Lin 
477*7cee23c8SJon Lin 	/* PHY config: no config need for snps3.0phy */
478*7cee23c8SJon Lin 
479*7cee23c8SJon Lin 	/* Enable PCIe Access in firewall and master secure mode */
480*7cee23c8SJon Lin 	writel(0xffff0000, FIREWALL_PCIE_MASTER_SEC);
481*7cee23c8SJon Lin 	writel(0x01800000, FIREWALL_PCIE_ACCESS);
482*7cee23c8SJon Lin }
483*7cee23c8SJon Lin #elif CONFIG_ROCKCHIP_RK3568
484*7cee23c8SJon Lin 
485*7cee23c8SJon Lin static void pcie_board_init(void)
486*7cee23c8SJon Lin {
487*7cee23c8SJon Lin 	/* to-do */
488*7cee23c8SJon Lin }
489*7cee23c8SJon Lin 
490*7cee23c8SJon Lin static const u16 phy_fw[] = {
491*7cee23c8SJon Lin 	#include "./../../../drivers/phy/phy-rockchip-snps-pcie3.fw"
492*7cee23c8SJon Lin };
493*7cee23c8SJon Lin 
494*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON1 0x4
495*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON3 0xC
496*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON4 0x10
497*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON5 0x14
498*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON6 0x18
499*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON9 0x24
500*7cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_STATUS0 0x80
501*7cee23c8SJon Lin #define RK3568_SRAM_INIT_DONE(reg) ((reg) & BIT(14))
502*7cee23c8SJon Lin 
503*7cee23c8SJon Lin #define PMUCRU_BASE			0xFDD00000
504*7cee23c8SJon Lin #define PMUCRU_PMUGATE_CON02		(PMUCRU_BASE + 0x188)
505*7cee23c8SJon Lin 
506*7cee23c8SJon Lin #define CRU_BASE			0xFDD20000
507*7cee23c8SJon Lin #define CRU_GATE_CON12			(CRU_BASE + 0x330)
508*7cee23c8SJon Lin #define CRU_GATE_CON13			(CRU_BASE + 0x334)
509*7cee23c8SJon Lin #define CRU_GATE_CON33			(CRU_BASE + 0x384)
510*7cee23c8SJon Lin #define CRU_SOFTRST_CON12		(CRU_BASE + 0x430)
511*7cee23c8SJon Lin #define CRU_SOFTRST_CON27		(CRU_BASE + 0x46c)
512*7cee23c8SJon Lin 
513*7cee23c8SJon Lin #define PCIE30_PHY_GRF			0xFDCB8000
514*7cee23c8SJon Lin 
515*7cee23c8SJon Lin void pcie_cru_init(void)
516*7cee23c8SJon Lin {
517*7cee23c8SJon Lin 	u32 i, reg;
518*7cee23c8SJon Lin 	void __iomem *mmio = (void __iomem *)0xFE8C0000;
519*7cee23c8SJon Lin 
520*7cee23c8SJon Lin 	/* Enable phy and controoler clk */
521*7cee23c8SJon Lin 	writel(0xffff0000, PMUCRU_PMUGATE_CON02);
522*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON12);
523*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON13);
524*7cee23c8SJon Lin 	writel(0xffff0000, CRU_GATE_CON33);
525*7cee23c8SJon Lin 	writel(0xffff0000, CRU_SOFTRST_CON27);
526*7cee23c8SJon Lin 
527*7cee23c8SJon Lin 	writel(0x40004000, CRU_SOFTRST_CON27);
528*7cee23c8SJon Lin 	writel(0x80008000, PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9);
529*7cee23c8SJon Lin 
530*7cee23c8SJon Lin 	writel((0x1 << 15) | (0x1 << 31),
531*7cee23c8SJon Lin 	       PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9); //map to access sram
532*7cee23c8SJon Lin 
533*7cee23c8SJon Lin #ifdef PCIE_ENABLE_SRNS_PLL_REFCLK
534*7cee23c8SJon Lin 	/* use internal clock */
535*7cee23c8SJon Lin 	writel(0x0 | (0x1 << 31), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON3);
536*7cee23c8SJon Lin 
537*7cee23c8SJon Lin 	/* rx0_cmn_refclk_mode disabled */
538*7cee23c8SJon Lin 	writel((0x0) | (0x1 << 25), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON5);
539*7cee23c8SJon Lin 	/* rx1_cmn_refclk_mode disabled */
540*7cee23c8SJon Lin 	writel((0x0) | (0x1 << 25), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON6);
541*7cee23c8SJon Lin #endif
542*7cee23c8SJon Lin 
543*7cee23c8SJon Lin 	writel((0x0 << 14) | (0x1 << (14 + 16)),
544*7cee23c8SJon Lin 	       PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON4); //sdram_ld_done
545*7cee23c8SJon Lin 	writel((0x0 << 13) | (0x1 << (13 + 16)),
546*7cee23c8SJon Lin 	       PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON4); //sdram_bypass
547*7cee23c8SJon Lin 
548*7cee23c8SJon Lin 	writel(0x40000000, CRU_SOFTRST_CON27);
549*7cee23c8SJon Lin 
550*7cee23c8SJon Lin 	udelay(5);
551*7cee23c8SJon Lin 	printf("RKEP: sram initial\n");
552*7cee23c8SJon Lin 	while (1) {
553*7cee23c8SJon Lin 		reg = readl(PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_STATUS0);
554*7cee23c8SJon Lin 		if (RK3568_SRAM_INIT_DONE(reg))
555*7cee23c8SJon Lin 			break;
556*7cee23c8SJon Lin 	}
557*7cee23c8SJon Lin 	printf("RKEP: sram init done\n");
558*7cee23c8SJon Lin 
559*7cee23c8SJon Lin 	writel((0x3 << 8) | (0x3 << (8 + 16)),
560*7cee23c8SJon Lin 	       PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9); //map to access sram
561*7cee23c8SJon Lin 	for (i = 0; i < ARRAY_SIZE(phy_fw); i++)
562*7cee23c8SJon Lin 		writel(phy_fw[i], mmio + (i << 2));
563*7cee23c8SJon Lin 
564*7cee23c8SJon Lin 	printf("RKEP: snps pcie3phy FW update! size %ld\n", ARRAY_SIZE(phy_fw));
565*7cee23c8SJon Lin 	writel((0x0 << 8) | (0x3 << (8 + 16)),
566*7cee23c8SJon Lin 	       PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9);
567*7cee23c8SJon Lin 	writel((0x1 << 14) | (0x1 << (14 + 16)),
568*7cee23c8SJon Lin 	       PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON4); //sdram_ld_done
569*7cee23c8SJon Lin 
570*7cee23c8SJon Lin 	writel(0xffff0000, CRU_SOFTRST_CON12);
571*7cee23c8SJon Lin 	writel(0x100010, PCIE_SNPS_APB_BASE + 0x180);
572*7cee23c8SJon Lin 
573*7cee23c8SJon Lin 	udelay(1);
574*7cee23c8SJon Lin }
575*7cee23c8SJon Lin #endif
576*7cee23c8SJon Lin 
5774c8e468bSKever Yang static void pcie_ep_init(void)
5784c8e468bSKever Yang {
5794c8e468bSKever Yang 	u32 val;
5804c8e468bSKever Yang 	void *dbi_base = (void *)PCIE_SNPS_DBI_BASE;
5814c8e468bSKever Yang 	u64 apb_base = PCIE_SNPS_APB_BASE;
5824c8e468bSKever Yang 	int i, retries = 0;
5834c8e468bSKever Yang 
5844c8e468bSKever Yang #ifdef PCIE_ENABLE_SRNS_PLL_REFCLK
5854c8e468bSKever Yang 	printep("RefClock in SRNS clock mode\n");
5864c8e468bSKever Yang #else
5874c8e468bSKever Yang 	printep("RefClock in common clock_mode\n");
5884c8e468bSKever Yang #endif
5894c8e468bSKever Yang 
5904c8e468bSKever Yang 	/*
5912f33b98fSJon Lin 	 * ltssm_enable enhance mode and enable delaying the link training
5924c8e468bSKever Yang 	 * after Hot Reset
5934c8e468bSKever Yang 	 */
5944c8e468bSKever Yang 	writel(0x120012, apb_base + 0x180);
5954c8e468bSKever Yang 
5962f33b98fSJon Lin 	/* Unmask pm_turnoff_int */
5972f33b98fSJon Lin 	writel(0x04000000, apb_base + 0x18);
5982f33b98fSJon Lin 
5994c8e468bSKever Yang 	/* PortLorgic DBI_RO_WR_EN */
6004c8e468bSKever Yang 	val = readl((dbi_base + 0x8bc));
6014c8e468bSKever Yang 	val |= 0x1;
6024c8e468bSKever Yang 	writel(val, dbi_base + 0x8bc);
6034c8e468bSKever Yang 
6044c8e468bSKever Yang reinit:
6054c8e468bSKever Yang 	pcie_bar_init(dbi_base);
6064c8e468bSKever Yang 	pcie_inbound_config();
6074c8e468bSKever Yang 
6084c8e468bSKever Yang 	/* Device PID, DID */
6094c8e468bSKever Yang 	writel(0x1d87, dbi_base + 0x00);
6104c8e468bSKever Yang 	writel(0x356a, dbi_base + 0x02);
6114c8e468bSKever Yang 	/* Device Class: Processing accelerators */
6124c8e468bSKever Yang 	writel(0x1200, dbi_base + 0x0a);
6134c8e468bSKever Yang 
6142f33b98fSJon Lin 	pcie_link_set_max_speed(dbi_base, PCI_EXP_LNKCTL2_TLS_8_0GT);
615*7cee23c8SJon Lin 
616*7cee23c8SJon Lin #ifdef	CONFIG_ROCKCHIP_RK3588
6172f33b98fSJon Lin 	pcie_link_set_lanes(dbi_base, 4);
618*7cee23c8SJon Lin #elif	CONFIG_ROCKCHIP_RK3568
619*7cee23c8SJon Lin 	pcie_link_set_lanes(dbi_base, 2);
620*7cee23c8SJon Lin #endif
6212f33b98fSJon Lin 
6224c8e468bSKever Yang 	/* EP mode */
6234c8e468bSKever Yang 	writel(0xf00000, apb_base);
6244c8e468bSKever Yang 	udelay(100);
6254c8e468bSKever Yang 
6264c8e468bSKever Yang 	/* Enable EP mem/io access */
6274c8e468bSKever Yang 	val = readl(dbi_base + 0x4);
6284c8e468bSKever Yang 	writel(val | 0x6, dbi_base + 0x4);
6294c8e468bSKever Yang 
6304c8e468bSKever Yang 	if (retries)	/* Set app_dly2_done to enable app_ltssm_enable */
6314c8e468bSKever Yang 		writel(0x80008, apb_base + 0x180);
6324c8e468bSKever Yang 	else		/* Enable LTSSM */
6334c8e468bSKever Yang 		writel(0xc000c, apb_base);
6344c8e468bSKever Yang 	printep("init PCIe fast Link up\n");
6356fa0195bSXiao Ya peng 	pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_LNKRDY);
6364c8e468bSKever Yang 
6374c8e468bSKever Yang 	/* Waiting for Link up */
6384c8e468bSKever Yang 	while (1) {
6394c8e468bSKever Yang 		val = readl(apb_base + 0x300);
6404c8e468bSKever Yang 		if (((val & 0x3ffff) & ((0x3 << 16) | 0x11)) == 0x30011)
6414c8e468bSKever Yang 			break;
6422f33b98fSJon Lin 		mdelay(1);
6434c8e468bSKever Yang 	}
6444c8e468bSKever Yang 	printep("Link up %x\n", val);
6452f33b98fSJon Lin 	mdelay(3);
6464c8e468bSKever Yang 
6474c8e468bSKever Yang 	/* Wait for link stable */
6484c8e468bSKever Yang 	for (i = 0; i < 10000; i++) {
6494c8e468bSKever Yang 		val = readl(apb_base + 0x10);
6504c8e468bSKever Yang 		if (val & 0x4) {
6514c8e468bSKever Yang 			writel(0x4, apb_base + 0x10);
6524c8e468bSKever Yang 			printep("Link is reset, int status misc=%x\n", val);
6534c8e468bSKever Yang 			if (retries < 3) {
6544c8e468bSKever Yang 				retries++;
6554c8e468bSKever Yang 				goto reinit;
6564c8e468bSKever Yang 			} else {
6574c8e468bSKever Yang 				break;
6584c8e468bSKever Yang 			}
6594c8e468bSKever Yang 		}
6604c8e468bSKever Yang 		udelay(1);
6614c8e468bSKever Yang 	}
6624c8e468bSKever Yang 	printep("Done\n");
6636fa0195bSXiao Ya peng 	pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_LNKUP);
6644c8e468bSKever Yang }
6654c8e468bSKever Yang 
6664c8e468bSKever Yang void rockchip_pcie_ep_init(void)
6674c8e468bSKever Yang {
668*7cee23c8SJon Lin 	u32 val;
669*7cee23c8SJon Lin 
6704c8e468bSKever Yang 	printf("\nRKEP: Init PCIe EP\n");
6714c8e468bSKever Yang 	pcie_bar0_header_init();
6724c8e468bSKever Yang 
673*7cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
674*7cee23c8SJon Lin 	writel(0x1 << 23 | 0x1 << 21, PMU_PWR_GATE_SFTCON1);
675*7cee23c8SJon Lin 	udelay(10);
676*7cee23c8SJon Lin #endif
677*7cee23c8SJon Lin 	/* Re-in pcie initial */
678*7cee23c8SJon Lin 	val = readl(PCIE_SNPS_APB_BASE + 0x300);
679*7cee23c8SJon Lin 	if (((val & 0x3ffff) & ((0x3 << 16))) == 0x30000) {
680*7cee23c8SJon Lin 		printf("RKEP: already link up\n");
681*7cee23c8SJon Lin 		return;
682*7cee23c8SJon Lin 	}
683*7cee23c8SJon Lin 
6844c8e468bSKever Yang 	pcie_board_init();
6854c8e468bSKever Yang 	/* CRU and PHY Init */
6864c8e468bSKever Yang 	pcie_cru_init();
6874c8e468bSKever Yang 
6884c8e468bSKever Yang 	pcie_ep_init();
6894c8e468bSKever Yang }
690