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
267cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
277cee23c8SJon Lin #define PCIE_SNPS_DBI_BASE 0xf5000000
287cee23c8SJon Lin #define PCIE_SNPS_APB_BASE 0xfe150000
297cee23c8SJon Lin #define PCIE_SNPS_IATU_BASE 0xa40300000
307cee23c8SJon Lin
317cee23c8SJon Lin #define PCI_RESBAR 0x2e8
327cee23c8SJon Lin #elif CONFIG_ROCKCHIP_RK3568
337cee23c8SJon Lin #define PCIE_SNPS_DBI_BASE 0xf6000000
347cee23c8SJon Lin #define PCIE_SNPS_APB_BASE 0xfe280000
357cee23c8SJon Lin #define PCIE_SNPS_IATU_BASE 0x3c0b00000
367cee23c8SJon Lin
377cee23c8SJon Lin #define PCI_RESBAR 0x2b8
387cee23c8SJon Lin #else
397cee23c8SJon Lin #error "this soc is not support pcie ep!"
407cee23c8SJon Lin #endif
417cee23c8SJon 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
pcie_inbound_config(void)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
rockchip_pcie_ep_set_bar_flag(void * dbi_base,u32 barno,int flags)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
pcie_bar_init(void * dbi_base)1864c8e468bSKever Yang static void pcie_bar_init(void *dbi_base)
1874c8e468bSKever Yang {
1884c8e468bSKever Yang void *resbar_base;
1898269535eSXiao Ya peng u32 val;
1904c8e468bSKever Yang
1914c8e468bSKever Yang writel(0, dbi_base + 0x10);
1924c8e468bSKever Yang writel(0, dbi_base + 0x14);
1934c8e468bSKever Yang writel(0, dbi_base + 0x18);
1944c8e468bSKever Yang writel(0, dbi_base + 0x1c);
1954c8e468bSKever Yang writel(0, dbi_base + 0x20);
1964c8e468bSKever Yang writel(0, dbi_base + 0x24);
1974c8e468bSKever Yang
198a74e90eeSJon Lin /* Disable ASPM */
199a74e90eeSJon Lin val = readl(dbi_base + 0x7c);
200a74e90eeSJon Lin val &= ~(3 << 10);
201a74e90eeSJon Lin writel(val, dbi_base + 0x7c);
202a74e90eeSJon Lin
2034c8e468bSKever Yang /* Resize BAR0 to support 4M 32bits */
2047cee23c8SJon Lin resbar_base = dbi_base + PCI_RESBAR;
20511badaecSJon Lin writel(0x40, resbar_base + 0x4);
2064c8e468bSKever Yang writel(0x2c0, resbar_base + 0x8);
2074c8e468bSKever Yang /* BAR2: 64M 64bits */
20811badaecSJon Lin writel(0x400, resbar_base + 0x14);
2094c8e468bSKever Yang writel(0x6c0, resbar_base + 0x18);
2104c8e468bSKever Yang /* BAR4: Fixed for EP wired register, 1M 32bits */
21111badaecSJon Lin writel(0x10, resbar_base + 0x24);
2124c8e468bSKever Yang writel(0xc0, resbar_base + 0x28);
2134c8e468bSKever Yang /* Set flags */
2144c8e468bSKever Yang rockchip_pcie_ep_set_bar_flag(dbi_base, 0, PCI_BASE_ADDRESS_MEM_TYPE_32);
2152f33b98fSJon Lin rockchip_pcie_ep_set_bar_flag(dbi_base, 2,
2162f33b98fSJon Lin PCI_BASE_ADDRESS_MEM_PREFETCH | PCI_BASE_ADDRESS_MEM_TYPE_64);
2174c8e468bSKever Yang rockchip_pcie_ep_set_bar_flag(dbi_base, 4, PCI_BASE_ADDRESS_MEM_TYPE_32);
2184c8e468bSKever Yang
21954afed56SJon Lin /* Close bar1 bar5 */
2204c8e468bSKever Yang writel(0x0, dbi_base + 0x100000 + 0x14);
2214c8e468bSKever Yang //writel(0x0, dbi_base + 0x100000 + 0x18);
22254afed56SJon Lin //writel(0x0, dbi_base + 0x100000 + 0x1c);
2234c8e468bSKever Yang //writel(0x0, dbi_base + 0x100000 + 0x20);
2244c8e468bSKever Yang writel(0x0, dbi_base + 0x100000 + 0x24);
2254c8e468bSKever Yang /* Close ROM BAR */
2264c8e468bSKever Yang writel(0x0, dbi_base + 0x100000 + 0x30);
2274c8e468bSKever Yang }
2284c8e468bSKever Yang
pcie_bar0_header_init(void)2294c8e468bSKever Yang static void pcie_bar0_header_init(void)
2304c8e468bSKever Yang {
2314c8e468bSKever Yang struct rkpcie_boot *bh = (struct rkpcie_boot *)RKEP_BAR0_ADDR;
2324c8e468bSKever Yang
2334c8e468bSKever Yang bh->magic = RKEP_BOOT_MAGIC;
2344c8e468bSKever Yang bh->version = 0x100;
2354c8e468bSKever Yang bh->devmode.mode = RKEP_MODE_LOADER;
2364c8e468bSKever Yang bh->devmode.submode = RKEP_SMODE_INIT;
2374c8e468bSKever Yang bh->cap_size = 0;
2384c8e468bSKever Yang
2394c8e468bSKever Yang memset((char *)RKEP_BAR0_CMD_ADDR, 0, sizeof(struct rkpcie_cmd));
2404c8e468bSKever Yang }
2414c8e468bSKever Yang
pcie_link_set_max_speed(void * dbi_base,u32 link_gen)2422f33b98fSJon Lin static void pcie_link_set_max_speed(void *dbi_base, u32 link_gen)
2432f33b98fSJon Lin {
2442f33b98fSJon Lin u32 cap, ctrl2, link_speed;
2452f33b98fSJon Lin u8 offset = 0x70;
2462f33b98fSJon Lin
2472f33b98fSJon Lin cap = readl(dbi_base + offset + PCI_EXP_LNKCAP);
2482f33b98fSJon Lin ctrl2 = readl(dbi_base + offset + PCI_EXP_LNKCTL2);
2492f33b98fSJon Lin ctrl2 &= ~PCI_EXP_LNKCTL2_TLS;
2502f33b98fSJon Lin
2512f33b98fSJon Lin link_speed = link_gen;
2522f33b98fSJon Lin
2532f33b98fSJon Lin cap &= ~((u32)PCI_EXP_LNKCAP_SLS);
2542f33b98fSJon Lin writel(ctrl2 | link_speed, dbi_base + offset + PCI_EXP_LNKCTL2);
2552f33b98fSJon Lin writel(cap | link_speed, dbi_base + offset + PCI_EXP_LNKCAP);
2562f33b98fSJon Lin }
2572f33b98fSJon Lin
pcie_link_set_lanes(void * dbi_base,u32 lanes)2582f33b98fSJon Lin static void pcie_link_set_lanes(void *dbi_base, u32 lanes)
2592f33b98fSJon Lin {
2602f33b98fSJon Lin u32 val;
2612f33b98fSJon Lin
2622f33b98fSJon Lin /* Set the number of lanes */
2632f33b98fSJon Lin val = readl(dbi_base + PCIE_PORT_LINK_CONTROL);
2642f33b98fSJon Lin val &= ~PORT_LINK_MODE_MASK;
2652f33b98fSJon Lin switch (lanes) {
2662f33b98fSJon Lin case 1:
2672f33b98fSJon Lin val |= PORT_LINK_MODE_1_LANES;
2682f33b98fSJon Lin break;
2692f33b98fSJon Lin case 2:
2702f33b98fSJon Lin val |= PORT_LINK_MODE_2_LANES;
2712f33b98fSJon Lin break;
2722f33b98fSJon Lin case 4:
2732f33b98fSJon Lin val |= PORT_LINK_MODE_4_LANES;
2742f33b98fSJon Lin break;
2752f33b98fSJon Lin default:
2767cee23c8SJon Lin printf("RKEP: num-lanes %u: invalid value\n", lanes);
2772f33b98fSJon Lin return;
2782f33b98fSJon Lin }
2792f33b98fSJon Lin writel(val, dbi_base + PCIE_PORT_LINK_CONTROL);
2802f33b98fSJon Lin
2812f33b98fSJon Lin /* Set link width speed control register */
2822f33b98fSJon Lin val = readl(dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
2832f33b98fSJon Lin val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
2842f33b98fSJon Lin switch (lanes) {
2852f33b98fSJon Lin case 1:
2862f33b98fSJon Lin val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
2872f33b98fSJon Lin break;
2882f33b98fSJon Lin case 2:
2892f33b98fSJon Lin val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
2902f33b98fSJon Lin break;
2912f33b98fSJon Lin case 4:
2922f33b98fSJon Lin val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
2932f33b98fSJon Lin break;
2942f33b98fSJon Lin }
2952f33b98fSJon Lin
2962f33b98fSJon Lin val |= PCIE_DIRECT_SPEED_CHANGE;
2972f33b98fSJon Lin
2982f33b98fSJon Lin writel(val, dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
2992f33b98fSJon Lin }
3002f33b98fSJon Lin
pcie_devmode_update(int mode,int submode)3016fa0195bSXiao Ya peng static void pcie_devmode_update(int mode, int submode)
3026fa0195bSXiao Ya peng {
3036fa0195bSXiao Ya peng struct rkpcie_boot *bh = (struct rkpcie_boot *)RKEP_BAR0_ADDR;
3046fa0195bSXiao Ya peng
3056fa0195bSXiao Ya peng bh->devmode.mode = mode;
3066fa0195bSXiao Ya peng bh->devmode.submode = submode;
30726d59203SXiao Ya peng flush_dcache_range(RKEP_BAR0_ADDR, RKEP_BAR0_ADDR + 64);
3086fa0195bSXiao Ya peng }
3096fa0195bSXiao Ya peng
3104c8e468bSKever Yang #ifdef CONFIG_SPL_RAM_DEVICE
pcie_wait_for_fw(void)3114c8e468bSKever Yang static void pcie_wait_for_fw(void)
3124c8e468bSKever Yang {
3134c8e468bSKever Yang struct rkpcie_cmd *cmd = (struct rkpcie_cmd *)(RKEP_BAR0_CMD_ADDR);
3144c8e468bSKever Yang int val;
3154c8e468bSKever Yang int i = 0;
3164c8e468bSKever Yang
3174c8e468bSKever Yang printep("Link ready! Waiting RC to download Firmware:\n");
3184c8e468bSKever Yang printep("Download uboot.img to BAR2+0\n");
3194c8e468bSKever Yang printep("Download boot.img to BAR2+0x400000\n");
3204c8e468bSKever Yang printep("Send CMD_LOADER_RUN to BAR0+0x400\n");
3214c8e468bSKever Yang while (1) {
3224c8e468bSKever Yang invalidate_dcache_range(RKEP_BAR0_CMD_ADDR,
3234c8e468bSKever Yang RKEP_BAR0_CMD_ADDR + 32);
3244c8e468bSKever Yang val = readl(&cmd->cmd);
3254c8e468bSKever Yang if (val == RKEP_CMD_LOADER_RUN)
3264c8e468bSKever Yang break;
3274c8e468bSKever Yang i++;
3284c8e468bSKever Yang if (!(i % 10))
3294c8e468bSKever Yang printep("Waiting for FW, CMD: %x\n", val);
3302f33b98fSJon Lin mdelay(100);
3314c8e468bSKever Yang }
3324c8e468bSKever Yang /* Invalidate Cache for firmware area: BAR2, 64MB */
3334c8e468bSKever Yang invalidate_dcache_range(RKEP_BAR2_ADDR, RKEP_BAR2_ADDR + 0x4000000);
3344c8e468bSKever Yang printep("Firmware Download complete!\n");
3354c8e468bSKever Yang }
3364c8e468bSKever Yang
pcie_update_atags(void)3374c8e468bSKever Yang static void pcie_update_atags(void)
3384c8e468bSKever Yang {
3394c8e468bSKever Yang struct tag_ram_partition t_ram_part;
3404c8e468bSKever Yang
3414c8e468bSKever Yang if (!atags_is_available()) {
3428269535eSXiao Ya peng printep("RKEP: No ATAGS data found, create new!\n");
3434c8e468bSKever Yang atags_destroy();
3444c8e468bSKever Yang }
3454c8e468bSKever Yang
3464c8e468bSKever Yang /* ram partition */
3474c8e468bSKever Yang memset(&t_ram_part, 0, sizeof(t_ram_part));
3484c8e468bSKever Yang t_ram_part.version = 0;
3494c8e468bSKever Yang t_ram_part.count = 1;
3504c8e468bSKever Yang strcpy(t_ram_part.part[0].name, "boot");
3514c8e468bSKever Yang t_ram_part.part[0].start = RKEP_BAR2_ADDR + 0x400000; /* 4M offset */
3524c8e468bSKever Yang t_ram_part.part[0].size = 0x3c00000; /* 60M size */
3534c8e468bSKever Yang atags_set_tag(ATAG_RAM_PARTITION, &t_ram_part);
3544c8e468bSKever Yang }
3554c8e468bSKever Yang
rockchip_pcie_ep_get_firmware(void)3564c8e468bSKever Yang void rockchip_pcie_ep_get_firmware(void)
3574c8e468bSKever Yang {
3586fa0195bSXiao Ya peng pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_FWDLRDY);
3594c8e468bSKever Yang pcie_wait_for_fw();
3604c8e468bSKever Yang pcie_update_atags();
3616fa0195bSXiao Ya peng pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_FWDLDONE);
3624c8e468bSKever Yang }
3634c8e468bSKever Yang #endif
3644c8e468bSKever Yang
3657cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
3667cee23c8SJon Lin #define BUS_IOC_GPIO3D_IOMUX_SEL_H 0xfd5f807c
3677cee23c8SJon Lin #define GPIO3_BASE 0xfec40000
3687cee23c8SJon Lin #define GPIO3_SWPORT_DR_H (GPIO3_BASE + 0x4)
3697cee23c8SJon Lin #define GPIO3_SWPORT_DDR_H (GPIO3_BASE + 0xc)
3707cee23c8SJon Lin
pcie_board_init(void)3717cee23c8SJon Lin static void pcie_board_init(void)
3727cee23c8SJon Lin {
3737cee23c8SJon Lin /* Enable AU5426 buffer chip on EVB4v10 */
3747cee23c8SJon Lin /* Set GPIO3D4 to gpio output HIGH mode PCIE20_CLK_PWREN */
3757cee23c8SJon Lin writel(0xf << 16, BUS_IOC_GPIO3D_IOMUX_SEL_H);
3767cee23c8SJon Lin writel(0x10001000, GPIO3_SWPORT_DDR_H);
3777cee23c8SJon Lin writel(0x10001000, GPIO3_SWPORT_DR_H);
3787cee23c8SJon Lin udelay(100);
3797cee23c8SJon Lin }
3807cee23c8SJon Lin
3817cee23c8SJon Lin #define PHY_MODE_PCIE_AGGREGATION 4 /* PCIe3x4 */
3827cee23c8SJon Lin #define PHY_MODE_PCIE_NANBNB 0 /* P1:PCIe3x2 + P0:PCIe3x2 */
3837cee23c8SJon Lin #define PHY_MODE_PCIE_NANBBI 1 /* P1:PCIe3x2 + P0:PCIe3x1*2 */
3847cee23c8SJon Lin #define PHY_MODE_PCIE_NABINB 2 /* P1:PCIe3x1*2 + P0:PCIe3x2 */
3857cee23c8SJon Lin #define PHY_MODE_PCIE_NABIBI 3 /* P1:PCIe3x1*2 + P0:PCIe3x1*2 */
3867cee23c8SJon Lin
387fe857eeaSJon Lin #define PHY_MODE_PCIE PHY_MODE_PCIE_AGGREGATION
388fe857eeaSJon Lin
3897cee23c8SJon Lin #define CRU_BASE_ADDR 0xfd7c0000
3907cee23c8SJon Lin #define CRU_SOFTRST_CON32 (CRU_BASE_ADDR + 0x0a80)
3917cee23c8SJon Lin #define CRU_SOFTRST_CON33 (CRU_BASE_ADDR + 0x0a84)
3927cee23c8SJon Lin #define CRU_SOFTRST_CON34 (CRU_BASE_ADDR + 0x0a88)
3937cee23c8SJon Lin #define CRU_GATE_CON32 (CRU_BASE_ADDR + 0x0880)
3947cee23c8SJon Lin #define CRU_GATE_CON33 (CRU_BASE_ADDR + 0x0884)
3957cee23c8SJon Lin #define CRU_GATE_CON34 (CRU_BASE_ADDR + 0x0888)
3967cee23c8SJon Lin #define CRU_GATE_CON38 (CRU_BASE_ADDR + 0x0898)
3977cee23c8SJon Lin #define CRU_GATE_CON39 (CRU_BASE_ADDR + 0x089c)
3987cee23c8SJon Lin #define PHPTOPCRU_BASE_ADDR 0xfd7c8000
3997cee23c8SJon Lin #define PHPTOPCRU_SOFTRST_CON00 (PHPTOPCRU_BASE_ADDR + 0x0a00)
4007cee23c8SJon Lin #define PHPTOPCRU_GATE_CON00 (PHPTOPCRU_BASE_ADDR + 0x0800)
4017cee23c8SJon Lin #define PCIE3PHY_GRF_BASE 0xfd5b8000
4027cee23c8SJon Lin #define RK3588_PCIE3PHY_GRF_CMN_CON0 (PCIE3PHY_GRF_BASE + 0x0000)
4037cee23c8SJon Lin #define PCIE3PHY_GRF_PHY0_CON6 (PCIE3PHY_GRF_BASE + 0x0118)
4047cee23c8SJon Lin #define PCIE3PHY_GRF_PHY1_CON6 (PCIE3PHY_GRF_BASE + 0x0218)
4057cee23c8SJon Lin #define PCIE3PHY_GRF_PHY0_LN0_CON1 (PCIE3PHY_GRF_BASE + 0x1004)
4067cee23c8SJon Lin #define PCIE3PHY_GRF_PHY0_LN1_CON1 (PCIE3PHY_GRF_BASE + 0x1104)
4077cee23c8SJon Lin #define PCIE3PHY_GRF_PHY1_LN0_CON1 (PCIE3PHY_GRF_BASE + 0x2004)
4087cee23c8SJon Lin #define PCIE3PHY_GRF_PHY1_LN1_CON1 (PCIE3PHY_GRF_BASE + 0x2104)
4097cee23c8SJon Lin #define FIREWALL_PCIE_MASTER_SEC 0xfe0300f0
410197c7fbfSJon Lin #define FIREWALL_PCIE_ACCESS 0xfd586040
4117cee23c8SJon Lin #define CRU_PHYREF_ALT_GATE_CON (CRU_BASE_ADDR + 0x0c38)
412d0abf46dSJon Lin #define PMU1_GRF_BASE 0xfd58a000
4137cee23c8SJon Lin #define PMU_PWR_GATE_SFTCON1 0xfd8d8150
414d0abf46dSJon Lin #define PMU1_IOC_BASE 0xfd5F0000
415d0abf46dSJon Lin #define CRU_GLB_RST_CON_OFFSET (0xC10U)
416d0abf46dSJon Lin #define CRU_GLB_SRST_FST_VALUE_OFFSET (0xC08U)
417d0abf46dSJon Lin
418*867b5b94SJon Lin #define RK3588_SRAM_INIT_DONE(reg) ((reg & 0xf) == 0xf)
419*867b5b94SJon Lin
pcie_first_reset(void)420d0abf46dSJon Lin void pcie_first_reset(void)
421d0abf46dSJon Lin {
422d0abf46dSJon Lin printep("Fst Reset\n");
423d0abf46dSJon Lin mdelay(1);
424d0abf46dSJon Lin
425d0abf46dSJon Lin writel(0xFFDF, CRU_BASE_ADDR + CRU_GLB_RST_CON_OFFSET);
426d0abf46dSJon Lin writel(0xffffffff, PMU1_GRF_BASE + 0x4); // reset width
427d0abf46dSJon Lin writel(0x30003000, PMU1_GRF_BASE + 0x1c); // pmu1_grf pmu1_ioc hiold
428d0abf46dSJon Lin writel(0x00f00020, PMU1_IOC_BASE + 0x0); //select tsad_shut_m0 iomux
429d0abf46dSJon Lin writel(0xFDB9, CRU_BASE_ADDR + CRU_GLB_SRST_FST_VALUE_OFFSET);
430d0abf46dSJon Lin
431d0abf46dSJon Lin while (1)
432d0abf46dSJon Lin ;
433d0abf46dSJon Lin }
434d0abf46dSJon Lin
pcie_cru_init(void)4357cee23c8SJon Lin static void pcie_cru_init(void)
4367cee23c8SJon Lin {
4377cee23c8SJon Lin u32 phy0_mplla, phy1_mplla, t0 = 0, t1 = 0;
4387cee23c8SJon Lin u32 i, timeout = 500;
4397cee23c8SJon Lin
4407cee23c8SJon Lin /* Enable power domain: PD_PCIE & PD_PHP */
4417cee23c8SJon Lin writel(0x1 << 23 | 0x1 << 21, PMU_PWR_GATE_SFTCON1);
4427cee23c8SJon Lin
4437cee23c8SJon Lin /* FixMe init 3.0 PHY */
4447cee23c8SJon Lin /* Phy mode: Aggregation NBNB */
445fe857eeaSJon Lin writel((0x7 << 16) | PHY_MODE_PCIE, RK3588_PCIE3PHY_GRF_CMN_CON0);
4467cee23c8SJon Lin printep("PHY Mode 0x%x\n", readl(RK3588_PCIE3PHY_GRF_CMN_CON0) & 7);
4477cee23c8SJon Lin /* Enable clock and sfreset for Controller and PHY */
448*867b5b94SJon Lin writel(0xFFFC0000, CRU_SOFTRST_CON33);
4497cee23c8SJon Lin writel(0xffff0000, CRU_SOFTRST_CON34);
4507cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON32);
4517cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON33);
4527cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON34);
4537cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON38);
4547cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON39);
4557cee23c8SJon Lin
4567cee23c8SJon Lin writel((0x1 << 24), PHPTOPCRU_SOFTRST_CON00);
4577cee23c8SJon Lin writel(0xffff0000, PHPTOPCRU_GATE_CON00);
4587cee23c8SJon Lin
4597cee23c8SJon Lin /* PHY Reset */
4607cee23c8SJon Lin writel((0x1 << 10) | (0x1 << 26), PHPTOPCRU_SOFTRST_CON00);
4617cee23c8SJon Lin
4627cee23c8SJon Lin udelay(1);
4637cee23c8SJon Lin
4647cee23c8SJon Lin #ifdef PCIE_ENABLE_SRNS_PLL_REFCLK
4657cee23c8SJon Lin writel(0x000f0000, CRU_PHYREF_ALT_GATE_CON);
4667cee23c8SJon Lin
4677cee23c8SJon Lin /* PHY0 & PHY1 use internal clock */
4687cee23c8SJon Lin writel(0x0 | (0x1 << 18), PCIE3PHY_GRF_PHY0_CON6);
4697cee23c8SJon Lin writel(0x0 | (0x1 << 18), PCIE3PHY_GRF_PHY1_CON6);
4707cee23c8SJon Lin
4717cee23c8SJon Lin /* phy0_rx0_cmn_refclk_mod */
4727cee23c8SJon Lin writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY0_LN0_CON1);
4737cee23c8SJon Lin /* phy1_rx0_cmn_refclk_mod */
4747cee23c8SJon Lin writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY0_LN1_CON1);
4757cee23c8SJon Lin /* phy0_rx0_cmn_refclk_mod */
4767cee23c8SJon Lin writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY1_LN0_CON1);
4777cee23c8SJon Lin /* phy1_rx0_cmn_refclk_mod */
4787cee23c8SJon Lin writel((0x0) | (0x1 << 23), PCIE3PHY_GRF_PHY1_LN1_CON1);
4797cee23c8SJon Lin #endif
4807cee23c8SJon Lin
4817cee23c8SJon Lin udelay(1000);
4827cee23c8SJon Lin
4837cee23c8SJon Lin /* Deassert PCIe PMA output clamp mode */
4847cee23c8SJon Lin writel((0x1 << 8) | (0x1 << 24), RK3588_PCIE3PHY_GRF_CMN_CON0);
4857cee23c8SJon Lin
4867cee23c8SJon Lin /* Deassert PHY Reset */
4877cee23c8SJon Lin writel((0x1 << 26), PHPTOPCRU_SOFTRST_CON00);
488*867b5b94SJon Lin udelay(10);
489*867b5b94SJon Lin
490*867b5b94SJon Lin /* release resetn_pcie_4l_power_up */
491*867b5b94SJon Lin writel(0x20000000, CRU_SOFTRST_CON32);
492*867b5b94SJon Lin udelay(10);
4937cee23c8SJon Lin
4947cee23c8SJon Lin /* S-Phy: waiting for phy locked */
4957cee23c8SJon Lin for (i = 0; i < timeout; i++) {
4967cee23c8SJon Lin phy0_mplla = readl(PCIE3PHY_GRF_BASE + 0x904);
4977cee23c8SJon Lin phy1_mplla = readl(PCIE3PHY_GRF_BASE + 0xA04);
4987cee23c8SJon Lin
4997cee23c8SJon Lin if (phy0_mplla != t0 || phy1_mplla != t1) {
500d0abf46dSJon Lin printep("RKEP: GRF:904=%x, a04=%x...\n", phy0_mplla, phy1_mplla);
5017cee23c8SJon Lin
5027cee23c8SJon Lin t0 = phy0_mplla;
5037cee23c8SJon Lin t1 = phy1_mplla;
504*867b5b94SJon Lin
505*867b5b94SJon Lin if (RK3588_SRAM_INIT_DONE(phy0_mplla)) {
506*867b5b94SJon Lin if (PHY_MODE_PCIE == PHY_MODE_PCIE_AGGREGATION && RK3588_SRAM_INIT_DONE(phy1_mplla))
5077cee23c8SJon Lin break;
508*867b5b94SJon Lin else
509*867b5b94SJon Lin break;
510*867b5b94SJon Lin }
5117cee23c8SJon Lin }
5127cee23c8SJon Lin
5137cee23c8SJon Lin udelay(10);
5147cee23c8SJon Lin }
5157cee23c8SJon Lin
516d0abf46dSJon Lin if (i >= timeout) {
517d0abf46dSJon Lin printep("lock fail\n");
518d0abf46dSJon Lin mdelay(1);
519d0abf46dSJon Lin pcie_first_reset();
520d0abf46dSJon Lin }
521d0abf46dSJon Lin
5227cee23c8SJon Lin /* PHY config: no config need for snps3.0phy */
523a74e90eeSJon Lin }
5247cee23c8SJon Lin
pcie_firewall_init(void)525a74e90eeSJon Lin static void pcie_firewall_init(void)
526a74e90eeSJon Lin {
5277cee23c8SJon Lin /* Enable PCIe Access in firewall and master secure mode */
5287cee23c8SJon Lin writel(0xffff0000, FIREWALL_PCIE_MASTER_SEC);
529197c7fbfSJon Lin writel(0x03000000, FIREWALL_PCIE_ACCESS);
5307cee23c8SJon Lin }
5317cee23c8SJon Lin #elif CONFIG_ROCKCHIP_RK3568
5327cee23c8SJon Lin
pcie_board_init(void)5337cee23c8SJon Lin static void pcie_board_init(void)
5347cee23c8SJon Lin {
5357cee23c8SJon Lin /* to-do */
5367cee23c8SJon Lin }
5377cee23c8SJon Lin
5387cee23c8SJon Lin static const u16 phy_fw[] = {
5397cee23c8SJon Lin #include "./../../../drivers/phy/phy-rockchip-snps-pcie3.fw"
5407cee23c8SJon Lin };
5417cee23c8SJon Lin
5427cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON1 0x4
5437cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON3 0xC
5447cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON4 0x10
5457cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON5 0x14
5467cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON6 0x18
5477cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_CON9 0x24
5487cee23c8SJon Lin #define GRF_PCIE30PHY_RK3568_STATUS0 0x80
5497cee23c8SJon Lin #define RK3568_SRAM_INIT_DONE(reg) ((reg) & BIT(14))
5507cee23c8SJon Lin
5517cee23c8SJon Lin #define PMUCRU_BASE 0xFDD00000
5527cee23c8SJon Lin #define PMUCRU_PMUGATE_CON02 (PMUCRU_BASE + 0x188)
5537cee23c8SJon Lin
5547cee23c8SJon Lin #define CRU_BASE 0xFDD20000
5557cee23c8SJon Lin #define CRU_GATE_CON12 (CRU_BASE + 0x330)
5567cee23c8SJon Lin #define CRU_GATE_CON13 (CRU_BASE + 0x334)
5577cee23c8SJon Lin #define CRU_GATE_CON33 (CRU_BASE + 0x384)
5587cee23c8SJon Lin #define CRU_SOFTRST_CON12 (CRU_BASE + 0x430)
5597cee23c8SJon Lin #define CRU_SOFTRST_CON27 (CRU_BASE + 0x46c)
560d0abf46dSJon Lin #define CRU_GLB_SRST_FST_OFFSET (0xD4U)
5617cee23c8SJon Lin
5627cee23c8SJon Lin #define PCIE30_PHY_GRF 0xFDCB8000
5637cee23c8SJon Lin
564d0abf46dSJon Lin #define SYS_GRF_BASE 0xFDC60000
565d0abf46dSJon Lin
pcie_first_reset(void)566d0abf46dSJon Lin void pcie_first_reset(void)
567d0abf46dSJon Lin {
568d0abf46dSJon Lin printep("Fst Reset\n");
569d0abf46dSJon Lin mdelay(1);
570d0abf46dSJon Lin
571d0abf46dSJon Lin writel(0x00040004, CRU_BASE + 0x104);
572d0abf46dSJon Lin writel(0x00700010, CRU_BASE);
573d0abf46dSJon Lin writel(0x00100010, SYS_GRF_BASE + 0x508);
574d0abf46dSJon Lin writel(0xFDB9, CRU_BASE + CRU_GLB_SRST_FST_OFFSET);
575d0abf46dSJon Lin
576d0abf46dSJon Lin while (1)
577d0abf46dSJon Lin ;
578d0abf46dSJon Lin }
579d0abf46dSJon Lin
pcie_cru_init(void)5807cee23c8SJon Lin void pcie_cru_init(void)
5817cee23c8SJon Lin {
582d0abf46dSJon Lin u32 i, reg, timeout = 500;
5837cee23c8SJon Lin void __iomem *mmio = (void __iomem *)0xFE8C0000;
584d0abf46dSJon Lin u32 phy0_status0, phy0_status1, t0 = 0, t1 = 0;
5857cee23c8SJon Lin
5867cee23c8SJon Lin /* Enable phy and controoler clk */
5877cee23c8SJon Lin writel(0xffff0000, PMUCRU_PMUGATE_CON02);
5887cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON12);
5897cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON13);
5907cee23c8SJon Lin writel(0xffff0000, CRU_GATE_CON33);
5917cee23c8SJon Lin writel(0xffff0000, CRU_SOFTRST_CON27);
5927cee23c8SJon Lin
5937cee23c8SJon Lin writel(0x40004000, CRU_SOFTRST_CON27);
5947cee23c8SJon Lin writel(0x80008000, PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9);
5957cee23c8SJon Lin
5967cee23c8SJon Lin writel((0x1 << 15) | (0x1 << 31),
5977cee23c8SJon Lin PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9); //map to access sram
5987cee23c8SJon Lin
5997cee23c8SJon Lin #ifdef PCIE_ENABLE_SRNS_PLL_REFCLK
6007cee23c8SJon Lin /* use internal clock */
6017cee23c8SJon Lin writel(0x0 | (0x1 << 31), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON3);
6027cee23c8SJon Lin
6037cee23c8SJon Lin /* rx0_cmn_refclk_mode disabled */
6047cee23c8SJon Lin writel((0x0) | (0x1 << 25), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON5);
6057cee23c8SJon Lin /* rx1_cmn_refclk_mode disabled */
6067cee23c8SJon Lin writel((0x0) | (0x1 << 25), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON6);
6077cee23c8SJon Lin #endif
6087cee23c8SJon Lin
6097cee23c8SJon Lin writel((0x0 << 14) | (0x1 << (14 + 16)),
6107cee23c8SJon Lin PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON4); //sdram_ld_done
6117cee23c8SJon Lin writel((0x0 << 13) | (0x1 << (13 + 16)),
6127cee23c8SJon Lin PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON4); //sdram_bypass
6137cee23c8SJon Lin
6147cee23c8SJon Lin writel(0x40000000, CRU_SOFTRST_CON27);
6157cee23c8SJon Lin
6167cee23c8SJon Lin udelay(5);
6178269535eSXiao Ya peng printep("RKEP: sram initial\n");
6187cee23c8SJon Lin while (1) {
6197cee23c8SJon Lin reg = readl(PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_STATUS0);
6207cee23c8SJon Lin if (RK3568_SRAM_INIT_DONE(reg))
6217cee23c8SJon Lin break;
6227cee23c8SJon Lin }
6238269535eSXiao Ya peng printep("RKEP: sram init done\n");
6247cee23c8SJon Lin
6257cee23c8SJon Lin writel((0x3 << 8) | (0x3 << (8 + 16)),
6267cee23c8SJon Lin PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9); //map to access sram
6277cee23c8SJon Lin for (i = 0; i < ARRAY_SIZE(phy_fw); i++)
6287cee23c8SJon Lin writel(phy_fw[i], mmio + (i << 2));
6297cee23c8SJon Lin
6308269535eSXiao Ya peng printep("RKEP: snps pcie3phy FW update! size %ld\n", ARRAY_SIZE(phy_fw));
6317cee23c8SJon Lin writel((0x0 << 8) | (0x3 << (8 + 16)),
6327cee23c8SJon Lin PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9);
6337cee23c8SJon Lin writel((0x1 << 14) | (0x1 << (14 + 16)),
6347cee23c8SJon Lin PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON4); //sdram_ld_done
6357cee23c8SJon Lin
6367cee23c8SJon Lin writel(0xffff0000, CRU_SOFTRST_CON12);
6377cee23c8SJon Lin writel(0x100010, PCIE_SNPS_APB_BASE + 0x180);
6387cee23c8SJon Lin
639d0abf46dSJon Lin /* S-Phy: waiting for phy locked */
640d0abf46dSJon Lin for (i = 0; i < timeout; i++) {
641d0abf46dSJon Lin phy0_status0 = readl(PCIE30_PHY_GRF + 0x80);
642d0abf46dSJon Lin phy0_status1 = readl(PCIE30_PHY_GRF + 0x84);
643d0abf46dSJon Lin
644d0abf46dSJon Lin if (phy0_status0 != t0 || phy0_status1 != t1) {
645d0abf46dSJon Lin printep("RKEP: GRF:0x80=%x, 0x84=%x...\n", phy0_status0, phy0_status1);
646d0abf46dSJon Lin
647d0abf46dSJon Lin t0 = phy0_status0;
648d0abf46dSJon Lin t1 = phy0_status1;
649d0abf46dSJon Lin if (RK3568_SRAM_INIT_DONE(phy0_status0))
650d0abf46dSJon Lin break;
651d0abf46dSJon Lin }
652d0abf46dSJon Lin
653d0abf46dSJon Lin udelay(10);
654d0abf46dSJon Lin }
655d0abf46dSJon Lin
656d0abf46dSJon Lin if (i >= timeout) {
657d0abf46dSJon Lin printep("lock fail\n");
658d0abf46dSJon Lin mdelay(1);
659d0abf46dSJon Lin pcie_first_reset();
660d0abf46dSJon Lin }
661d0abf46dSJon Lin
6627cee23c8SJon Lin udelay(1);
6637cee23c8SJon Lin }
664a74e90eeSJon Lin
pcie_firewall_init(void)665a74e90eeSJon Lin static void pcie_firewall_init(void)
666a74e90eeSJon Lin {
667a74e90eeSJon Lin }
6687cee23c8SJon Lin #endif
6697cee23c8SJon Lin
pcie_ep_init(void)6704c8e468bSKever Yang static void pcie_ep_init(void)
6714c8e468bSKever Yang {
6724c8e468bSKever Yang u32 val;
6734c8e468bSKever Yang void *dbi_base = (void *)PCIE_SNPS_DBI_BASE;
6744c8e468bSKever Yang u64 apb_base = PCIE_SNPS_APB_BASE;
67554afed56SJon Lin int i, retries = 0, phy_linkup;
6764c8e468bSKever Yang
6774c8e468bSKever Yang #ifdef PCIE_ENABLE_SRNS_PLL_REFCLK
6784c8e468bSKever Yang printep("RefClock in SRNS clock mode\n");
6794c8e468bSKever Yang #else
6804c8e468bSKever Yang printep("RefClock in common clock_mode\n");
6814c8e468bSKever Yang #endif
6824c8e468bSKever Yang
6834c8e468bSKever Yang /*
6842f33b98fSJon Lin * ltssm_enable enhance mode and enable delaying the link training
6854c8e468bSKever Yang * after Hot Reset
6864c8e468bSKever Yang */
6874c8e468bSKever Yang writel(0x120012, apb_base + 0x180);
6884c8e468bSKever Yang
6892f33b98fSJon Lin /* Unmask pm_turnoff_int */
6902f33b98fSJon Lin writel(0x04000000, apb_base + 0x18);
6912f33b98fSJon Lin
6924c8e468bSKever Yang /* PortLorgic DBI_RO_WR_EN */
6934c8e468bSKever Yang val = readl((dbi_base + 0x8bc));
6944c8e468bSKever Yang val |= 0x1;
6954c8e468bSKever Yang writel(val, dbi_base + 0x8bc);
6964c8e468bSKever Yang
6974c8e468bSKever Yang reinit:
6984c8e468bSKever Yang pcie_bar_init(dbi_base);
6994c8e468bSKever Yang pcie_inbound_config();
7004c8e468bSKever Yang
7014c8e468bSKever Yang /* Device PID, DID */
7024c8e468bSKever Yang writel(0x1d87, dbi_base + 0x00);
7034c8e468bSKever Yang writel(0x356a, dbi_base + 0x02);
7044c8e468bSKever Yang /* Device Class: Processing accelerators */
7054c8e468bSKever Yang writel(0x1200, dbi_base + 0x0a);
7064c8e468bSKever Yang
7072f33b98fSJon Lin pcie_link_set_max_speed(dbi_base, PCI_EXP_LNKCTL2_TLS_8_0GT);
7087cee23c8SJon Lin
7097cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
7102f33b98fSJon Lin pcie_link_set_lanes(dbi_base, 4);
7117cee23c8SJon Lin #elif CONFIG_ROCKCHIP_RK3568
7127cee23c8SJon Lin pcie_link_set_lanes(dbi_base, 2);
7137cee23c8SJon Lin #endif
7142f33b98fSJon Lin
7154c8e468bSKever Yang /* EP mode */
7164c8e468bSKever Yang writel(0xf00000, apb_base);
7174c8e468bSKever Yang udelay(100);
7184c8e468bSKever Yang
719b7b35050SJon Lin val = readl(apb_base + 0x10);
720b7b35050SJon Lin if (val & 0x4) {
721b7b35050SJon Lin printep("Link is reset, int status misc=%x\n", val);
722b7b35050SJon Lin retries++;
723b7b35050SJon Lin }
724b7b35050SJon Lin
7254c8e468bSKever Yang if (retries) /* Set app_dly2_done to enable app_ltssm_enable */
7264c8e468bSKever Yang writel(0x80008, apb_base + 0x180);
7274c8e468bSKever Yang else /* Enable LTSSM */
7284c8e468bSKever Yang writel(0xc000c, apb_base);
7294c8e468bSKever Yang printep("init PCIe fast Link up\n");
7306fa0195bSXiao Ya peng pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_LNKRDY);
7314c8e468bSKever Yang
7324c8e468bSKever Yang /* Waiting for Link up */
733fe857eeaSJon Lin phy_linkup = 0;
7344c8e468bSKever Yang while (1) {
7354c8e468bSKever Yang val = readl(apb_base + 0x300);
73654afed56SJon Lin if (((val & 0x3ffff) & ((0x3 << 16))) == 0x30000)
7374c8e468bSKever Yang break;
73854afed56SJon Lin
73954afed56SJon Lin if (((val & 0x3ffff) & ((0x3 << 16))) == 0x10000)
74054afed56SJon Lin phy_linkup = 1;
74154afed56SJon Lin
74254afed56SJon Lin if (val == 0 && phy_linkup)
74354afed56SJon Lin pcie_first_reset();
74454afed56SJon Lin
74554afed56SJon Lin udelay(10);
7464c8e468bSKever Yang }
7474c8e468bSKever Yang printep("Link up %x\n", val);
7482f33b98fSJon Lin mdelay(3);
7494c8e468bSKever Yang
7504c8e468bSKever Yang /* Wait for link stable */
7514c8e468bSKever Yang for (i = 0; i < 10000; i++) {
7524c8e468bSKever Yang val = readl(apb_base + 0x10);
7534c8e468bSKever Yang if (val & 0x4) {
7544c8e468bSKever Yang writel(0x4, apb_base + 0x10);
7554c8e468bSKever Yang printep("Link is reset, int status misc=%x\n", val);
7564c8e468bSKever Yang if (retries < 3) {
7574c8e468bSKever Yang retries++;
7584c8e468bSKever Yang goto reinit;
7594c8e468bSKever Yang } else {
7604c8e468bSKever Yang break;
7614c8e468bSKever Yang }
7624c8e468bSKever Yang }
76354afed56SJon Lin
76454afed56SJon Lin /* L2 */
76554afed56SJon Lin val = readl(apb_base + 0x4);
76654afed56SJon Lin if (val & 0x400) {
76754afed56SJon Lin writel(0x4, apb_base + 0x10);
76854afed56SJon Lin pcie_first_reset();
76954afed56SJon Lin }
7704c8e468bSKever Yang udelay(1);
7714c8e468bSKever Yang }
7724c8e468bSKever Yang printep("Done\n");
7736fa0195bSXiao Ya peng pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_LNKUP);
7744c8e468bSKever Yang }
7754c8e468bSKever Yang
rockchip_pcie_ep_init(void)7764c8e468bSKever Yang void rockchip_pcie_ep_init(void)
7774c8e468bSKever Yang {
7787cee23c8SJon Lin u32 val;
7797cee23c8SJon Lin
7804c8e468bSKever Yang printf("\nRKEP: Init PCIe EP\n");
7814c8e468bSKever Yang pcie_bar0_header_init();
7824c8e468bSKever Yang
7837cee23c8SJon Lin #ifdef CONFIG_ROCKCHIP_RK3588
7847cee23c8SJon Lin writel(0x1 << 23 | 0x1 << 21, PMU_PWR_GATE_SFTCON1);
7857cee23c8SJon Lin udelay(10);
7867cee23c8SJon Lin #endif
787a74e90eeSJon Lin
788a74e90eeSJon Lin pcie_firewall_init();
7897cee23c8SJon Lin /* Re-in pcie initial */
7907cee23c8SJon Lin val = readl(PCIE_SNPS_APB_BASE + 0x300);
7917cee23c8SJon Lin if (((val & 0x3ffff) & ((0x3 << 16))) == 0x30000) {
7927cee23c8SJon Lin printf("RKEP: already link up\n");
793a74e90eeSJon Lin pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_LNKUP);
7947cee23c8SJon Lin return;
7957cee23c8SJon Lin }
7967cee23c8SJon Lin
7974c8e468bSKever Yang pcie_board_init();
7984c8e468bSKever Yang /* CRU and PHY Init */
7994c8e468bSKever Yang pcie_cru_init();
8004c8e468bSKever Yang
8014c8e468bSKever Yang pcie_ep_init();
8024c8e468bSKever Yang }
803