pcie_ep: layerscape: Add the multiple function support
[platform/kernel/u-boot.git] / drivers / pci / pcie_layerscape.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2017-2020 NXP
4  * Copyright 2014-2015 Freescale Semiconductor, Inc.
5  * Layerscape PCIe driver
6  */
7
8 #include <common.h>
9 #include <log.h>
10 #include <asm/io.h>
11 #include <errno.h>
12 #include <malloc.h>
13 #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
14         defined(CONFIG_ARM)
15 #include <asm/arch/clock.h>
16 #endif
17 #include "pcie_layerscape.h"
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 LIST_HEAD(ls_pcie_list);
22
23 unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset)
24 {
25         return in_le32(pcie->dbi + offset);
26 }
27
28 void dbi_writel(struct ls_pcie *pcie, unsigned int value, unsigned int offset)
29 {
30         out_le32(pcie->dbi + offset, value);
31 }
32
33 unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int offset)
34 {
35         if (pcie->big_endian)
36                 return in_be32(pcie->ctrl + offset);
37         else
38                 return in_le32(pcie->ctrl + offset);
39 }
40
41 void ctrl_writel(struct ls_pcie *pcie, unsigned int value,
42                  unsigned int offset)
43 {
44         if (pcie->big_endian)
45                 out_be32(pcie->ctrl + offset, value);
46         else
47                 out_le32(pcie->ctrl + offset, value);
48 }
49
50 void ls_pcie_dbi_ro_wr_en(struct ls_pcie *pcie)
51 {
52         u32 reg, val;
53
54         reg = PCIE_MISC_CONTROL_1_OFF;
55         val = dbi_readl(pcie, reg);
56         val |= PCIE_DBI_RO_WR_EN;
57         dbi_writel(pcie, val, reg);
58 }
59
60 void ls_pcie_dbi_ro_wr_dis(struct ls_pcie *pcie)
61 {
62         u32 reg, val;
63
64         reg = PCIE_MISC_CONTROL_1_OFF;
65         val = dbi_readl(pcie, reg);
66         val &= ~PCIE_DBI_RO_WR_EN;
67         dbi_writel(pcie, val, reg);
68 }
69
70 static int ls_pcie_ltssm(struct ls_pcie *pcie)
71 {
72         u32 state;
73         uint svr;
74
75         svr = get_svr();
76         if (((svr >> SVR_VAR_PER_SHIFT) & SVR_LS102XA_MASK) == SVR_LS102XA) {
77                 state = ctrl_readl(pcie, LS1021_PEXMSCPORTSR(pcie->idx));
78                 state = (state >> LS1021_LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
79         } else {
80                 state = ctrl_readl(pcie, PCIE_PF_DBG) & LTSSM_STATE_MASK;
81         }
82
83         return state;
84 }
85
86 int ls_pcie_link_up(struct ls_pcie *pcie)
87 {
88         int ltssm;
89
90         ltssm = ls_pcie_ltssm(pcie);
91         if (ltssm < LTSSM_PCIE_L0)
92                 return 0;
93
94         return 1;
95 }
96
97 void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type,
98                               u64 phys, u64 bus_addr, pci_size_t size)
99 {
100         dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | idx, PCIE_ATU_VIEWPORT);
101         dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_BASE);
102         dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_BASE);
103         dbi_writel(pcie, (u32)phys + size - 1, PCIE_ATU_LIMIT);
104         dbi_writel(pcie, (u32)bus_addr, PCIE_ATU_LOWER_TARGET);
105         dbi_writel(pcie, bus_addr >> 32, PCIE_ATU_UPPER_TARGET);
106         dbi_writel(pcie, type, PCIE_ATU_CR1);
107         dbi_writel(pcie, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
108 }
109
110 /* Use bar match mode and MEM type as default */
111 void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, u32 pf, int type,
112                              int idx, int bar, u64 phys)
113 {
114         dbi_writel(pcie, PCIE_ATU_REGION_INBOUND | idx, PCIE_ATU_VIEWPORT);
115         dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_TARGET);
116         dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_TARGET);
117         dbi_writel(pcie, type | PCIE_ATU_FUNC_NUM(pf), PCIE_ATU_CR1);
118         dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE |
119                    PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2);
120 }
121
122 void ls_pcie_dump_atu(struct ls_pcie *pcie)
123 {
124         int i;
125
126         for (i = 0; i < PCIE_ATU_REGION_NUM; i++) {
127                 dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | i,
128                            PCIE_ATU_VIEWPORT);
129                 debug("iATU%d:\n", i);
130                 debug("\tLOWER PHYS 0x%08x\n",
131                       dbi_readl(pcie, PCIE_ATU_LOWER_BASE));
132                 debug("\tUPPER PHYS 0x%08x\n",
133                       dbi_readl(pcie, PCIE_ATU_UPPER_BASE));
134                 debug("\tLOWER BUS  0x%08x\n",
135                       dbi_readl(pcie, PCIE_ATU_LOWER_TARGET));
136                 debug("\tUPPER BUS  0x%08x\n",
137                       dbi_readl(pcie, PCIE_ATU_UPPER_TARGET));
138                 debug("\tLIMIT      0x%08x\n",
139                       dbi_readl(pcie, PCIE_ATU_LIMIT));
140                 debug("\tCR1        0x%08x\n",
141                       dbi_readl(pcie, PCIE_ATU_CR1));
142                 debug("\tCR2        0x%08x\n",
143                       dbi_readl(pcie, PCIE_ATU_CR2));
144         }
145 }