12fdc9b74SLiviu Dudau /*
22fdc9b74SLiviu Dudau * Copyright (C) ARM Ltd 2015
32fdc9b74SLiviu Dudau *
42fdc9b74SLiviu Dudau * Author: Liviu Dudau <Liviu.Dudau@arm.com>
52fdc9b74SLiviu Dudau *
62fdc9b74SLiviu Dudau * SPDX-Licence-Identifier: GPL-2.0+
72fdc9b74SLiviu Dudau */
82fdc9b74SLiviu Dudau
92fdc9b74SLiviu Dudau #include <common.h>
102fdc9b74SLiviu Dudau #include <asm/io.h>
112fdc9b74SLiviu Dudau #include <linux/bitops.h>
122fdc9b74SLiviu Dudau #include <pci_ids.h>
132fdc9b74SLiviu Dudau #include "pcie.h"
142fdc9b74SLiviu Dudau
152fdc9b74SLiviu Dudau /* XpressRICH3 support */
162fdc9b74SLiviu Dudau #define XR3_CONFIG_BASE 0x7ff30000
172fdc9b74SLiviu Dudau #define XR3_RESET_BASE 0x7ff20000
182fdc9b74SLiviu Dudau
192fdc9b74SLiviu Dudau #define XR3_PCI_ECAM_START 0x40000000
202fdc9b74SLiviu Dudau #define XR3_PCI_ECAM_SIZE 28 /* as power of 2 = 0x10000000 */
212fdc9b74SLiviu Dudau #define XR3_PCI_IOSPACE_START 0x5f800000
222fdc9b74SLiviu Dudau #define XR3_PCI_IOSPACE_SIZE 23 /* as power of 2 = 0x800000 */
232fdc9b74SLiviu Dudau #define XR3_PCI_MEMSPACE_START 0x50000000
242fdc9b74SLiviu Dudau #define XR3_PCI_MEMSPACE_SIZE 27 /* as power of 2 = 0x8000000 */
252fdc9b74SLiviu Dudau #define XR3_PCI_MEMSPACE64_START 0x4000000000
262fdc9b74SLiviu Dudau #define XR3_PCI_MEMSPACE64_SIZE 33 /* as power of 2 = 0x200000000 */
272fdc9b74SLiviu Dudau
282fdc9b74SLiviu Dudau #define JUNO_V2M_MSI_START 0x2c1c0000
292fdc9b74SLiviu Dudau #define JUNO_V2M_MSI_SIZE 12 /* as power of 2 = 4096 */
302fdc9b74SLiviu Dudau
312fdc9b74SLiviu Dudau #define XR3PCI_BASIC_STATUS 0x18
322fdc9b74SLiviu Dudau #define XR3PCI_BS_GEN_MASK (0xf << 8)
332fdc9b74SLiviu Dudau #define XR3PCI_BS_LINK_MASK 0xff
342fdc9b74SLiviu Dudau
352fdc9b74SLiviu Dudau #define XR3PCI_VIRTCHAN_CREDITS 0x90
362fdc9b74SLiviu Dudau #define XR3PCI_BRIDGE_PCI_IDS 0x9c
372fdc9b74SLiviu Dudau #define XR3PCI_PEX_SPC2 0xd8
382fdc9b74SLiviu Dudau
392fdc9b74SLiviu Dudau #define XR3PCI_ATR_PCIE_WIN0 0x600
402fdc9b74SLiviu Dudau #define XR3PCI_ATR_PCIE_WIN1 0x700
412fdc9b74SLiviu Dudau #define XR3PCI_ATR_AXI4_SLV0 0x800
422fdc9b74SLiviu Dudau
432fdc9b74SLiviu Dudau #define XR3PCI_ATR_TABLE_SIZE 0x20
442fdc9b74SLiviu Dudau #define XR3PCI_ATR_SRC_ADDR_LOW 0x0
452fdc9b74SLiviu Dudau #define XR3PCI_ATR_SRC_ADDR_HIGH 0x4
462fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSL_ADDR_LOW 0x8
472fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSL_ADDR_HIGH 0xc
482fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSL_PARAM 0x10
492fdc9b74SLiviu Dudau
502fdc9b74SLiviu Dudau /* IDs used in the XR3PCI_ATR_TRSL_PARAM */
512fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSLID_AXIDEVICE (0x420004)
522fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSLID_AXIMEMORY (0x4e0004) /* Write-through, read/write allocate */
532fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSLID_PCIE_CONF (0x000001)
542fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSLID_PCIE_IO (0x020000)
552fdc9b74SLiviu Dudau #define XR3PCI_ATR_TRSLID_PCIE_MEMORY (0x000000)
562fdc9b74SLiviu Dudau
572fdc9b74SLiviu Dudau #define XR3PCI_ECAM_OFFSET(b, d, o) (((b) << 20) | \
582fdc9b74SLiviu Dudau (PCI_SLOT(d) << 15) | \
592fdc9b74SLiviu Dudau (PCI_FUNC(d) << 12) | o)
602fdc9b74SLiviu Dudau
612fdc9b74SLiviu Dudau #define JUNO_RESET_CTRL 0x1004
622fdc9b74SLiviu Dudau #define JUNO_RESET_CTRL_PHY BIT(0)
632fdc9b74SLiviu Dudau #define JUNO_RESET_CTRL_RC BIT(1)
642fdc9b74SLiviu Dudau
652fdc9b74SLiviu Dudau #define JUNO_RESET_STATUS 0x1008
662fdc9b74SLiviu Dudau #define JUNO_RESET_STATUS_PLL BIT(0)
672fdc9b74SLiviu Dudau #define JUNO_RESET_STATUS_PHY BIT(1)
682fdc9b74SLiviu Dudau #define JUNO_RESET_STATUS_RC BIT(2)
692fdc9b74SLiviu Dudau #define JUNO_RESET_STATUS_MASK (JUNO_RESET_STATUS_PLL | \
702fdc9b74SLiviu Dudau JUNO_RESET_STATUS_PHY | \
712fdc9b74SLiviu Dudau JUNO_RESET_STATUS_RC)
722fdc9b74SLiviu Dudau
xr3pci_set_atr_entry(unsigned long base,unsigned long src_addr,unsigned long trsl_addr,int window_size,int trsl_param)732fdc9b74SLiviu Dudau void xr3pci_set_atr_entry(unsigned long base, unsigned long src_addr,
742fdc9b74SLiviu Dudau unsigned long trsl_addr, int window_size,
752fdc9b74SLiviu Dudau int trsl_param)
762fdc9b74SLiviu Dudau {
772fdc9b74SLiviu Dudau /* X3PCI_ATR_SRC_ADDR_LOW:
782fdc9b74SLiviu Dudau - bit 0: enable entry,
792fdc9b74SLiviu Dudau - bits 1-6: ATR window size: total size in bytes: 2^(ATR_WSIZE + 1)
802fdc9b74SLiviu Dudau - bits 7-11: reserved
812fdc9b74SLiviu Dudau - bits 12-31: start of source address
822fdc9b74SLiviu Dudau */
832fdc9b74SLiviu Dudau writel((u32)(src_addr & 0xfffff000) | (window_size - 1) << 1 | 1,
842fdc9b74SLiviu Dudau base + XR3PCI_ATR_SRC_ADDR_LOW);
852fdc9b74SLiviu Dudau writel((u32)(src_addr >> 32), base + XR3PCI_ATR_SRC_ADDR_HIGH);
862fdc9b74SLiviu Dudau writel((u32)(trsl_addr & 0xfffff000), base + XR3PCI_ATR_TRSL_ADDR_LOW);
872fdc9b74SLiviu Dudau writel((u32)(trsl_addr >> 32), base + XR3PCI_ATR_TRSL_ADDR_HIGH);
882fdc9b74SLiviu Dudau writel(trsl_param, base + XR3PCI_ATR_TRSL_PARAM);
892fdc9b74SLiviu Dudau
900ee1a22bSAndre Przywara debug("ATR entry: 0x%010lx %s 0x%010lx [0x%010llx] (param: 0x%06x)\n",
912fdc9b74SLiviu Dudau src_addr, (trsl_param & 0x400000) ? "<-" : "->", trsl_addr,
922fdc9b74SLiviu Dudau ((u64)1) << window_size, trsl_param);
932fdc9b74SLiviu Dudau }
942fdc9b74SLiviu Dudau
xr3pci_setup_atr(void)952fdc9b74SLiviu Dudau void xr3pci_setup_atr(void)
962fdc9b74SLiviu Dudau {
972fdc9b74SLiviu Dudau /* setup PCIe to CPU address translation tables */
982fdc9b74SLiviu Dudau unsigned long base = XR3_CONFIG_BASE + XR3PCI_ATR_PCIE_WIN0;
992fdc9b74SLiviu Dudau
1002fdc9b74SLiviu Dudau /* forward all writes from PCIe to GIC V2M (used for MSI) */
1012fdc9b74SLiviu Dudau xr3pci_set_atr_entry(base, JUNO_V2M_MSI_START, JUNO_V2M_MSI_START,
1022fdc9b74SLiviu Dudau JUNO_V2M_MSI_SIZE, XR3PCI_ATR_TRSLID_AXIDEVICE);
1032fdc9b74SLiviu Dudau
1042fdc9b74SLiviu Dudau base += XR3PCI_ATR_TABLE_SIZE;
1052fdc9b74SLiviu Dudau
1062fdc9b74SLiviu Dudau /* PCIe devices can write anywhere in memory */
1072fdc9b74SLiviu Dudau xr3pci_set_atr_entry(base, PHYS_SDRAM_1, PHYS_SDRAM_1,
1082fdc9b74SLiviu Dudau 31 /* grant access to all RAM under 4GB */,
1092fdc9b74SLiviu Dudau XR3PCI_ATR_TRSLID_AXIMEMORY);
1102fdc9b74SLiviu Dudau base += XR3PCI_ATR_TABLE_SIZE;
1112fdc9b74SLiviu Dudau xr3pci_set_atr_entry(base, PHYS_SDRAM_2, PHYS_SDRAM_2,
1122fdc9b74SLiviu Dudau XR3_PCI_MEMSPACE64_SIZE,
1132fdc9b74SLiviu Dudau XR3PCI_ATR_TRSLID_AXIMEMORY);
1142fdc9b74SLiviu Dudau
1152fdc9b74SLiviu Dudau
1162fdc9b74SLiviu Dudau /* setup CPU to PCIe address translation table */
1172fdc9b74SLiviu Dudau base = XR3_CONFIG_BASE + XR3PCI_ATR_AXI4_SLV0;
1182fdc9b74SLiviu Dudau
1192fdc9b74SLiviu Dudau /* setup ECAM space to bus configuration interface */
1202fdc9b74SLiviu Dudau xr3pci_set_atr_entry(base, XR3_PCI_ECAM_START, 0, XR3_PCI_ECAM_SIZE,
1212fdc9b74SLiviu Dudau XR3PCI_ATR_TRSLID_PCIE_CONF);
1222fdc9b74SLiviu Dudau
1232fdc9b74SLiviu Dudau base += XR3PCI_ATR_TABLE_SIZE;
1242fdc9b74SLiviu Dudau
1252fdc9b74SLiviu Dudau /* setup IO space translation */
126*88e0d593SLiviu Dudau xr3pci_set_atr_entry(base, XR3_PCI_IOSPACE_START, 0,
1272fdc9b74SLiviu Dudau XR3_PCI_IOSPACE_SIZE, XR3PCI_ATR_TRSLID_PCIE_IO);
1282fdc9b74SLiviu Dudau
1292fdc9b74SLiviu Dudau base += XR3PCI_ATR_TABLE_SIZE;
1302fdc9b74SLiviu Dudau
1312fdc9b74SLiviu Dudau /* setup 32bit MEM space translation */
1322fdc9b74SLiviu Dudau xr3pci_set_atr_entry(base, XR3_PCI_MEMSPACE_START, XR3_PCI_MEMSPACE_START,
1332fdc9b74SLiviu Dudau XR3_PCI_MEMSPACE_SIZE, XR3PCI_ATR_TRSLID_PCIE_MEMORY);
1342fdc9b74SLiviu Dudau
1352fdc9b74SLiviu Dudau base += XR3PCI_ATR_TABLE_SIZE;
1362fdc9b74SLiviu Dudau
1372fdc9b74SLiviu Dudau /* setup 64bit MEM space translation */
1382fdc9b74SLiviu Dudau xr3pci_set_atr_entry(base, XR3_PCI_MEMSPACE64_START, XR3_PCI_MEMSPACE64_START,
1392fdc9b74SLiviu Dudau XR3_PCI_MEMSPACE64_SIZE, XR3PCI_ATR_TRSLID_PCIE_MEMORY);
1402fdc9b74SLiviu Dudau }
1412fdc9b74SLiviu Dudau
xr3pci_init(void)1422fdc9b74SLiviu Dudau void xr3pci_init(void)
1432fdc9b74SLiviu Dudau {
1442fdc9b74SLiviu Dudau u32 val;
1452fdc9b74SLiviu Dudau int timeout = 200;
1462fdc9b74SLiviu Dudau
1472fdc9b74SLiviu Dudau /* Initialise the XpressRICH3 PCIe host bridge */
1482fdc9b74SLiviu Dudau
1492fdc9b74SLiviu Dudau /* add credits */
1502fdc9b74SLiviu Dudau writel(0x00f0b818, XR3_CONFIG_BASE + XR3PCI_VIRTCHAN_CREDITS);
1512fdc9b74SLiviu Dudau writel(0x1, XR3_CONFIG_BASE + XR3PCI_VIRTCHAN_CREDITS + 4);
1522fdc9b74SLiviu Dudau /* allow ECRC */
1532fdc9b74SLiviu Dudau writel(0x6006, XR3_CONFIG_BASE + XR3PCI_PEX_SPC2);
1542fdc9b74SLiviu Dudau /* setup the correct class code for the host bridge */
1552fdc9b74SLiviu Dudau writel(PCI_CLASS_BRIDGE_PCI << 16, XR3_CONFIG_BASE + XR3PCI_BRIDGE_PCI_IDS);
1562fdc9b74SLiviu Dudau
1572fdc9b74SLiviu Dudau /* reset phy and root complex */
1582fdc9b74SLiviu Dudau writel(JUNO_RESET_CTRL_PHY | JUNO_RESET_CTRL_RC,
1592fdc9b74SLiviu Dudau XR3_RESET_BASE + JUNO_RESET_CTRL);
1602fdc9b74SLiviu Dudau
1612fdc9b74SLiviu Dudau do {
1622fdc9b74SLiviu Dudau mdelay(1);
1632fdc9b74SLiviu Dudau val = readl(XR3_RESET_BASE + JUNO_RESET_STATUS);
1642fdc9b74SLiviu Dudau } while (--timeout &&
1652fdc9b74SLiviu Dudau (val & JUNO_RESET_STATUS_MASK) != JUNO_RESET_STATUS_MASK);
1662fdc9b74SLiviu Dudau
1672fdc9b74SLiviu Dudau if (!timeout) {
1682fdc9b74SLiviu Dudau printf("PCI XR3 Root complex reset timed out\n");
1692fdc9b74SLiviu Dudau return;
1702fdc9b74SLiviu Dudau }
1712fdc9b74SLiviu Dudau
1722fdc9b74SLiviu Dudau /* Wait for the link to train */
1732fdc9b74SLiviu Dudau mdelay(20);
1742fdc9b74SLiviu Dudau timeout = 20;
1752fdc9b74SLiviu Dudau
1762fdc9b74SLiviu Dudau do {
1772fdc9b74SLiviu Dudau mdelay(1);
1782fdc9b74SLiviu Dudau val = readl(XR3_CONFIG_BASE + XR3PCI_BASIC_STATUS);
1792fdc9b74SLiviu Dudau } while (--timeout && !(val & XR3PCI_BS_LINK_MASK));
1802fdc9b74SLiviu Dudau
1812fdc9b74SLiviu Dudau if (!(val & XR3PCI_BS_LINK_MASK)) {
1822fdc9b74SLiviu Dudau printf("Failed to negotiate a link!\n");
1832fdc9b74SLiviu Dudau return;
1842fdc9b74SLiviu Dudau }
1852fdc9b74SLiviu Dudau
1862fdc9b74SLiviu Dudau printf("PCIe XR3 Host Bridge enabled: x%d link (Gen %d)\n",
1872fdc9b74SLiviu Dudau val & XR3PCI_BS_LINK_MASK, (val & XR3PCI_BS_GEN_MASK) >> 8);
1882fdc9b74SLiviu Dudau
1892fdc9b74SLiviu Dudau xr3pci_setup_atr();
1902fdc9b74SLiviu Dudau }
1912fdc9b74SLiviu Dudau
vexpress64_pcie_init(void)1922fdc9b74SLiviu Dudau void vexpress64_pcie_init(void)
1932fdc9b74SLiviu Dudau {
1942fdc9b74SLiviu Dudau xr3pci_init();
1952fdc9b74SLiviu Dudau }
196