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