16e0832faSShawn Lin // SPDX-License-Identifier: GPL-2.0 26e0832faSShawn Lin /* 36e0832faSShawn Lin * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de> 46e0832faSShawn Lin * Copyright (C) 2015 Broadcom Corporation 56e0832faSShawn Lin */ 66e0832faSShawn Lin 76e0832faSShawn Lin #include <linux/kernel.h> 86e0832faSShawn Lin #include <linux/pci.h> 96e0832faSShawn Lin #include <linux/msi.h> 106e0832faSShawn Lin #include <linux/clk.h> 116e0832faSShawn Lin #include <linux/module.h> 126e0832faSShawn Lin #include <linux/mbus.h> 136e0832faSShawn Lin #include <linux/slab.h> 146e0832faSShawn Lin #include <linux/delay.h> 156e0832faSShawn Lin #include <linux/interrupt.h> 166e0832faSShawn Lin #include <linux/irqchip/arm-gic-v3.h> 176e0832faSShawn Lin #include <linux/platform_device.h> 186e0832faSShawn Lin #include <linux/of_address.h> 196e0832faSShawn Lin #include <linux/of_pci.h> 206e0832faSShawn Lin #include <linux/of_irq.h> 216e0832faSShawn Lin #include <linux/of_platform.h> 226e0832faSShawn Lin #include <linux/phy/phy.h> 236e0832faSShawn Lin 246e0832faSShawn Lin #include "pcie-iproc.h" 256e0832faSShawn Lin 266e0832faSShawn Lin #define EP_PERST_SOURCE_SELECT_SHIFT 2 276e0832faSShawn Lin #define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT) 286e0832faSShawn Lin #define EP_MODE_SURVIVE_PERST_SHIFT 1 296e0832faSShawn Lin #define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT) 306e0832faSShawn Lin #define RC_PCIE_RST_OUTPUT_SHIFT 0 316e0832faSShawn Lin #define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT) 326e0832faSShawn Lin #define PAXC_RESET_MASK 0x7f 336e0832faSShawn Lin 346e0832faSShawn Lin #define GIC_V3_CFG_SHIFT 0 356e0832faSShawn Lin #define GIC_V3_CFG BIT(GIC_V3_CFG_SHIFT) 366e0832faSShawn Lin 376e0832faSShawn Lin #define MSI_ENABLE_CFG_SHIFT 0 386e0832faSShawn Lin #define MSI_ENABLE_CFG BIT(MSI_ENABLE_CFG_SHIFT) 396e0832faSShawn Lin 406e0832faSShawn Lin #define CFG_IND_ADDR_MASK 0x00001ffc 416e0832faSShawn Lin 426e0832faSShawn Lin #define CFG_ADDR_BUS_NUM_SHIFT 20 436e0832faSShawn Lin #define CFG_ADDR_BUS_NUM_MASK 0x0ff00000 446e0832faSShawn Lin #define CFG_ADDR_DEV_NUM_SHIFT 15 456e0832faSShawn Lin #define CFG_ADDR_DEV_NUM_MASK 0x000f8000 466e0832faSShawn Lin #define CFG_ADDR_FUNC_NUM_SHIFT 12 476e0832faSShawn Lin #define CFG_ADDR_FUNC_NUM_MASK 0x00007000 486e0832faSShawn Lin #define CFG_ADDR_REG_NUM_SHIFT 2 496e0832faSShawn Lin #define CFG_ADDR_REG_NUM_MASK 0x00000ffc 506e0832faSShawn Lin #define CFG_ADDR_CFG_TYPE_SHIFT 0 516e0832faSShawn Lin #define CFG_ADDR_CFG_TYPE_MASK 0x00000003 526e0832faSShawn Lin 536e0832faSShawn Lin #define SYS_RC_INTX_MASK 0xf 546e0832faSShawn Lin 556e0832faSShawn Lin #define PCIE_PHYLINKUP_SHIFT 3 566e0832faSShawn Lin #define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT) 576e0832faSShawn Lin #define PCIE_DL_ACTIVE_SHIFT 2 586e0832faSShawn Lin #define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT) 596e0832faSShawn Lin 606e0832faSShawn Lin #define APB_ERR_EN_SHIFT 0 616e0832faSShawn Lin #define APB_ERR_EN BIT(APB_ERR_EN_SHIFT) 626e0832faSShawn Lin 636e0832faSShawn Lin #define CFG_RETRY_STATUS 0xffff0001 646e0832faSShawn Lin #define CFG_RETRY_STATUS_TIMEOUT_US 500000 /* 500 milliseconds */ 656e0832faSShawn Lin 666e0832faSShawn Lin /* derive the enum index of the outbound/inbound mapping registers */ 676e0832faSShawn Lin #define MAP_REG(base_reg, index) ((base_reg) + (index) * 2) 686e0832faSShawn Lin 696e0832faSShawn Lin /* 706e0832faSShawn Lin * Maximum number of outbound mapping window sizes that can be supported by any 716e0832faSShawn Lin * OARR/OMAP mapping pair 726e0832faSShawn Lin */ 736e0832faSShawn Lin #define MAX_NUM_OB_WINDOW_SIZES 4 746e0832faSShawn Lin 756e0832faSShawn Lin #define OARR_VALID_SHIFT 0 766e0832faSShawn Lin #define OARR_VALID BIT(OARR_VALID_SHIFT) 776e0832faSShawn Lin #define OARR_SIZE_CFG_SHIFT 1 786e0832faSShawn Lin 796e0832faSShawn Lin /* 806e0832faSShawn Lin * Maximum number of inbound mapping region sizes that can be supported by an 816e0832faSShawn Lin * IARR 826e0832faSShawn Lin */ 836e0832faSShawn Lin #define MAX_NUM_IB_REGION_SIZES 9 846e0832faSShawn Lin 856e0832faSShawn Lin #define IMAP_VALID_SHIFT 0 866e0832faSShawn Lin #define IMAP_VALID BIT(IMAP_VALID_SHIFT) 876e0832faSShawn Lin 886e0832faSShawn Lin #define IPROC_PCI_EXP_CAP 0xac 896e0832faSShawn Lin 906e0832faSShawn Lin #define IPROC_PCIE_REG_INVALID 0xffff 916e0832faSShawn Lin 926e0832faSShawn Lin /** 936e0832faSShawn Lin * iProc PCIe outbound mapping controller specific parameters 946e0832faSShawn Lin * 956e0832faSShawn Lin * @window_sizes: list of supported outbound mapping window sizes in MB 966e0832faSShawn Lin * @nr_sizes: number of supported outbound mapping window sizes 976e0832faSShawn Lin */ 986e0832faSShawn Lin struct iproc_pcie_ob_map { 996e0832faSShawn Lin resource_size_t window_sizes[MAX_NUM_OB_WINDOW_SIZES]; 1006e0832faSShawn Lin unsigned int nr_sizes; 1016e0832faSShawn Lin }; 1026e0832faSShawn Lin 1036e0832faSShawn Lin static const struct iproc_pcie_ob_map paxb_ob_map[] = { 1046e0832faSShawn Lin { 1056e0832faSShawn Lin /* OARR0/OMAP0 */ 1066e0832faSShawn Lin .window_sizes = { 128, 256 }, 1076e0832faSShawn Lin .nr_sizes = 2, 1086e0832faSShawn Lin }, 1096e0832faSShawn Lin { 1106e0832faSShawn Lin /* OARR1/OMAP1 */ 1116e0832faSShawn Lin .window_sizes = { 128, 256 }, 1126e0832faSShawn Lin .nr_sizes = 2, 1136e0832faSShawn Lin }, 1146e0832faSShawn Lin }; 1156e0832faSShawn Lin 1166e0832faSShawn Lin static const struct iproc_pcie_ob_map paxb_v2_ob_map[] = { 1176e0832faSShawn Lin { 1186e0832faSShawn Lin /* OARR0/OMAP0 */ 1196e0832faSShawn Lin .window_sizes = { 128, 256 }, 1206e0832faSShawn Lin .nr_sizes = 2, 1216e0832faSShawn Lin }, 1226e0832faSShawn Lin { 1236e0832faSShawn Lin /* OARR1/OMAP1 */ 1246e0832faSShawn Lin .window_sizes = { 128, 256 }, 1256e0832faSShawn Lin .nr_sizes = 2, 1266e0832faSShawn Lin }, 1276e0832faSShawn Lin { 1286e0832faSShawn Lin /* OARR2/OMAP2 */ 1296e0832faSShawn Lin .window_sizes = { 128, 256, 512, 1024 }, 1306e0832faSShawn Lin .nr_sizes = 4, 1316e0832faSShawn Lin }, 1326e0832faSShawn Lin { 1336e0832faSShawn Lin /* OARR3/OMAP3 */ 1346e0832faSShawn Lin .window_sizes = { 128, 256, 512, 1024 }, 1356e0832faSShawn Lin .nr_sizes = 4, 1366e0832faSShawn Lin }, 1376e0832faSShawn Lin }; 1386e0832faSShawn Lin 1396e0832faSShawn Lin /** 1406e0832faSShawn Lin * iProc PCIe inbound mapping type 1416e0832faSShawn Lin */ 1426e0832faSShawn Lin enum iproc_pcie_ib_map_type { 1436e0832faSShawn Lin /* for DDR memory */ 1446e0832faSShawn Lin IPROC_PCIE_IB_MAP_MEM = 0, 1456e0832faSShawn Lin 1466e0832faSShawn Lin /* for device I/O memory */ 1476e0832faSShawn Lin IPROC_PCIE_IB_MAP_IO, 1486e0832faSShawn Lin 1496e0832faSShawn Lin /* invalid or unused */ 1506e0832faSShawn Lin IPROC_PCIE_IB_MAP_INVALID 1516e0832faSShawn Lin }; 1526e0832faSShawn Lin 1536e0832faSShawn Lin /** 1546e0832faSShawn Lin * iProc PCIe inbound mapping controller specific parameters 1556e0832faSShawn Lin * 1566e0832faSShawn Lin * @type: inbound mapping region type 1576e0832faSShawn Lin * @size_unit: inbound mapping region size unit, could be SZ_1K, SZ_1M, or 1586e0832faSShawn Lin * SZ_1G 1596e0832faSShawn Lin * @region_sizes: list of supported inbound mapping region sizes in KB, MB, or 1606e0832faSShawn Lin * GB, depedning on the size unit 1616e0832faSShawn Lin * @nr_sizes: number of supported inbound mapping region sizes 1626e0832faSShawn Lin * @nr_windows: number of supported inbound mapping windows for the region 1636e0832faSShawn Lin * @imap_addr_offset: register offset between the upper and lower 32-bit 1646e0832faSShawn Lin * IMAP address registers 1656e0832faSShawn Lin * @imap_window_offset: register offset between each IMAP window 1666e0832faSShawn Lin */ 1676e0832faSShawn Lin struct iproc_pcie_ib_map { 1686e0832faSShawn Lin enum iproc_pcie_ib_map_type type; 1696e0832faSShawn Lin unsigned int size_unit; 1706e0832faSShawn Lin resource_size_t region_sizes[MAX_NUM_IB_REGION_SIZES]; 1716e0832faSShawn Lin unsigned int nr_sizes; 1726e0832faSShawn Lin unsigned int nr_windows; 1736e0832faSShawn Lin u16 imap_addr_offset; 1746e0832faSShawn Lin u16 imap_window_offset; 1756e0832faSShawn Lin }; 1766e0832faSShawn Lin 1776e0832faSShawn Lin static const struct iproc_pcie_ib_map paxb_v2_ib_map[] = { 1786e0832faSShawn Lin { 1796e0832faSShawn Lin /* IARR0/IMAP0 */ 1806e0832faSShawn Lin .type = IPROC_PCIE_IB_MAP_IO, 1816e0832faSShawn Lin .size_unit = SZ_1K, 1826e0832faSShawn Lin .region_sizes = { 32 }, 1836e0832faSShawn Lin .nr_sizes = 1, 1846e0832faSShawn Lin .nr_windows = 8, 1856e0832faSShawn Lin .imap_addr_offset = 0x40, 1866e0832faSShawn Lin .imap_window_offset = 0x4, 1876e0832faSShawn Lin }, 1886e0832faSShawn Lin { 1896e0832faSShawn Lin /* IARR1/IMAP1 (currently unused) */ 1906e0832faSShawn Lin .type = IPROC_PCIE_IB_MAP_INVALID, 1916e0832faSShawn Lin }, 1926e0832faSShawn Lin { 1936e0832faSShawn Lin /* IARR2/IMAP2 */ 1946e0832faSShawn Lin .type = IPROC_PCIE_IB_MAP_MEM, 1956e0832faSShawn Lin .size_unit = SZ_1M, 1966e0832faSShawn Lin .region_sizes = { 64, 128, 256, 512, 1024, 2048, 4096, 8192, 1976e0832faSShawn Lin 16384 }, 1986e0832faSShawn Lin .nr_sizes = 9, 1996e0832faSShawn Lin .nr_windows = 1, 2006e0832faSShawn Lin .imap_addr_offset = 0x4, 2016e0832faSShawn Lin .imap_window_offset = 0x8, 2026e0832faSShawn Lin }, 2036e0832faSShawn Lin { 2046e0832faSShawn Lin /* IARR3/IMAP3 */ 2056e0832faSShawn Lin .type = IPROC_PCIE_IB_MAP_MEM, 2066e0832faSShawn Lin .size_unit = SZ_1G, 2076e0832faSShawn Lin .region_sizes = { 1, 2, 4, 8, 16, 32 }, 2086e0832faSShawn Lin .nr_sizes = 6, 2096e0832faSShawn Lin .nr_windows = 8, 2106e0832faSShawn Lin .imap_addr_offset = 0x4, 2116e0832faSShawn Lin .imap_window_offset = 0x8, 2126e0832faSShawn Lin }, 2136e0832faSShawn Lin { 2146e0832faSShawn Lin /* IARR4/IMAP4 */ 2156e0832faSShawn Lin .type = IPROC_PCIE_IB_MAP_MEM, 2166e0832faSShawn Lin .size_unit = SZ_1G, 2176e0832faSShawn Lin .region_sizes = { 32, 64, 128, 256, 512 }, 2186e0832faSShawn Lin .nr_sizes = 5, 2196e0832faSShawn Lin .nr_windows = 8, 2206e0832faSShawn Lin .imap_addr_offset = 0x4, 2216e0832faSShawn Lin .imap_window_offset = 0x8, 2226e0832faSShawn Lin }, 2236e0832faSShawn Lin }; 2246e0832faSShawn Lin 2256e0832faSShawn Lin /* 2266e0832faSShawn Lin * iProc PCIe host registers 2276e0832faSShawn Lin */ 2286e0832faSShawn Lin enum iproc_pcie_reg { 2296e0832faSShawn Lin /* clock/reset signal control */ 2306e0832faSShawn Lin IPROC_PCIE_CLK_CTRL = 0, 2316e0832faSShawn Lin 2326e0832faSShawn Lin /* 2336e0832faSShawn Lin * To allow MSI to be steered to an external MSI controller (e.g., ARM 2346e0832faSShawn Lin * GICv3 ITS) 2356e0832faSShawn Lin */ 2366e0832faSShawn Lin IPROC_PCIE_MSI_GIC_MODE, 2376e0832faSShawn Lin 2386e0832faSShawn Lin /* 2396e0832faSShawn Lin * IPROC_PCIE_MSI_BASE_ADDR and IPROC_PCIE_MSI_WINDOW_SIZE define the 2406e0832faSShawn Lin * window where the MSI posted writes are written, for the writes to be 2416e0832faSShawn Lin * interpreted as MSI writes. 2426e0832faSShawn Lin */ 2436e0832faSShawn Lin IPROC_PCIE_MSI_BASE_ADDR, 2446e0832faSShawn Lin IPROC_PCIE_MSI_WINDOW_SIZE, 2456e0832faSShawn Lin 2466e0832faSShawn Lin /* 2476e0832faSShawn Lin * To hold the address of the register where the MSI writes are 2486e0832faSShawn Lin * programed. When ARM GICv3 ITS is used, this should be programmed 2496e0832faSShawn Lin * with the address of the GITS_TRANSLATER register. 2506e0832faSShawn Lin */ 2516e0832faSShawn Lin IPROC_PCIE_MSI_ADDR_LO, 2526e0832faSShawn Lin IPROC_PCIE_MSI_ADDR_HI, 2536e0832faSShawn Lin 2546e0832faSShawn Lin /* enable MSI */ 2556e0832faSShawn Lin IPROC_PCIE_MSI_EN_CFG, 2566e0832faSShawn Lin 2576e0832faSShawn Lin /* allow access to root complex configuration space */ 2586e0832faSShawn Lin IPROC_PCIE_CFG_IND_ADDR, 2596e0832faSShawn Lin IPROC_PCIE_CFG_IND_DATA, 2606e0832faSShawn Lin 2616e0832faSShawn Lin /* allow access to device configuration space */ 2626e0832faSShawn Lin IPROC_PCIE_CFG_ADDR, 2636e0832faSShawn Lin IPROC_PCIE_CFG_DATA, 2646e0832faSShawn Lin 2656e0832faSShawn Lin /* enable INTx */ 2666e0832faSShawn Lin IPROC_PCIE_INTX_EN, 2676e0832faSShawn Lin 2686e0832faSShawn Lin /* outbound address mapping */ 2696e0832faSShawn Lin IPROC_PCIE_OARR0, 2706e0832faSShawn Lin IPROC_PCIE_OMAP0, 2716e0832faSShawn Lin IPROC_PCIE_OARR1, 2726e0832faSShawn Lin IPROC_PCIE_OMAP1, 2736e0832faSShawn Lin IPROC_PCIE_OARR2, 2746e0832faSShawn Lin IPROC_PCIE_OMAP2, 2756e0832faSShawn Lin IPROC_PCIE_OARR3, 2766e0832faSShawn Lin IPROC_PCIE_OMAP3, 2776e0832faSShawn Lin 2786e0832faSShawn Lin /* inbound address mapping */ 2796e0832faSShawn Lin IPROC_PCIE_IARR0, 2806e0832faSShawn Lin IPROC_PCIE_IMAP0, 2816e0832faSShawn Lin IPROC_PCIE_IARR1, 2826e0832faSShawn Lin IPROC_PCIE_IMAP1, 2836e0832faSShawn Lin IPROC_PCIE_IARR2, 2846e0832faSShawn Lin IPROC_PCIE_IMAP2, 2856e0832faSShawn Lin IPROC_PCIE_IARR3, 2866e0832faSShawn Lin IPROC_PCIE_IMAP3, 2876e0832faSShawn Lin IPROC_PCIE_IARR4, 2886e0832faSShawn Lin IPROC_PCIE_IMAP4, 2896e0832faSShawn Lin 2906e0832faSShawn Lin /* link status */ 2916e0832faSShawn Lin IPROC_PCIE_LINK_STATUS, 2926e0832faSShawn Lin 2936e0832faSShawn Lin /* enable APB error for unsupported requests */ 2946e0832faSShawn Lin IPROC_PCIE_APB_ERR_EN, 2956e0832faSShawn Lin 2966e0832faSShawn Lin /* total number of core registers */ 2976e0832faSShawn Lin IPROC_PCIE_MAX_NUM_REG, 2986e0832faSShawn Lin }; 2996e0832faSShawn Lin 3006e0832faSShawn Lin /* iProc PCIe PAXB BCMA registers */ 3016e0832faSShawn Lin static const u16 iproc_pcie_reg_paxb_bcma[] = { 3026e0832faSShawn Lin [IPROC_PCIE_CLK_CTRL] = 0x000, 3036e0832faSShawn Lin [IPROC_PCIE_CFG_IND_ADDR] = 0x120, 3046e0832faSShawn Lin [IPROC_PCIE_CFG_IND_DATA] = 0x124, 3056e0832faSShawn Lin [IPROC_PCIE_CFG_ADDR] = 0x1f8, 3066e0832faSShawn Lin [IPROC_PCIE_CFG_DATA] = 0x1fc, 3076e0832faSShawn Lin [IPROC_PCIE_INTX_EN] = 0x330, 3086e0832faSShawn Lin [IPROC_PCIE_LINK_STATUS] = 0xf0c, 3096e0832faSShawn Lin }; 3106e0832faSShawn Lin 3116e0832faSShawn Lin /* iProc PCIe PAXB registers */ 3126e0832faSShawn Lin static const u16 iproc_pcie_reg_paxb[] = { 3136e0832faSShawn Lin [IPROC_PCIE_CLK_CTRL] = 0x000, 3146e0832faSShawn Lin [IPROC_PCIE_CFG_IND_ADDR] = 0x120, 3156e0832faSShawn Lin [IPROC_PCIE_CFG_IND_DATA] = 0x124, 3166e0832faSShawn Lin [IPROC_PCIE_CFG_ADDR] = 0x1f8, 3176e0832faSShawn Lin [IPROC_PCIE_CFG_DATA] = 0x1fc, 3186e0832faSShawn Lin [IPROC_PCIE_INTX_EN] = 0x330, 3196e0832faSShawn Lin [IPROC_PCIE_OARR0] = 0xd20, 3206e0832faSShawn Lin [IPROC_PCIE_OMAP0] = 0xd40, 3216e0832faSShawn Lin [IPROC_PCIE_OARR1] = 0xd28, 3226e0832faSShawn Lin [IPROC_PCIE_OMAP1] = 0xd48, 3236e0832faSShawn Lin [IPROC_PCIE_LINK_STATUS] = 0xf0c, 3246e0832faSShawn Lin [IPROC_PCIE_APB_ERR_EN] = 0xf40, 3256e0832faSShawn Lin }; 3266e0832faSShawn Lin 3276e0832faSShawn Lin /* iProc PCIe PAXB v2 registers */ 3286e0832faSShawn Lin static const u16 iproc_pcie_reg_paxb_v2[] = { 3296e0832faSShawn Lin [IPROC_PCIE_CLK_CTRL] = 0x000, 3306e0832faSShawn Lin [IPROC_PCIE_CFG_IND_ADDR] = 0x120, 3316e0832faSShawn Lin [IPROC_PCIE_CFG_IND_DATA] = 0x124, 3326e0832faSShawn Lin [IPROC_PCIE_CFG_ADDR] = 0x1f8, 3336e0832faSShawn Lin [IPROC_PCIE_CFG_DATA] = 0x1fc, 3346e0832faSShawn Lin [IPROC_PCIE_INTX_EN] = 0x330, 3356e0832faSShawn Lin [IPROC_PCIE_OARR0] = 0xd20, 3366e0832faSShawn Lin [IPROC_PCIE_OMAP0] = 0xd40, 3376e0832faSShawn Lin [IPROC_PCIE_OARR1] = 0xd28, 3386e0832faSShawn Lin [IPROC_PCIE_OMAP1] = 0xd48, 3396e0832faSShawn Lin [IPROC_PCIE_OARR2] = 0xd60, 3406e0832faSShawn Lin [IPROC_PCIE_OMAP2] = 0xd68, 3416e0832faSShawn Lin [IPROC_PCIE_OARR3] = 0xdf0, 3426e0832faSShawn Lin [IPROC_PCIE_OMAP3] = 0xdf8, 3436e0832faSShawn Lin [IPROC_PCIE_IARR0] = 0xd00, 3446e0832faSShawn Lin [IPROC_PCIE_IMAP0] = 0xc00, 3456e0832faSShawn Lin [IPROC_PCIE_IARR2] = 0xd10, 3466e0832faSShawn Lin [IPROC_PCIE_IMAP2] = 0xcc0, 3476e0832faSShawn Lin [IPROC_PCIE_IARR3] = 0xe00, 3486e0832faSShawn Lin [IPROC_PCIE_IMAP3] = 0xe08, 3496e0832faSShawn Lin [IPROC_PCIE_IARR4] = 0xe68, 3506e0832faSShawn Lin [IPROC_PCIE_IMAP4] = 0xe70, 3516e0832faSShawn Lin [IPROC_PCIE_LINK_STATUS] = 0xf0c, 3526e0832faSShawn Lin [IPROC_PCIE_APB_ERR_EN] = 0xf40, 3536e0832faSShawn Lin }; 3546e0832faSShawn Lin 3556e0832faSShawn Lin /* iProc PCIe PAXC v1 registers */ 3566e0832faSShawn Lin static const u16 iproc_pcie_reg_paxc[] = { 3576e0832faSShawn Lin [IPROC_PCIE_CLK_CTRL] = 0x000, 3586e0832faSShawn Lin [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, 3596e0832faSShawn Lin [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, 3606e0832faSShawn Lin [IPROC_PCIE_CFG_ADDR] = 0x1f8, 3616e0832faSShawn Lin [IPROC_PCIE_CFG_DATA] = 0x1fc, 3626e0832faSShawn Lin }; 3636e0832faSShawn Lin 3646e0832faSShawn Lin /* iProc PCIe PAXC v2 registers */ 3656e0832faSShawn Lin static const u16 iproc_pcie_reg_paxc_v2[] = { 3666e0832faSShawn Lin [IPROC_PCIE_MSI_GIC_MODE] = 0x050, 3676e0832faSShawn Lin [IPROC_PCIE_MSI_BASE_ADDR] = 0x074, 3686e0832faSShawn Lin [IPROC_PCIE_MSI_WINDOW_SIZE] = 0x078, 3696e0832faSShawn Lin [IPROC_PCIE_MSI_ADDR_LO] = 0x07c, 3706e0832faSShawn Lin [IPROC_PCIE_MSI_ADDR_HI] = 0x080, 3716e0832faSShawn Lin [IPROC_PCIE_MSI_EN_CFG] = 0x09c, 3726e0832faSShawn Lin [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, 3736e0832faSShawn Lin [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, 3746e0832faSShawn Lin [IPROC_PCIE_CFG_ADDR] = 0x1f8, 3756e0832faSShawn Lin [IPROC_PCIE_CFG_DATA] = 0x1fc, 3766e0832faSShawn Lin }; 3776e0832faSShawn Lin 3786e0832faSShawn Lin static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) 3796e0832faSShawn Lin { 3806e0832faSShawn Lin struct iproc_pcie *pcie = bus->sysdata; 3816e0832faSShawn Lin return pcie; 3826e0832faSShawn Lin } 3836e0832faSShawn Lin 3846e0832faSShawn Lin static inline bool iproc_pcie_reg_is_invalid(u16 reg_offset) 3856e0832faSShawn Lin { 3866e0832faSShawn Lin return !!(reg_offset == IPROC_PCIE_REG_INVALID); 3876e0832faSShawn Lin } 3886e0832faSShawn Lin 3896e0832faSShawn Lin static inline u16 iproc_pcie_reg_offset(struct iproc_pcie *pcie, 3906e0832faSShawn Lin enum iproc_pcie_reg reg) 3916e0832faSShawn Lin { 3926e0832faSShawn Lin return pcie->reg_offsets[reg]; 3936e0832faSShawn Lin } 3946e0832faSShawn Lin 3956e0832faSShawn Lin static inline u32 iproc_pcie_read_reg(struct iproc_pcie *pcie, 3966e0832faSShawn Lin enum iproc_pcie_reg reg) 3976e0832faSShawn Lin { 3986e0832faSShawn Lin u16 offset = iproc_pcie_reg_offset(pcie, reg); 3996e0832faSShawn Lin 4006e0832faSShawn Lin if (iproc_pcie_reg_is_invalid(offset)) 4016e0832faSShawn Lin return 0; 4026e0832faSShawn Lin 4036e0832faSShawn Lin return readl(pcie->base + offset); 4046e0832faSShawn Lin } 4056e0832faSShawn Lin 4066e0832faSShawn Lin static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie, 4076e0832faSShawn Lin enum iproc_pcie_reg reg, u32 val) 4086e0832faSShawn Lin { 4096e0832faSShawn Lin u16 offset = iproc_pcie_reg_offset(pcie, reg); 4106e0832faSShawn Lin 4116e0832faSShawn Lin if (iproc_pcie_reg_is_invalid(offset)) 4126e0832faSShawn Lin return; 4136e0832faSShawn Lin 4146e0832faSShawn Lin writel(val, pcie->base + offset); 4156e0832faSShawn Lin } 4166e0832faSShawn Lin 4176e0832faSShawn Lin /** 4186e0832faSShawn Lin * APB error forwarding can be disabled during access of configuration 4196e0832faSShawn Lin * registers of the endpoint device, to prevent unsupported requests 4206e0832faSShawn Lin * (typically seen during enumeration with multi-function devices) from 4216e0832faSShawn Lin * triggering a system exception. 4226e0832faSShawn Lin */ 4236e0832faSShawn Lin static inline void iproc_pcie_apb_err_disable(struct pci_bus *bus, 4246e0832faSShawn Lin bool disable) 4256e0832faSShawn Lin { 4266e0832faSShawn Lin struct iproc_pcie *pcie = iproc_data(bus); 4276e0832faSShawn Lin u32 val; 4286e0832faSShawn Lin 4296e0832faSShawn Lin if (bus->number && pcie->has_apb_err_disable) { 4306e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, IPROC_PCIE_APB_ERR_EN); 4316e0832faSShawn Lin if (disable) 4326e0832faSShawn Lin val &= ~APB_ERR_EN; 4336e0832faSShawn Lin else 4346e0832faSShawn Lin val |= APB_ERR_EN; 4356e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_APB_ERR_EN, val); 4366e0832faSShawn Lin } 4376e0832faSShawn Lin } 4386e0832faSShawn Lin 4396e0832faSShawn Lin static void __iomem *iproc_pcie_map_ep_cfg_reg(struct iproc_pcie *pcie, 4406e0832faSShawn Lin unsigned int busno, 4416e0832faSShawn Lin unsigned int slot, 4426e0832faSShawn Lin unsigned int fn, 4436e0832faSShawn Lin int where) 4446e0832faSShawn Lin { 4456e0832faSShawn Lin u16 offset; 4466e0832faSShawn Lin u32 val; 4476e0832faSShawn Lin 4486e0832faSShawn Lin /* EP device access */ 4496e0832faSShawn Lin val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | 4506e0832faSShawn Lin (slot << CFG_ADDR_DEV_NUM_SHIFT) | 4516e0832faSShawn Lin (fn << CFG_ADDR_FUNC_NUM_SHIFT) | 4526e0832faSShawn Lin (where & CFG_ADDR_REG_NUM_MASK) | 4536e0832faSShawn Lin (1 & CFG_ADDR_CFG_TYPE_MASK); 4546e0832faSShawn Lin 4556e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_ADDR, val); 4566e0832faSShawn Lin offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_DATA); 4576e0832faSShawn Lin 4586e0832faSShawn Lin if (iproc_pcie_reg_is_invalid(offset)) 4596e0832faSShawn Lin return NULL; 4606e0832faSShawn Lin 4616e0832faSShawn Lin return (pcie->base + offset); 4626e0832faSShawn Lin } 4636e0832faSShawn Lin 4646e0832faSShawn Lin static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p) 4656e0832faSShawn Lin { 4666e0832faSShawn Lin int timeout = CFG_RETRY_STATUS_TIMEOUT_US; 4676e0832faSShawn Lin unsigned int data; 4686e0832faSShawn Lin 4696e0832faSShawn Lin /* 4706e0832faSShawn Lin * As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only 4716e0832faSShawn Lin * affects config reads of the Vendor ID. For config writes or any 4726e0832faSShawn Lin * other config reads, the Root may automatically reissue the 4736e0832faSShawn Lin * configuration request again as a new request. 4746e0832faSShawn Lin * 4756e0832faSShawn Lin * For config reads, this hardware returns CFG_RETRY_STATUS data 4766e0832faSShawn Lin * when it receives a CRS completion, regardless of the address of 4776e0832faSShawn Lin * the read or the CRS Software Visibility Enable bit. As a 4786e0832faSShawn Lin * partial workaround for this, we retry in software any read that 4796e0832faSShawn Lin * returns CFG_RETRY_STATUS. 4806e0832faSShawn Lin * 4816e0832faSShawn Lin * Note that a non-Vendor ID config register may have a value of 4826e0832faSShawn Lin * CFG_RETRY_STATUS. If we read that, we can't distinguish it from 4836e0832faSShawn Lin * a CRS completion, so we will incorrectly retry the read and 4846e0832faSShawn Lin * eventually return the wrong data (0xffffffff). 4856e0832faSShawn Lin */ 4866e0832faSShawn Lin data = readl(cfg_data_p); 4876e0832faSShawn Lin while (data == CFG_RETRY_STATUS && timeout--) { 4886e0832faSShawn Lin udelay(1); 4896e0832faSShawn Lin data = readl(cfg_data_p); 4906e0832faSShawn Lin } 4916e0832faSShawn Lin 4926e0832faSShawn Lin if (data == CFG_RETRY_STATUS) 4936e0832faSShawn Lin data = 0xffffffff; 4946e0832faSShawn Lin 4956e0832faSShawn Lin return data; 4966e0832faSShawn Lin } 4976e0832faSShawn Lin 4986e0832faSShawn Lin static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn, 4996e0832faSShawn Lin int where, int size, u32 *val) 5006e0832faSShawn Lin { 5016e0832faSShawn Lin struct iproc_pcie *pcie = iproc_data(bus); 5026e0832faSShawn Lin unsigned int slot = PCI_SLOT(devfn); 5036e0832faSShawn Lin unsigned int fn = PCI_FUNC(devfn); 5046e0832faSShawn Lin unsigned int busno = bus->number; 5056e0832faSShawn Lin void __iomem *cfg_data_p; 5066e0832faSShawn Lin unsigned int data; 5076e0832faSShawn Lin int ret; 5086e0832faSShawn Lin 5096e0832faSShawn Lin /* root complex access */ 5106e0832faSShawn Lin if (busno == 0) { 5116e0832faSShawn Lin ret = pci_generic_config_read32(bus, devfn, where, size, val); 5126e0832faSShawn Lin if (ret != PCIBIOS_SUCCESSFUL) 5136e0832faSShawn Lin return ret; 5146e0832faSShawn Lin 5156e0832faSShawn Lin /* Don't advertise CRS SV support */ 5166e0832faSShawn Lin if ((where & ~0x3) == IPROC_PCI_EXP_CAP + PCI_EXP_RTCTL) 5176e0832faSShawn Lin *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16); 5186e0832faSShawn Lin return PCIBIOS_SUCCESSFUL; 5196e0832faSShawn Lin } 5206e0832faSShawn Lin 5216e0832faSShawn Lin cfg_data_p = iproc_pcie_map_ep_cfg_reg(pcie, busno, slot, fn, where); 5226e0832faSShawn Lin 5236e0832faSShawn Lin if (!cfg_data_p) 5246e0832faSShawn Lin return PCIBIOS_DEVICE_NOT_FOUND; 5256e0832faSShawn Lin 5266e0832faSShawn Lin data = iproc_pcie_cfg_retry(cfg_data_p); 5276e0832faSShawn Lin 5286e0832faSShawn Lin *val = data; 5296e0832faSShawn Lin if (size <= 2) 5306e0832faSShawn Lin *val = (data >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); 5316e0832faSShawn Lin 5326e0832faSShawn Lin return PCIBIOS_SUCCESSFUL; 5336e0832faSShawn Lin } 5346e0832faSShawn Lin 5356e0832faSShawn Lin /** 5366e0832faSShawn Lin * Note access to the configuration registers are protected at the higher layer 5376e0832faSShawn Lin * by 'pci_lock' in drivers/pci/access.c 5386e0832faSShawn Lin */ 5396e0832faSShawn Lin static void __iomem *iproc_pcie_map_cfg_bus(struct iproc_pcie *pcie, 5406e0832faSShawn Lin int busno, unsigned int devfn, 5416e0832faSShawn Lin int where) 5426e0832faSShawn Lin { 5436e0832faSShawn Lin unsigned slot = PCI_SLOT(devfn); 5446e0832faSShawn Lin unsigned fn = PCI_FUNC(devfn); 5456e0832faSShawn Lin u16 offset; 5466e0832faSShawn Lin 5476e0832faSShawn Lin /* root complex access */ 5486e0832faSShawn Lin if (busno == 0) { 5496e0832faSShawn Lin if (slot > 0 || fn > 0) 5506e0832faSShawn Lin return NULL; 5516e0832faSShawn Lin 5526e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR, 5536e0832faSShawn Lin where & CFG_IND_ADDR_MASK); 5546e0832faSShawn Lin offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA); 5556e0832faSShawn Lin if (iproc_pcie_reg_is_invalid(offset)) 5566e0832faSShawn Lin return NULL; 5576e0832faSShawn Lin else 5586e0832faSShawn Lin return (pcie->base + offset); 5596e0832faSShawn Lin } 5606e0832faSShawn Lin 5616e0832faSShawn Lin /* 5626e0832faSShawn Lin * PAXC is connected to an internally emulated EP within the SoC. It 5636e0832faSShawn Lin * allows only one device. 5646e0832faSShawn Lin */ 5656e0832faSShawn Lin if (pcie->ep_is_internal) 5666e0832faSShawn Lin if (slot > 0) 5676e0832faSShawn Lin return NULL; 5686e0832faSShawn Lin 5696e0832faSShawn Lin return iproc_pcie_map_ep_cfg_reg(pcie, busno, slot, fn, where); 5706e0832faSShawn Lin } 5716e0832faSShawn Lin 5726e0832faSShawn Lin static void __iomem *iproc_pcie_bus_map_cfg_bus(struct pci_bus *bus, 5736e0832faSShawn Lin unsigned int devfn, 5746e0832faSShawn Lin int where) 5756e0832faSShawn Lin { 5766e0832faSShawn Lin return iproc_pcie_map_cfg_bus(iproc_data(bus), bus->number, devfn, 5776e0832faSShawn Lin where); 5786e0832faSShawn Lin } 5796e0832faSShawn Lin 5806e0832faSShawn Lin static int iproc_pci_raw_config_read32(struct iproc_pcie *pcie, 5816e0832faSShawn Lin unsigned int devfn, int where, 5826e0832faSShawn Lin int size, u32 *val) 5836e0832faSShawn Lin { 5846e0832faSShawn Lin void __iomem *addr; 5856e0832faSShawn Lin 5866e0832faSShawn Lin addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3); 5876e0832faSShawn Lin if (!addr) { 5886e0832faSShawn Lin *val = ~0; 5896e0832faSShawn Lin return PCIBIOS_DEVICE_NOT_FOUND; 5906e0832faSShawn Lin } 5916e0832faSShawn Lin 5926e0832faSShawn Lin *val = readl(addr); 5936e0832faSShawn Lin 5946e0832faSShawn Lin if (size <= 2) 5956e0832faSShawn Lin *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); 5966e0832faSShawn Lin 5976e0832faSShawn Lin return PCIBIOS_SUCCESSFUL; 5986e0832faSShawn Lin } 5996e0832faSShawn Lin 6006e0832faSShawn Lin static int iproc_pci_raw_config_write32(struct iproc_pcie *pcie, 6016e0832faSShawn Lin unsigned int devfn, int where, 6026e0832faSShawn Lin int size, u32 val) 6036e0832faSShawn Lin { 6046e0832faSShawn Lin void __iomem *addr; 6056e0832faSShawn Lin u32 mask, tmp; 6066e0832faSShawn Lin 6076e0832faSShawn Lin addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3); 6086e0832faSShawn Lin if (!addr) 6096e0832faSShawn Lin return PCIBIOS_DEVICE_NOT_FOUND; 6106e0832faSShawn Lin 6116e0832faSShawn Lin if (size == 4) { 6126e0832faSShawn Lin writel(val, addr); 6136e0832faSShawn Lin return PCIBIOS_SUCCESSFUL; 6146e0832faSShawn Lin } 6156e0832faSShawn Lin 6166e0832faSShawn Lin mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8)); 6176e0832faSShawn Lin tmp = readl(addr) & mask; 6186e0832faSShawn Lin tmp |= val << ((where & 0x3) * 8); 6196e0832faSShawn Lin writel(tmp, addr); 6206e0832faSShawn Lin 6216e0832faSShawn Lin return PCIBIOS_SUCCESSFUL; 6226e0832faSShawn Lin } 6236e0832faSShawn Lin 6246e0832faSShawn Lin static int iproc_pcie_config_read32(struct pci_bus *bus, unsigned int devfn, 6256e0832faSShawn Lin int where, int size, u32 *val) 6266e0832faSShawn Lin { 6276e0832faSShawn Lin int ret; 6286e0832faSShawn Lin struct iproc_pcie *pcie = iproc_data(bus); 6296e0832faSShawn Lin 6306e0832faSShawn Lin iproc_pcie_apb_err_disable(bus, true); 6316e0832faSShawn Lin if (pcie->type == IPROC_PCIE_PAXB_V2) 6326e0832faSShawn Lin ret = iproc_pcie_config_read(bus, devfn, where, size, val); 6336e0832faSShawn Lin else 6346e0832faSShawn Lin ret = pci_generic_config_read32(bus, devfn, where, size, val); 6356e0832faSShawn Lin iproc_pcie_apb_err_disable(bus, false); 6366e0832faSShawn Lin 6376e0832faSShawn Lin return ret; 6386e0832faSShawn Lin } 6396e0832faSShawn Lin 6406e0832faSShawn Lin static int iproc_pcie_config_write32(struct pci_bus *bus, unsigned int devfn, 6416e0832faSShawn Lin int where, int size, u32 val) 6426e0832faSShawn Lin { 6436e0832faSShawn Lin int ret; 6446e0832faSShawn Lin 6456e0832faSShawn Lin iproc_pcie_apb_err_disable(bus, true); 6466e0832faSShawn Lin ret = pci_generic_config_write32(bus, devfn, where, size, val); 6476e0832faSShawn Lin iproc_pcie_apb_err_disable(bus, false); 6486e0832faSShawn Lin 6496e0832faSShawn Lin return ret; 6506e0832faSShawn Lin } 6516e0832faSShawn Lin 6526e0832faSShawn Lin static struct pci_ops iproc_pcie_ops = { 6536e0832faSShawn Lin .map_bus = iproc_pcie_bus_map_cfg_bus, 6546e0832faSShawn Lin .read = iproc_pcie_config_read32, 6556e0832faSShawn Lin .write = iproc_pcie_config_write32, 6566e0832faSShawn Lin }; 6576e0832faSShawn Lin 6586e0832faSShawn Lin static void iproc_pcie_perst_ctrl(struct iproc_pcie *pcie, bool assert) 6596e0832faSShawn Lin { 6606e0832faSShawn Lin u32 val; 6616e0832faSShawn Lin 6626e0832faSShawn Lin /* 6636e0832faSShawn Lin * PAXC and the internal emulated endpoint device downstream should not 6646e0832faSShawn Lin * be reset. If firmware has been loaded on the endpoint device at an 6656e0832faSShawn Lin * earlier boot stage, reset here causes issues. 6666e0832faSShawn Lin */ 6676e0832faSShawn Lin if (pcie->ep_is_internal) 6686e0832faSShawn Lin return; 6696e0832faSShawn Lin 6706e0832faSShawn Lin if (assert) { 6716e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL); 6726e0832faSShawn Lin val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST & 6736e0832faSShawn Lin ~RC_PCIE_RST_OUTPUT; 6746e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); 6756e0832faSShawn Lin udelay(250); 6766e0832faSShawn Lin } else { 6776e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL); 6786e0832faSShawn Lin val |= RC_PCIE_RST_OUTPUT; 6796e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); 6806e0832faSShawn Lin msleep(100); 6816e0832faSShawn Lin } 6826e0832faSShawn Lin } 6836e0832faSShawn Lin 6846e0832faSShawn Lin int iproc_pcie_shutdown(struct iproc_pcie *pcie) 6856e0832faSShawn Lin { 6866e0832faSShawn Lin iproc_pcie_perst_ctrl(pcie, true); 6876e0832faSShawn Lin msleep(500); 6886e0832faSShawn Lin 6896e0832faSShawn Lin return 0; 6906e0832faSShawn Lin } 6916e0832faSShawn Lin EXPORT_SYMBOL_GPL(iproc_pcie_shutdown); 6926e0832faSShawn Lin 6936e0832faSShawn Lin static int iproc_pcie_check_link(struct iproc_pcie *pcie) 6946e0832faSShawn Lin { 6956e0832faSShawn Lin struct device *dev = pcie->dev; 6966e0832faSShawn Lin u32 hdr_type, link_ctrl, link_status, class, val; 6976e0832faSShawn Lin bool link_is_active = false; 6986e0832faSShawn Lin 6996e0832faSShawn Lin /* 7006e0832faSShawn Lin * PAXC connects to emulated endpoint devices directly and does not 7016e0832faSShawn Lin * have a Serdes. Therefore skip the link detection logic here. 7026e0832faSShawn Lin */ 7036e0832faSShawn Lin if (pcie->ep_is_internal) 7046e0832faSShawn Lin return 0; 7056e0832faSShawn Lin 7066e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS); 7076e0832faSShawn Lin if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { 7086e0832faSShawn Lin dev_err(dev, "PHY or data link is INACTIVE!\n"); 7096e0832faSShawn Lin return -ENODEV; 7106e0832faSShawn Lin } 7116e0832faSShawn Lin 7126e0832faSShawn Lin /* make sure we are not in EP mode */ 7136e0832faSShawn Lin iproc_pci_raw_config_read32(pcie, 0, PCI_HEADER_TYPE, 1, &hdr_type); 7146e0832faSShawn Lin if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { 7156e0832faSShawn Lin dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type); 7166e0832faSShawn Lin return -EFAULT; 7176e0832faSShawn Lin } 7186e0832faSShawn Lin 7196e0832faSShawn Lin /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ 7206e0832faSShawn Lin #define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c 7216e0832faSShawn Lin #define PCI_CLASS_BRIDGE_MASK 0xffff00 7226e0832faSShawn Lin #define PCI_CLASS_BRIDGE_SHIFT 8 7236e0832faSShawn Lin iproc_pci_raw_config_read32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET, 7246e0832faSShawn Lin 4, &class); 7256e0832faSShawn Lin class &= ~PCI_CLASS_BRIDGE_MASK; 7266e0832faSShawn Lin class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); 7276e0832faSShawn Lin iproc_pci_raw_config_write32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET, 7286e0832faSShawn Lin 4, class); 7296e0832faSShawn Lin 7306e0832faSShawn Lin /* check link status to see if link is active */ 7316e0832faSShawn Lin iproc_pci_raw_config_read32(pcie, 0, IPROC_PCI_EXP_CAP + PCI_EXP_LNKSTA, 7326e0832faSShawn Lin 2, &link_status); 7336e0832faSShawn Lin if (link_status & PCI_EXP_LNKSTA_NLW) 7346e0832faSShawn Lin link_is_active = true; 7356e0832faSShawn Lin 7366e0832faSShawn Lin if (!link_is_active) { 7376e0832faSShawn Lin /* try GEN 1 link speed */ 7386e0832faSShawn Lin #define PCI_TARGET_LINK_SPEED_MASK 0xf 7396e0832faSShawn Lin #define PCI_TARGET_LINK_SPEED_GEN2 0x2 7406e0832faSShawn Lin #define PCI_TARGET_LINK_SPEED_GEN1 0x1 7416e0832faSShawn Lin iproc_pci_raw_config_read32(pcie, 0, 7426e0832faSShawn Lin IPROC_PCI_EXP_CAP + PCI_EXP_LNKCTL2, 7436e0832faSShawn Lin 4, &link_ctrl); 7446e0832faSShawn Lin if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == 7456e0832faSShawn Lin PCI_TARGET_LINK_SPEED_GEN2) { 7466e0832faSShawn Lin link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; 7476e0832faSShawn Lin link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; 7486e0832faSShawn Lin iproc_pci_raw_config_write32(pcie, 0, 7496e0832faSShawn Lin IPROC_PCI_EXP_CAP + PCI_EXP_LNKCTL2, 7506e0832faSShawn Lin 4, link_ctrl); 7516e0832faSShawn Lin msleep(100); 7526e0832faSShawn Lin 7536e0832faSShawn Lin iproc_pci_raw_config_read32(pcie, 0, 7546e0832faSShawn Lin IPROC_PCI_EXP_CAP + PCI_EXP_LNKSTA, 7556e0832faSShawn Lin 2, &link_status); 7566e0832faSShawn Lin if (link_status & PCI_EXP_LNKSTA_NLW) 7576e0832faSShawn Lin link_is_active = true; 7586e0832faSShawn Lin } 7596e0832faSShawn Lin } 7606e0832faSShawn Lin 7616e0832faSShawn Lin dev_info(dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); 7626e0832faSShawn Lin 7636e0832faSShawn Lin return link_is_active ? 0 : -ENODEV; 7646e0832faSShawn Lin } 7656e0832faSShawn Lin 7666e0832faSShawn Lin static void iproc_pcie_enable(struct iproc_pcie *pcie) 7676e0832faSShawn Lin { 7686e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK); 7696e0832faSShawn Lin } 7706e0832faSShawn Lin 7716e0832faSShawn Lin static inline bool iproc_pcie_ob_is_valid(struct iproc_pcie *pcie, 7726e0832faSShawn Lin int window_idx) 7736e0832faSShawn Lin { 7746e0832faSShawn Lin u32 val; 7756e0832faSShawn Lin 7766e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, MAP_REG(IPROC_PCIE_OARR0, window_idx)); 7776e0832faSShawn Lin 7786e0832faSShawn Lin return !!(val & OARR_VALID); 7796e0832faSShawn Lin } 7806e0832faSShawn Lin 7816e0832faSShawn Lin static inline int iproc_pcie_ob_write(struct iproc_pcie *pcie, int window_idx, 7826e0832faSShawn Lin int size_idx, u64 axi_addr, u64 pci_addr) 7836e0832faSShawn Lin { 7846e0832faSShawn Lin struct device *dev = pcie->dev; 7856e0832faSShawn Lin u16 oarr_offset, omap_offset; 7866e0832faSShawn Lin 7876e0832faSShawn Lin /* 7886e0832faSShawn Lin * Derive the OARR/OMAP offset from the first pair (OARR0/OMAP0) based 7896e0832faSShawn Lin * on window index. 7906e0832faSShawn Lin */ 7916e0832faSShawn Lin oarr_offset = iproc_pcie_reg_offset(pcie, MAP_REG(IPROC_PCIE_OARR0, 7926e0832faSShawn Lin window_idx)); 7936e0832faSShawn Lin omap_offset = iproc_pcie_reg_offset(pcie, MAP_REG(IPROC_PCIE_OMAP0, 7946e0832faSShawn Lin window_idx)); 7956e0832faSShawn Lin if (iproc_pcie_reg_is_invalid(oarr_offset) || 7966e0832faSShawn Lin iproc_pcie_reg_is_invalid(omap_offset)) 7976e0832faSShawn Lin return -EINVAL; 7986e0832faSShawn Lin 7996e0832faSShawn Lin /* 8006e0832faSShawn Lin * Program the OARR registers. The upper 32-bit OARR register is 8016e0832faSShawn Lin * always right after the lower 32-bit OARR register. 8026e0832faSShawn Lin */ 8036e0832faSShawn Lin writel(lower_32_bits(axi_addr) | (size_idx << OARR_SIZE_CFG_SHIFT) | 8046e0832faSShawn Lin OARR_VALID, pcie->base + oarr_offset); 8056e0832faSShawn Lin writel(upper_32_bits(axi_addr), pcie->base + oarr_offset + 4); 8066e0832faSShawn Lin 8076e0832faSShawn Lin /* now program the OMAP registers */ 8086e0832faSShawn Lin writel(lower_32_bits(pci_addr), pcie->base + omap_offset); 8096e0832faSShawn Lin writel(upper_32_bits(pci_addr), pcie->base + omap_offset + 4); 8106e0832faSShawn Lin 8116e0832faSShawn Lin dev_info(dev, "ob window [%d]: offset 0x%x axi %pap pci %pap\n", 8126e0832faSShawn Lin window_idx, oarr_offset, &axi_addr, &pci_addr); 8136e0832faSShawn Lin dev_info(dev, "oarr lo 0x%x oarr hi 0x%x\n", 8146e0832faSShawn Lin readl(pcie->base + oarr_offset), 8156e0832faSShawn Lin readl(pcie->base + oarr_offset + 4)); 8166e0832faSShawn Lin dev_info(dev, "omap lo 0x%x omap hi 0x%x\n", 8176e0832faSShawn Lin readl(pcie->base + omap_offset), 8186e0832faSShawn Lin readl(pcie->base + omap_offset + 4)); 8196e0832faSShawn Lin 8206e0832faSShawn Lin return 0; 8216e0832faSShawn Lin } 8226e0832faSShawn Lin 8236e0832faSShawn Lin /** 8246e0832faSShawn Lin * Some iProc SoCs require the SW to configure the outbound address mapping 8256e0832faSShawn Lin * 8266e0832faSShawn Lin * Outbound address translation: 8276e0832faSShawn Lin * 8286e0832faSShawn Lin * iproc_pcie_address = axi_address - axi_offset 8296e0832faSShawn Lin * OARR = iproc_pcie_address 8306e0832faSShawn Lin * OMAP = pci_addr 8316e0832faSShawn Lin * 8326e0832faSShawn Lin * axi_addr -> iproc_pcie_address -> OARR -> OMAP -> pci_address 8336e0832faSShawn Lin */ 8346e0832faSShawn Lin static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, 8356e0832faSShawn Lin u64 pci_addr, resource_size_t size) 8366e0832faSShawn Lin { 8376e0832faSShawn Lin struct iproc_pcie_ob *ob = &pcie->ob; 8386e0832faSShawn Lin struct device *dev = pcie->dev; 8396e0832faSShawn Lin int ret = -EINVAL, window_idx, size_idx; 8406e0832faSShawn Lin 8416e0832faSShawn Lin if (axi_addr < ob->axi_offset) { 8426e0832faSShawn Lin dev_err(dev, "axi address %pap less than offset %pap\n", 8436e0832faSShawn Lin &axi_addr, &ob->axi_offset); 8446e0832faSShawn Lin return -EINVAL; 8456e0832faSShawn Lin } 8466e0832faSShawn Lin 8476e0832faSShawn Lin /* 8486e0832faSShawn Lin * Translate the AXI address to the internal address used by the iProc 8496e0832faSShawn Lin * PCIe core before programming the OARR 8506e0832faSShawn Lin */ 8516e0832faSShawn Lin axi_addr -= ob->axi_offset; 8526e0832faSShawn Lin 8536e0832faSShawn Lin /* iterate through all OARR/OMAP mapping windows */ 8546e0832faSShawn Lin for (window_idx = ob->nr_windows - 1; window_idx >= 0; window_idx--) { 8556e0832faSShawn Lin const struct iproc_pcie_ob_map *ob_map = 8566e0832faSShawn Lin &pcie->ob_map[window_idx]; 8576e0832faSShawn Lin 8586e0832faSShawn Lin /* 8596e0832faSShawn Lin * If current outbound window is already in use, move on to the 8606e0832faSShawn Lin * next one. 8616e0832faSShawn Lin */ 8626e0832faSShawn Lin if (iproc_pcie_ob_is_valid(pcie, window_idx)) 8636e0832faSShawn Lin continue; 8646e0832faSShawn Lin 8656e0832faSShawn Lin /* 8666e0832faSShawn Lin * Iterate through all supported window sizes within the 8676e0832faSShawn Lin * OARR/OMAP pair to find a match. Go through the window sizes 8686e0832faSShawn Lin * in a descending order. 8696e0832faSShawn Lin */ 8706e0832faSShawn Lin for (size_idx = ob_map->nr_sizes - 1; size_idx >= 0; 8716e0832faSShawn Lin size_idx--) { 8726e0832faSShawn Lin resource_size_t window_size = 8736e0832faSShawn Lin ob_map->window_sizes[size_idx] * SZ_1M; 8746e0832faSShawn Lin 8756e0832faSShawn Lin if (size < window_size) 8766e0832faSShawn Lin continue; 8776e0832faSShawn Lin 8786e0832faSShawn Lin if (!IS_ALIGNED(axi_addr, window_size) || 8796e0832faSShawn Lin !IS_ALIGNED(pci_addr, window_size)) { 8806e0832faSShawn Lin dev_err(dev, 8816e0832faSShawn Lin "axi %pap or pci %pap not aligned\n", 8826e0832faSShawn Lin &axi_addr, &pci_addr); 8836e0832faSShawn Lin return -EINVAL; 8846e0832faSShawn Lin } 8856e0832faSShawn Lin 8866e0832faSShawn Lin /* 8876e0832faSShawn Lin * Match found! Program both OARR and OMAP and mark 8886e0832faSShawn Lin * them as a valid entry. 8896e0832faSShawn Lin */ 8906e0832faSShawn Lin ret = iproc_pcie_ob_write(pcie, window_idx, size_idx, 8916e0832faSShawn Lin axi_addr, pci_addr); 8926e0832faSShawn Lin if (ret) 8936e0832faSShawn Lin goto err_ob; 8946e0832faSShawn Lin 8956e0832faSShawn Lin size -= window_size; 8966e0832faSShawn Lin if (size == 0) 8976e0832faSShawn Lin return 0; 8986e0832faSShawn Lin 8996e0832faSShawn Lin /* 9006e0832faSShawn Lin * If we are here, we are done with the current window, 9016e0832faSShawn Lin * but not yet finished all mappings. Need to move on 9026e0832faSShawn Lin * to the next window. 9036e0832faSShawn Lin */ 9046e0832faSShawn Lin axi_addr += window_size; 9056e0832faSShawn Lin pci_addr += window_size; 9066e0832faSShawn Lin break; 9076e0832faSShawn Lin } 9086e0832faSShawn Lin } 9096e0832faSShawn Lin 9106e0832faSShawn Lin err_ob: 9116e0832faSShawn Lin dev_err(dev, "unable to configure outbound mapping\n"); 9126e0832faSShawn Lin dev_err(dev, 9136e0832faSShawn Lin "axi %pap, axi offset %pap, pci %pap, res size %pap\n", 9146e0832faSShawn Lin &axi_addr, &ob->axi_offset, &pci_addr, &size); 9156e0832faSShawn Lin 9166e0832faSShawn Lin return ret; 9176e0832faSShawn Lin } 9186e0832faSShawn Lin 9196e0832faSShawn Lin static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, 9206e0832faSShawn Lin struct list_head *resources) 9216e0832faSShawn Lin { 9226e0832faSShawn Lin struct device *dev = pcie->dev; 9236e0832faSShawn Lin struct resource_entry *window; 9246e0832faSShawn Lin int ret; 9256e0832faSShawn Lin 9266e0832faSShawn Lin resource_list_for_each_entry(window, resources) { 9276e0832faSShawn Lin struct resource *res = window->res; 9286e0832faSShawn Lin u64 res_type = resource_type(res); 9296e0832faSShawn Lin 9306e0832faSShawn Lin switch (res_type) { 9316e0832faSShawn Lin case IORESOURCE_IO: 9326e0832faSShawn Lin case IORESOURCE_BUS: 9336e0832faSShawn Lin break; 9346e0832faSShawn Lin case IORESOURCE_MEM: 9356e0832faSShawn Lin ret = iproc_pcie_setup_ob(pcie, res->start, 9366e0832faSShawn Lin res->start - window->offset, 9376e0832faSShawn Lin resource_size(res)); 9386e0832faSShawn Lin if (ret) 9396e0832faSShawn Lin return ret; 9406e0832faSShawn Lin break; 9416e0832faSShawn Lin default: 9426e0832faSShawn Lin dev_err(dev, "invalid resource %pR\n", res); 9436e0832faSShawn Lin return -EINVAL; 9446e0832faSShawn Lin } 9456e0832faSShawn Lin } 9466e0832faSShawn Lin 9476e0832faSShawn Lin return 0; 9486e0832faSShawn Lin } 9496e0832faSShawn Lin 9506e0832faSShawn Lin static inline bool iproc_pcie_ib_is_in_use(struct iproc_pcie *pcie, 9516e0832faSShawn Lin int region_idx) 9526e0832faSShawn Lin { 9536e0832faSShawn Lin const struct iproc_pcie_ib_map *ib_map = &pcie->ib_map[region_idx]; 9546e0832faSShawn Lin u32 val; 9556e0832faSShawn Lin 9566e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, MAP_REG(IPROC_PCIE_IARR0, region_idx)); 9576e0832faSShawn Lin 9586e0832faSShawn Lin return !!(val & (BIT(ib_map->nr_sizes) - 1)); 9596e0832faSShawn Lin } 9606e0832faSShawn Lin 9616e0832faSShawn Lin static inline bool iproc_pcie_ib_check_type(const struct iproc_pcie_ib_map *ib_map, 9626e0832faSShawn Lin enum iproc_pcie_ib_map_type type) 9636e0832faSShawn Lin { 9646e0832faSShawn Lin return !!(ib_map->type == type); 9656e0832faSShawn Lin } 9666e0832faSShawn Lin 9676e0832faSShawn Lin static int iproc_pcie_ib_write(struct iproc_pcie *pcie, int region_idx, 9686e0832faSShawn Lin int size_idx, int nr_windows, u64 axi_addr, 9696e0832faSShawn Lin u64 pci_addr, resource_size_t size) 9706e0832faSShawn Lin { 9716e0832faSShawn Lin struct device *dev = pcie->dev; 9726e0832faSShawn Lin const struct iproc_pcie_ib_map *ib_map = &pcie->ib_map[region_idx]; 9736e0832faSShawn Lin u16 iarr_offset, imap_offset; 9746e0832faSShawn Lin u32 val; 9756e0832faSShawn Lin int window_idx; 9766e0832faSShawn Lin 9776e0832faSShawn Lin iarr_offset = iproc_pcie_reg_offset(pcie, 9786e0832faSShawn Lin MAP_REG(IPROC_PCIE_IARR0, region_idx)); 9796e0832faSShawn Lin imap_offset = iproc_pcie_reg_offset(pcie, 9806e0832faSShawn Lin MAP_REG(IPROC_PCIE_IMAP0, region_idx)); 9816e0832faSShawn Lin if (iproc_pcie_reg_is_invalid(iarr_offset) || 9826e0832faSShawn Lin iproc_pcie_reg_is_invalid(imap_offset)) 9836e0832faSShawn Lin return -EINVAL; 9846e0832faSShawn Lin 9856e0832faSShawn Lin dev_info(dev, "ib region [%d]: offset 0x%x axi %pap pci %pap\n", 9866e0832faSShawn Lin region_idx, iarr_offset, &axi_addr, &pci_addr); 9876e0832faSShawn Lin 9886e0832faSShawn Lin /* 9896e0832faSShawn Lin * Program the IARR registers. The upper 32-bit IARR register is 9906e0832faSShawn Lin * always right after the lower 32-bit IARR register. 9916e0832faSShawn Lin */ 9926e0832faSShawn Lin writel(lower_32_bits(pci_addr) | BIT(size_idx), 9936e0832faSShawn Lin pcie->base + iarr_offset); 9946e0832faSShawn Lin writel(upper_32_bits(pci_addr), pcie->base + iarr_offset + 4); 9956e0832faSShawn Lin 9966e0832faSShawn Lin dev_info(dev, "iarr lo 0x%x iarr hi 0x%x\n", 9976e0832faSShawn Lin readl(pcie->base + iarr_offset), 9986e0832faSShawn Lin readl(pcie->base + iarr_offset + 4)); 9996e0832faSShawn Lin 10006e0832faSShawn Lin /* 10016e0832faSShawn Lin * Now program the IMAP registers. Each IARR region may have one or 10026e0832faSShawn Lin * more IMAP windows. 10036e0832faSShawn Lin */ 10046e0832faSShawn Lin size >>= ilog2(nr_windows); 10056e0832faSShawn Lin for (window_idx = 0; window_idx < nr_windows; window_idx++) { 10066e0832faSShawn Lin val = readl(pcie->base + imap_offset); 10076e0832faSShawn Lin val |= lower_32_bits(axi_addr) | IMAP_VALID; 10086e0832faSShawn Lin writel(val, pcie->base + imap_offset); 10096e0832faSShawn Lin writel(upper_32_bits(axi_addr), 10106e0832faSShawn Lin pcie->base + imap_offset + ib_map->imap_addr_offset); 10116e0832faSShawn Lin 10126e0832faSShawn Lin dev_info(dev, "imap window [%d] lo 0x%x hi 0x%x\n", 10136e0832faSShawn Lin window_idx, readl(pcie->base + imap_offset), 10146e0832faSShawn Lin readl(pcie->base + imap_offset + 10156e0832faSShawn Lin ib_map->imap_addr_offset)); 10166e0832faSShawn Lin 10176e0832faSShawn Lin imap_offset += ib_map->imap_window_offset; 10186e0832faSShawn Lin axi_addr += size; 10196e0832faSShawn Lin } 10206e0832faSShawn Lin 10216e0832faSShawn Lin return 0; 10226e0832faSShawn Lin } 10236e0832faSShawn Lin 10246e0832faSShawn Lin static int iproc_pcie_setup_ib(struct iproc_pcie *pcie, 10256e0832faSShawn Lin struct of_pci_range *range, 10266e0832faSShawn Lin enum iproc_pcie_ib_map_type type) 10276e0832faSShawn Lin { 10286e0832faSShawn Lin struct device *dev = pcie->dev; 10296e0832faSShawn Lin struct iproc_pcie_ib *ib = &pcie->ib; 10306e0832faSShawn Lin int ret; 10316e0832faSShawn Lin unsigned int region_idx, size_idx; 10326e0832faSShawn Lin u64 axi_addr = range->cpu_addr, pci_addr = range->pci_addr; 10336e0832faSShawn Lin resource_size_t size = range->size; 10346e0832faSShawn Lin 10356e0832faSShawn Lin /* iterate through all IARR mapping regions */ 10366e0832faSShawn Lin for (region_idx = 0; region_idx < ib->nr_regions; region_idx++) { 10376e0832faSShawn Lin const struct iproc_pcie_ib_map *ib_map = 10386e0832faSShawn Lin &pcie->ib_map[region_idx]; 10396e0832faSShawn Lin 10406e0832faSShawn Lin /* 10416e0832faSShawn Lin * If current inbound region is already in use or not a 10426e0832faSShawn Lin * compatible type, move on to the next. 10436e0832faSShawn Lin */ 10446e0832faSShawn Lin if (iproc_pcie_ib_is_in_use(pcie, region_idx) || 10456e0832faSShawn Lin !iproc_pcie_ib_check_type(ib_map, type)) 10466e0832faSShawn Lin continue; 10476e0832faSShawn Lin 10486e0832faSShawn Lin /* iterate through all supported region sizes to find a match */ 10496e0832faSShawn Lin for (size_idx = 0; size_idx < ib_map->nr_sizes; size_idx++) { 10506e0832faSShawn Lin resource_size_t region_size = 10516e0832faSShawn Lin ib_map->region_sizes[size_idx] * ib_map->size_unit; 10526e0832faSShawn Lin 10536e0832faSShawn Lin if (size != region_size) 10546e0832faSShawn Lin continue; 10556e0832faSShawn Lin 10566e0832faSShawn Lin if (!IS_ALIGNED(axi_addr, region_size) || 10576e0832faSShawn Lin !IS_ALIGNED(pci_addr, region_size)) { 10586e0832faSShawn Lin dev_err(dev, 10596e0832faSShawn Lin "axi %pap or pci %pap not aligned\n", 10606e0832faSShawn Lin &axi_addr, &pci_addr); 10616e0832faSShawn Lin return -EINVAL; 10626e0832faSShawn Lin } 10636e0832faSShawn Lin 10646e0832faSShawn Lin /* Match found! Program IARR and all IMAP windows. */ 10656e0832faSShawn Lin ret = iproc_pcie_ib_write(pcie, region_idx, size_idx, 10666e0832faSShawn Lin ib_map->nr_windows, axi_addr, 10676e0832faSShawn Lin pci_addr, size); 10686e0832faSShawn Lin if (ret) 10696e0832faSShawn Lin goto err_ib; 10706e0832faSShawn Lin else 10716e0832faSShawn Lin return 0; 10726e0832faSShawn Lin 10736e0832faSShawn Lin } 10746e0832faSShawn Lin } 10756e0832faSShawn Lin ret = -EINVAL; 10766e0832faSShawn Lin 10776e0832faSShawn Lin err_ib: 10786e0832faSShawn Lin dev_err(dev, "unable to configure inbound mapping\n"); 10796e0832faSShawn Lin dev_err(dev, "axi %pap, pci %pap, res size %pap\n", 10806e0832faSShawn Lin &axi_addr, &pci_addr, &size); 10816e0832faSShawn Lin 10826e0832faSShawn Lin return ret; 10836e0832faSShawn Lin } 10846e0832faSShawn Lin 10856e0832faSShawn Lin static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie) 10866e0832faSShawn Lin { 10876e0832faSShawn Lin struct of_pci_range range; 10886e0832faSShawn Lin struct of_pci_range_parser parser; 10896e0832faSShawn Lin int ret; 10906e0832faSShawn Lin 10916e0832faSShawn Lin /* Get the dma-ranges from DT */ 10926e0832faSShawn Lin ret = of_pci_dma_range_parser_init(&parser, pcie->dev->of_node); 10936e0832faSShawn Lin if (ret) 10946e0832faSShawn Lin return ret; 10956e0832faSShawn Lin 10966e0832faSShawn Lin for_each_of_pci_range(&parser, &range) { 10976e0832faSShawn Lin /* Each range entry corresponds to an inbound mapping region */ 10986e0832faSShawn Lin ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM); 10996e0832faSShawn Lin if (ret) 11006e0832faSShawn Lin return ret; 11016e0832faSShawn Lin } 11026e0832faSShawn Lin 11036e0832faSShawn Lin return 0; 11046e0832faSShawn Lin } 11056e0832faSShawn Lin 11066e0832faSShawn Lin static int iproce_pcie_get_msi(struct iproc_pcie *pcie, 11076e0832faSShawn Lin struct device_node *msi_node, 11086e0832faSShawn Lin u64 *msi_addr) 11096e0832faSShawn Lin { 11106e0832faSShawn Lin struct device *dev = pcie->dev; 11116e0832faSShawn Lin int ret; 11126e0832faSShawn Lin struct resource res; 11136e0832faSShawn Lin 11146e0832faSShawn Lin /* 11156e0832faSShawn Lin * Check if 'msi-map' points to ARM GICv3 ITS, which is the only 11166e0832faSShawn Lin * supported external MSI controller that requires steering. 11176e0832faSShawn Lin */ 11186e0832faSShawn Lin if (!of_device_is_compatible(msi_node, "arm,gic-v3-its")) { 11196e0832faSShawn Lin dev_err(dev, "unable to find compatible MSI controller\n"); 11206e0832faSShawn Lin return -ENODEV; 11216e0832faSShawn Lin } 11226e0832faSShawn Lin 11236e0832faSShawn Lin /* derive GITS_TRANSLATER address from GICv3 */ 11246e0832faSShawn Lin ret = of_address_to_resource(msi_node, 0, &res); 11256e0832faSShawn Lin if (ret < 0) { 11266e0832faSShawn Lin dev_err(dev, "unable to obtain MSI controller resources\n"); 11276e0832faSShawn Lin return ret; 11286e0832faSShawn Lin } 11296e0832faSShawn Lin 11306e0832faSShawn Lin *msi_addr = res.start + GITS_TRANSLATER; 11316e0832faSShawn Lin return 0; 11326e0832faSShawn Lin } 11336e0832faSShawn Lin 11346e0832faSShawn Lin static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) 11356e0832faSShawn Lin { 11366e0832faSShawn Lin int ret; 11376e0832faSShawn Lin struct of_pci_range range; 11386e0832faSShawn Lin 11396e0832faSShawn Lin memset(&range, 0, sizeof(range)); 11406e0832faSShawn Lin range.size = SZ_32K; 11416e0832faSShawn Lin range.pci_addr = range.cpu_addr = msi_addr & ~(range.size - 1); 11426e0832faSShawn Lin 11436e0832faSShawn Lin ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_IO); 11446e0832faSShawn Lin return ret; 11456e0832faSShawn Lin } 11466e0832faSShawn Lin 11476e0832faSShawn Lin static void iproc_pcie_paxc_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) 11486e0832faSShawn Lin { 11496e0832faSShawn Lin u32 val; 11506e0832faSShawn Lin 11516e0832faSShawn Lin /* 11526e0832faSShawn Lin * Program bits [43:13] of address of GITS_TRANSLATER register into 11536e0832faSShawn Lin * bits [30:0] of the MSI base address register. In fact, in all iProc 11546e0832faSShawn Lin * based SoCs, all I/O register bases are well below the 32-bit 11556e0832faSShawn Lin * boundary, so we can safely assume bits [43:32] are always zeros. 11566e0832faSShawn Lin */ 11576e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_BASE_ADDR, 11586e0832faSShawn Lin (u32)(msi_addr >> 13)); 11596e0832faSShawn Lin 11606e0832faSShawn Lin /* use a default 8K window size */ 11616e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_WINDOW_SIZE, 0); 11626e0832faSShawn Lin 11636e0832faSShawn Lin /* steering MSI to GICv3 ITS */ 11646e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, IPROC_PCIE_MSI_GIC_MODE); 11656e0832faSShawn Lin val |= GIC_V3_CFG; 11666e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_GIC_MODE, val); 11676e0832faSShawn Lin 11686e0832faSShawn Lin /* 11696e0832faSShawn Lin * Program bits [43:2] of address of GITS_TRANSLATER register into the 11706e0832faSShawn Lin * iProc MSI address registers. 11716e0832faSShawn Lin */ 11726e0832faSShawn Lin msi_addr >>= 2; 11736e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_ADDR_HI, 11746e0832faSShawn Lin upper_32_bits(msi_addr)); 11756e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_ADDR_LO, 11766e0832faSShawn Lin lower_32_bits(msi_addr)); 11776e0832faSShawn Lin 11786e0832faSShawn Lin /* enable MSI */ 11796e0832faSShawn Lin val = iproc_pcie_read_reg(pcie, IPROC_PCIE_MSI_EN_CFG); 11806e0832faSShawn Lin val |= MSI_ENABLE_CFG; 11816e0832faSShawn Lin iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_EN_CFG, val); 11826e0832faSShawn Lin } 11836e0832faSShawn Lin 11846e0832faSShawn Lin static int iproc_pcie_msi_steer(struct iproc_pcie *pcie, 11856e0832faSShawn Lin struct device_node *msi_node) 11866e0832faSShawn Lin { 11876e0832faSShawn Lin struct device *dev = pcie->dev; 11886e0832faSShawn Lin int ret; 11896e0832faSShawn Lin u64 msi_addr; 11906e0832faSShawn Lin 11916e0832faSShawn Lin ret = iproce_pcie_get_msi(pcie, msi_node, &msi_addr); 11926e0832faSShawn Lin if (ret < 0) { 11936e0832faSShawn Lin dev_err(dev, "msi steering failed\n"); 11946e0832faSShawn Lin return ret; 11956e0832faSShawn Lin } 11966e0832faSShawn Lin 11976e0832faSShawn Lin switch (pcie->type) { 11986e0832faSShawn Lin case IPROC_PCIE_PAXB_V2: 11996e0832faSShawn Lin ret = iproc_pcie_paxb_v2_msi_steer(pcie, msi_addr); 12006e0832faSShawn Lin if (ret) 12016e0832faSShawn Lin return ret; 12026e0832faSShawn Lin break; 12036e0832faSShawn Lin case IPROC_PCIE_PAXC_V2: 12046e0832faSShawn Lin iproc_pcie_paxc_v2_msi_steer(pcie, msi_addr); 12056e0832faSShawn Lin break; 12066e0832faSShawn Lin default: 12076e0832faSShawn Lin return -EINVAL; 12086e0832faSShawn Lin } 12096e0832faSShawn Lin 12106e0832faSShawn Lin return 0; 12116e0832faSShawn Lin } 12126e0832faSShawn Lin 12136e0832faSShawn Lin static int iproc_pcie_msi_enable(struct iproc_pcie *pcie) 12146e0832faSShawn Lin { 12156e0832faSShawn Lin struct device_node *msi_node; 12166e0832faSShawn Lin int ret; 12176e0832faSShawn Lin 12186e0832faSShawn Lin /* 12196e0832faSShawn Lin * Either the "msi-parent" or the "msi-map" phandle needs to exist 12206e0832faSShawn Lin * for us to obtain the MSI node. 12216e0832faSShawn Lin */ 12226e0832faSShawn Lin 12236e0832faSShawn Lin msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); 12246e0832faSShawn Lin if (!msi_node) { 12256e0832faSShawn Lin const __be32 *msi_map = NULL; 12266e0832faSShawn Lin int len; 12276e0832faSShawn Lin u32 phandle; 12286e0832faSShawn Lin 12296e0832faSShawn Lin msi_map = of_get_property(pcie->dev->of_node, "msi-map", &len); 12306e0832faSShawn Lin if (!msi_map) 12316e0832faSShawn Lin return -ENODEV; 12326e0832faSShawn Lin 12336e0832faSShawn Lin phandle = be32_to_cpup(msi_map + 1); 12346e0832faSShawn Lin msi_node = of_find_node_by_phandle(phandle); 12356e0832faSShawn Lin if (!msi_node) 12366e0832faSShawn Lin return -ENODEV; 12376e0832faSShawn Lin } 12386e0832faSShawn Lin 12396e0832faSShawn Lin /* 12406e0832faSShawn Lin * Certain revisions of the iProc PCIe controller require additional 12416e0832faSShawn Lin * configurations to steer the MSI writes towards an external MSI 12426e0832faSShawn Lin * controller. 12436e0832faSShawn Lin */ 12446e0832faSShawn Lin if (pcie->need_msi_steer) { 12456e0832faSShawn Lin ret = iproc_pcie_msi_steer(pcie, msi_node); 12466e0832faSShawn Lin if (ret) 12476e0832faSShawn Lin return ret; 12486e0832faSShawn Lin } 12496e0832faSShawn Lin 12506e0832faSShawn Lin /* 12516e0832faSShawn Lin * If another MSI controller is being used, the call below should fail 12526e0832faSShawn Lin * but that is okay 12536e0832faSShawn Lin */ 12546e0832faSShawn Lin return iproc_msi_init(pcie, msi_node); 12556e0832faSShawn Lin } 12566e0832faSShawn Lin 12576e0832faSShawn Lin static void iproc_pcie_msi_disable(struct iproc_pcie *pcie) 12586e0832faSShawn Lin { 12596e0832faSShawn Lin iproc_msi_exit(pcie); 12606e0832faSShawn Lin } 12616e0832faSShawn Lin 12626e0832faSShawn Lin static int iproc_pcie_rev_init(struct iproc_pcie *pcie) 12636e0832faSShawn Lin { 12646e0832faSShawn Lin struct device *dev = pcie->dev; 12656e0832faSShawn Lin unsigned int reg_idx; 12666e0832faSShawn Lin const u16 *regs; 12676e0832faSShawn Lin 12686e0832faSShawn Lin switch (pcie->type) { 12696e0832faSShawn Lin case IPROC_PCIE_PAXB_BCMA: 12706e0832faSShawn Lin regs = iproc_pcie_reg_paxb_bcma; 12716e0832faSShawn Lin break; 12726e0832faSShawn Lin case IPROC_PCIE_PAXB: 12736e0832faSShawn Lin regs = iproc_pcie_reg_paxb; 12746e0832faSShawn Lin pcie->has_apb_err_disable = true; 12756e0832faSShawn Lin if (pcie->need_ob_cfg) { 12766e0832faSShawn Lin pcie->ob_map = paxb_ob_map; 12776e0832faSShawn Lin pcie->ob.nr_windows = ARRAY_SIZE(paxb_ob_map); 12786e0832faSShawn Lin } 12796e0832faSShawn Lin break; 12806e0832faSShawn Lin case IPROC_PCIE_PAXB_V2: 12816e0832faSShawn Lin regs = iproc_pcie_reg_paxb_v2; 12826e0832faSShawn Lin pcie->has_apb_err_disable = true; 12836e0832faSShawn Lin if (pcie->need_ob_cfg) { 12846e0832faSShawn Lin pcie->ob_map = paxb_v2_ob_map; 12856e0832faSShawn Lin pcie->ob.nr_windows = ARRAY_SIZE(paxb_v2_ob_map); 12866e0832faSShawn Lin } 12876e0832faSShawn Lin pcie->ib.nr_regions = ARRAY_SIZE(paxb_v2_ib_map); 12886e0832faSShawn Lin pcie->ib_map = paxb_v2_ib_map; 12896e0832faSShawn Lin pcie->need_msi_steer = true; 12906e0832faSShawn Lin dev_warn(dev, "reads of config registers that contain %#x return incorrect data\n", 12916e0832faSShawn Lin CFG_RETRY_STATUS); 12926e0832faSShawn Lin break; 12936e0832faSShawn Lin case IPROC_PCIE_PAXC: 12946e0832faSShawn Lin regs = iproc_pcie_reg_paxc; 12956e0832faSShawn Lin pcie->ep_is_internal = true; 12966e0832faSShawn Lin break; 12976e0832faSShawn Lin case IPROC_PCIE_PAXC_V2: 12986e0832faSShawn Lin regs = iproc_pcie_reg_paxc_v2; 12996e0832faSShawn Lin pcie->ep_is_internal = true; 13006e0832faSShawn Lin pcie->need_msi_steer = true; 13016e0832faSShawn Lin break; 13026e0832faSShawn Lin default: 13036e0832faSShawn Lin dev_err(dev, "incompatible iProc PCIe interface\n"); 13046e0832faSShawn Lin return -EINVAL; 13056e0832faSShawn Lin } 13066e0832faSShawn Lin 13076e0832faSShawn Lin pcie->reg_offsets = devm_kcalloc(dev, IPROC_PCIE_MAX_NUM_REG, 13086e0832faSShawn Lin sizeof(*pcie->reg_offsets), 13096e0832faSShawn Lin GFP_KERNEL); 13106e0832faSShawn Lin if (!pcie->reg_offsets) 13116e0832faSShawn Lin return -ENOMEM; 13126e0832faSShawn Lin 13136e0832faSShawn Lin /* go through the register table and populate all valid registers */ 13146e0832faSShawn Lin pcie->reg_offsets[0] = (pcie->type == IPROC_PCIE_PAXC_V2) ? 13156e0832faSShawn Lin IPROC_PCIE_REG_INVALID : regs[0]; 13166e0832faSShawn Lin for (reg_idx = 1; reg_idx < IPROC_PCIE_MAX_NUM_REG; reg_idx++) 13176e0832faSShawn Lin pcie->reg_offsets[reg_idx] = regs[reg_idx] ? 13186e0832faSShawn Lin regs[reg_idx] : IPROC_PCIE_REG_INVALID; 13196e0832faSShawn Lin 13206e0832faSShawn Lin return 0; 13216e0832faSShawn Lin } 13226e0832faSShawn Lin 13236e0832faSShawn Lin int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) 13246e0832faSShawn Lin { 13256e0832faSShawn Lin struct device *dev; 13266e0832faSShawn Lin int ret; 13276e0832faSShawn Lin struct pci_bus *child; 13286e0832faSShawn Lin struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); 13296e0832faSShawn Lin 13306e0832faSShawn Lin dev = pcie->dev; 13316e0832faSShawn Lin 13326e0832faSShawn Lin ret = iproc_pcie_rev_init(pcie); 13336e0832faSShawn Lin if (ret) { 13346e0832faSShawn Lin dev_err(dev, "unable to initialize controller parameters\n"); 13356e0832faSShawn Lin return ret; 13366e0832faSShawn Lin } 13376e0832faSShawn Lin 13386e0832faSShawn Lin ret = devm_request_pci_bus_resources(dev, res); 13396e0832faSShawn Lin if (ret) 13406e0832faSShawn Lin return ret; 13416e0832faSShawn Lin 13426e0832faSShawn Lin ret = phy_init(pcie->phy); 13436e0832faSShawn Lin if (ret) { 13446e0832faSShawn Lin dev_err(dev, "unable to initialize PCIe PHY\n"); 13456e0832faSShawn Lin return ret; 13466e0832faSShawn Lin } 13476e0832faSShawn Lin 13486e0832faSShawn Lin ret = phy_power_on(pcie->phy); 13496e0832faSShawn Lin if (ret) { 13506e0832faSShawn Lin dev_err(dev, "unable to power on PCIe PHY\n"); 13516e0832faSShawn Lin goto err_exit_phy; 13526e0832faSShawn Lin } 13536e0832faSShawn Lin 13546e0832faSShawn Lin iproc_pcie_perst_ctrl(pcie, true); 13556e0832faSShawn Lin iproc_pcie_perst_ctrl(pcie, false); 13566e0832faSShawn Lin 13576e0832faSShawn Lin if (pcie->need_ob_cfg) { 13586e0832faSShawn Lin ret = iproc_pcie_map_ranges(pcie, res); 13596e0832faSShawn Lin if (ret) { 13606e0832faSShawn Lin dev_err(dev, "map failed\n"); 13616e0832faSShawn Lin goto err_power_off_phy; 13626e0832faSShawn Lin } 13636e0832faSShawn Lin } 13646e0832faSShawn Lin 13656e0832faSShawn Lin if (pcie->need_ib_cfg) { 13666e0832faSShawn Lin ret = iproc_pcie_map_dma_ranges(pcie); 13676e0832faSShawn Lin if (ret && ret != -ENOENT) 13686e0832faSShawn Lin goto err_power_off_phy; 13696e0832faSShawn Lin } 13706e0832faSShawn Lin 13716e0832faSShawn Lin ret = iproc_pcie_check_link(pcie); 13726e0832faSShawn Lin if (ret) { 13736e0832faSShawn Lin dev_err(dev, "no PCIe EP device detected\n"); 13746e0832faSShawn Lin goto err_power_off_phy; 13756e0832faSShawn Lin } 13766e0832faSShawn Lin 13776e0832faSShawn Lin iproc_pcie_enable(pcie); 13786e0832faSShawn Lin 13796e0832faSShawn Lin if (IS_ENABLED(CONFIG_PCI_MSI)) 13806e0832faSShawn Lin if (iproc_pcie_msi_enable(pcie)) 13816e0832faSShawn Lin dev_info(dev, "not using iProc MSI\n"); 13826e0832faSShawn Lin 13836e0832faSShawn Lin list_splice_init(res, &host->windows); 13846e0832faSShawn Lin host->busnr = 0; 13856e0832faSShawn Lin host->dev.parent = dev; 13866e0832faSShawn Lin host->ops = &iproc_pcie_ops; 13876e0832faSShawn Lin host->sysdata = pcie; 13886e0832faSShawn Lin host->map_irq = pcie->map_irq; 13896e0832faSShawn Lin host->swizzle_irq = pci_common_swizzle; 13906e0832faSShawn Lin 13916e0832faSShawn Lin ret = pci_scan_root_bus_bridge(host); 13926e0832faSShawn Lin if (ret < 0) { 13936e0832faSShawn Lin dev_err(dev, "failed to scan host: %d\n", ret); 13946e0832faSShawn Lin goto err_power_off_phy; 13956e0832faSShawn Lin } 13966e0832faSShawn Lin 13976e0832faSShawn Lin pci_assign_unassigned_bus_resources(host->bus); 13986e0832faSShawn Lin 13996e0832faSShawn Lin pcie->root_bus = host->bus; 14006e0832faSShawn Lin 14016e0832faSShawn Lin list_for_each_entry(child, &host->bus->children, node) 14026e0832faSShawn Lin pcie_bus_configure_settings(child); 14036e0832faSShawn Lin 14046e0832faSShawn Lin pci_bus_add_devices(host->bus); 14056e0832faSShawn Lin 14066e0832faSShawn Lin return 0; 14076e0832faSShawn Lin 14086e0832faSShawn Lin err_power_off_phy: 14096e0832faSShawn Lin phy_power_off(pcie->phy); 14106e0832faSShawn Lin err_exit_phy: 14116e0832faSShawn Lin phy_exit(pcie->phy); 14126e0832faSShawn Lin return ret; 14136e0832faSShawn Lin } 14146e0832faSShawn Lin EXPORT_SYMBOL(iproc_pcie_setup); 14156e0832faSShawn Lin 14166e0832faSShawn Lin int iproc_pcie_remove(struct iproc_pcie *pcie) 14176e0832faSShawn Lin { 14186e0832faSShawn Lin pci_stop_root_bus(pcie->root_bus); 14196e0832faSShawn Lin pci_remove_root_bus(pcie->root_bus); 14206e0832faSShawn Lin 14216e0832faSShawn Lin iproc_pcie_msi_disable(pcie); 14226e0832faSShawn Lin 14236e0832faSShawn Lin phy_power_off(pcie->phy); 14246e0832faSShawn Lin phy_exit(pcie->phy); 14256e0832faSShawn Lin 14266e0832faSShawn Lin return 0; 14276e0832faSShawn Lin } 14286e0832faSShawn Lin EXPORT_SYMBOL(iproc_pcie_remove); 14296e0832faSShawn Lin 14306e0832faSShawn Lin MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>"); 14316e0832faSShawn Lin MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver"); 14326e0832faSShawn Lin MODULE_LICENSE("GPL v2"); 1433