1bc58f211SShawn Lin // SPDX-License-Identifier: GPL-2.0+
2bc58f211SShawn Lin /*
3bc58f211SShawn Lin * Rockchip DesignWare based PCIe host controller driver
4bc58f211SShawn Lin *
5bc58f211SShawn Lin * Copyright (c) 2021 Rockchip, Inc.
6bc58f211SShawn Lin */
7bc58f211SShawn Lin
8bc58f211SShawn Lin #include <common.h>
9bc58f211SShawn Lin #include <clk.h>
10bc58f211SShawn Lin #include <dm.h>
11bc58f211SShawn Lin #include <generic-phy.h>
12bc58f211SShawn Lin #include <pci.h>
13bc58f211SShawn Lin #include <power-domain.h>
14bc58f211SShawn Lin #include <power/regulator.h>
15bc58f211SShawn Lin #include <reset.h>
16bc58f211SShawn Lin #include <syscon.h>
17bc58f211SShawn Lin #include <asm/io.h>
18bc58f211SShawn Lin #include <asm-generic/gpio.h>
19bc58f211SShawn Lin #include <asm/arch-rockchip/clock.h>
20b8495bb7SShawn Lin #include <linux/bitfield.h>
21bc58f211SShawn Lin #include <linux/iopoll.h>
22fbc8ca74SJon Lin #include <linux/ioport.h>
23b8495bb7SShawn Lin #include <linux/log2.h>
24bc58f211SShawn Lin
25bc58f211SShawn Lin DECLARE_GLOBAL_DATA_PTR;
26bc58f211SShawn Lin
270e16653bSJon Lin #define RK_PCIE_DBG 0
280e16653bSJon Lin
290e16653bSJon Lin #define __pcie_dev_print_emit(fmt, ...) \
300e16653bSJon Lin ({ \
310e16653bSJon Lin printf(fmt, ##__VA_ARGS__); \
320e16653bSJon Lin })
330e16653bSJon Lin
340e16653bSJon Lin #ifdef dev_err
350e16653bSJon Lin #undef dev_err
360e16653bSJon Lin #define dev_err(dev, fmt, ...) \
370e16653bSJon Lin ({ \
380e16653bSJon Lin if (dev) \
390e16653bSJon Lin __pcie_dev_print_emit("%s: " fmt, dev->name, \
400e16653bSJon Lin ##__VA_ARGS__); \
410e16653bSJon Lin })
420e16653bSJon Lin #endif
430e16653bSJon Lin
440e16653bSJon Lin #ifdef dev_info
450e16653bSJon Lin #undef dev_info
460e16653bSJon Lin #define dev_info dev_err
470e16653bSJon Lin #endif
480e16653bSJon Lin
490e16653bSJon Lin #ifdef DEBUG
500e16653bSJon Lin #define dev_dbg dev_err
510e16653bSJon Lin #else
520e16653bSJon Lin #define dev_dbg(dev, fmt, ...) \
530e16653bSJon Lin ({ \
540e16653bSJon Lin if (0) \
550e16653bSJon Lin __dev_printk(7, dev, fmt, ##__VA_ARGS__); \
560e16653bSJon Lin })
570e16653bSJon Lin #endif
580e16653bSJon Lin
59bc58f211SShawn Lin struct rk_pcie {
60bc58f211SShawn Lin struct udevice *dev;
61bc58f211SShawn Lin struct udevice *vpcie3v3;
62bc58f211SShawn Lin void *dbi_base;
63bc58f211SShawn Lin void *apb_base;
64bc58f211SShawn Lin void *cfg_base;
65bc58f211SShawn Lin fdt_size_t cfg_size;
66bc58f211SShawn Lin struct phy phy;
67bc58f211SShawn Lin struct clk_bulk clks;
68bc58f211SShawn Lin int first_busno;
69bc58f211SShawn Lin struct reset_ctl_bulk rsts;
70bc58f211SShawn Lin struct gpio_desc rst_gpio;
71bc58f211SShawn Lin struct pci_region io;
72bc58f211SShawn Lin struct pci_region mem;
737ff76e75SShawn Lin struct pci_region mem64;
74c2482762SShawn Lin bool is_bifurcation;
75769b1920SShawn Lin u32 rasdes_off;
76abcec002SJon Lin u32 gen;
77b8495bb7SShawn Lin u32 lanes;
78bc58f211SShawn Lin };
79bc58f211SShawn Lin
80bc58f211SShawn Lin enum {
81bc58f211SShawn Lin PCIBIOS_SUCCESSFUL = 0x0000,
82bc58f211SShawn Lin PCIBIOS_UNSUPPORTED = -ENODEV,
83bc58f211SShawn Lin PCIBIOS_NODEV = -ENODEV,
84bc58f211SShawn Lin };
85bc58f211SShawn Lin
86bc58f211SShawn Lin #define msleep(a) udelay((a) * 1000)
87fec7a75eSShawn Lin #define MAX_LINKUP_RETRIES 2
88bc58f211SShawn Lin
89bc58f211SShawn Lin /* Parameters for the waiting for iATU enabled routine */
90bc58f211SShawn Lin #define PCIE_CLIENT_GENERAL_DEBUG 0x104
91fbafd477SShawn Lin #define PCIE_CLIENT_CDM_RASDES_TBA_INFO_CMN 0x154
92bc58f211SShawn Lin #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
93bc58f211SShawn Lin #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4)
94bc58f211SShawn Lin #define PCIE_CLIENT_LTSSM_STATUS 0x300
95bc58f211SShawn Lin #define SMLH_LINKUP BIT(16)
96bc58f211SShawn Lin #define RDLH_LINKUP BIT(17)
97bc58f211SShawn Lin #define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
98bc58f211SShawn Lin #define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
99bc58f211SShawn Lin #define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
100bc58f211SShawn Lin #define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
101bc58f211SShawn Lin #define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
102bc58f211SShawn Lin #define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
103bc58f211SShawn Lin #define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
104bc58f211SShawn Lin #define PCIE_CLIENT_DBF_EN 0xffff0003
105bc58f211SShawn Lin
106bc58f211SShawn Lin /* PCI DBICS registers */
107bc58f211SShawn Lin #define PCIE_LINK_STATUS_REG 0x80
108bc58f211SShawn Lin #define PCIE_LINK_STATUS_SPEED_OFF 16
109bc58f211SShawn Lin #define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF)
110bc58f211SShawn Lin #define PCIE_LINK_STATUS_WIDTH_OFF 20
111bc58f211SShawn Lin #define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF)
112bc58f211SShawn Lin
113bc58f211SShawn Lin #define PCIE_LINK_CAPABILITY 0x7c
114bc58f211SShawn Lin #define PCIE_LINK_CTL_2 0xa0
115bc58f211SShawn Lin #define TARGET_LINK_SPEED_MASK 0xf
116bc58f211SShawn Lin #define LINK_SPEED_GEN_1 0x1
117bc58f211SShawn Lin #define LINK_SPEED_GEN_2 0x2
118bc58f211SShawn Lin #define LINK_SPEED_GEN_3 0x3
119bc58f211SShawn Lin
120b8495bb7SShawn Lin #define PCIE_PORT_LINK_CONTROL 0x710
121b8495bb7SShawn Lin #define PORT_LINK_FAST_LINK_MODE BIT(7)
122bc58f211SShawn Lin #define PCIE_MISC_CONTROL_1_OFF 0x8bc
123bc58f211SShawn Lin #define PCIE_DBI_RO_WR_EN BIT(0)
124bc58f211SShawn Lin
125bc58f211SShawn Lin #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80c
126bc58f211SShawn Lin #define PORT_LOGIC_SPEED_CHANGE BIT(17)
127b8495bb7SShawn Lin #define PORT_LINK_MODE_MASK GENMASK(21, 16)
128b8495bb7SShawn Lin #define PORT_LINK_MODE(n) FIELD_PREP(PORT_LINK_MODE_MASK, n)
129b8495bb7SShawn Lin #define PORT_LINK_MODE_1_LANES PORT_LINK_MODE(0x1)
130b8495bb7SShawn Lin #define PORT_LINK_MODE_2_LANES PORT_LINK_MODE(0x3)
131b8495bb7SShawn Lin #define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7)
132b8495bb7SShawn Lin #define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf)
133b8495bb7SShawn Lin #define PORT_LOGIC_LINK_WIDTH_MASK GENMASK(12, 8)
134b8495bb7SShawn Lin #define PORT_LOGIC_LINK_WIDTH(n) FIELD_PREP(PORT_LOGIC_LINK_WIDTH_MASK, n)
135b8495bb7SShawn Lin #define PORT_LOGIC_LINK_WIDTH_1_LANES PORT_LOGIC_LINK_WIDTH(0x1)
136b8495bb7SShawn Lin #define PORT_LOGIC_LINK_WIDTH_2_LANES PORT_LOGIC_LINK_WIDTH(0x2)
137b8495bb7SShawn Lin #define PORT_LOGIC_LINK_WIDTH_4_LANES PORT_LOGIC_LINK_WIDTH(0x4)
138b8495bb7SShawn Lin #define PORT_LOGIC_LINK_WIDTH_8_LANES PORT_LOGIC_LINK_WIDTH(0x8)
139b8495bb7SShawn Lin
140bc58f211SShawn Lin
141bc58f211SShawn Lin /*
142bc58f211SShawn Lin * iATU Unroll-specific register definitions
143bc58f211SShawn Lin * From 4.80 core version the address translation will be made by unroll.
144bc58f211SShawn Lin * The registers are offset from atu_base
145bc58f211SShawn Lin */
146bc58f211SShawn Lin #define PCIE_ATU_UNR_REGION_CTRL1 0x00
147bc58f211SShawn Lin #define PCIE_ATU_UNR_REGION_CTRL2 0x04
148bc58f211SShawn Lin #define PCIE_ATU_UNR_LOWER_BASE 0x08
149bc58f211SShawn Lin #define PCIE_ATU_UNR_UPPER_BASE 0x0c
150bc58f211SShawn Lin #define PCIE_ATU_UNR_LIMIT 0x10
151bc58f211SShawn Lin #define PCIE_ATU_UNR_LOWER_TARGET 0x14
152bc58f211SShawn Lin #define PCIE_ATU_UNR_UPPER_TARGET 0x18
153bc58f211SShawn Lin
1547ff76e75SShawn Lin #define PCIE_ATU_REGION_INDEX2 (0x2 << 0)
155bc58f211SShawn Lin #define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
156bc58f211SShawn Lin #define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
157bc58f211SShawn Lin #define PCIE_ATU_TYPE_MEM (0x0 << 0)
158bc58f211SShawn Lin #define PCIE_ATU_TYPE_IO (0x2 << 0)
159bc58f211SShawn Lin #define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
160bc58f211SShawn Lin #define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
161bc58f211SShawn Lin #define PCIE_ATU_ENABLE (0x1 << 31)
162bc58f211SShawn Lin #define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
163bc58f211SShawn Lin #define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
164bc58f211SShawn Lin #define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
165bc58f211SShawn Lin #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
166bc58f211SShawn Lin
167bc58f211SShawn Lin /* Register address builder */
168bc58f211SShawn Lin #define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \
169bc58f211SShawn Lin ((0x3 << 20) | ((region) << 9))
170bc58f211SShawn Lin #define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \
171bc58f211SShawn Lin ((0x3 << 20) | ((region) << 9) | (0x1 << 8))
172bc58f211SShawn Lin
173bc58f211SShawn Lin /* Parameters for the waiting for iATU enabled routine */
174bc58f211SShawn Lin #define LINK_WAIT_MAX_IATU_RETRIES 5
175bc58f211SShawn Lin #define LINK_WAIT_IATU 10000
176bc58f211SShawn Lin
1771f452320SJon Lin #define PCIE_TYPE0_HDR_DBI2_OFFSET 0x100000
1781f452320SJon Lin
rk_pcie_read(void __iomem * addr,int size,u32 * val)179bc58f211SShawn Lin static int rk_pcie_read(void __iomem *addr, int size, u32 *val)
180bc58f211SShawn Lin {
181bc58f211SShawn Lin if ((uintptr_t)addr & (size - 1)) {
182bc58f211SShawn Lin *val = 0;
183bc58f211SShawn Lin return PCIBIOS_UNSUPPORTED;
184bc58f211SShawn Lin }
185bc58f211SShawn Lin
186bc58f211SShawn Lin if (size == 4) {
187bc58f211SShawn Lin *val = readl(addr);
188bc58f211SShawn Lin } else if (size == 2) {
189bc58f211SShawn Lin *val = readw(addr);
190bc58f211SShawn Lin } else if (size == 1) {
191bc58f211SShawn Lin *val = readb(addr);
192bc58f211SShawn Lin } else {
193bc58f211SShawn Lin *val = 0;
194bc58f211SShawn Lin return PCIBIOS_NODEV;
195bc58f211SShawn Lin }
196bc58f211SShawn Lin
197bc58f211SShawn Lin return PCIBIOS_SUCCESSFUL;
198bc58f211SShawn Lin }
199bc58f211SShawn Lin
rk_pcie_write(void __iomem * addr,int size,u32 val)200bc58f211SShawn Lin static int rk_pcie_write(void __iomem *addr, int size, u32 val)
201bc58f211SShawn Lin {
202bc58f211SShawn Lin if ((uintptr_t)addr & (size - 1))
203bc58f211SShawn Lin return PCIBIOS_UNSUPPORTED;
204bc58f211SShawn Lin
205bc58f211SShawn Lin if (size == 4)
206bc58f211SShawn Lin writel(val, addr);
207bc58f211SShawn Lin else if (size == 2)
208bc58f211SShawn Lin writew(val, addr);
209bc58f211SShawn Lin else if (size == 1)
210bc58f211SShawn Lin writeb(val, addr);
211bc58f211SShawn Lin else
212bc58f211SShawn Lin return PCIBIOS_NODEV;
213bc58f211SShawn Lin
214bc58f211SShawn Lin return PCIBIOS_SUCCESSFUL;
215bc58f211SShawn Lin }
216bc58f211SShawn Lin
__rk_pcie_read_apb(struct rk_pcie * rk_pcie,void __iomem * base,u32 reg,size_t size)217bc58f211SShawn Lin static u32 __rk_pcie_read_apb(struct rk_pcie *rk_pcie, void __iomem *base,
218bc58f211SShawn Lin u32 reg, size_t size)
219bc58f211SShawn Lin {
220bc58f211SShawn Lin int ret;
221bc58f211SShawn Lin u32 val;
222bc58f211SShawn Lin
223bc58f211SShawn Lin ret = rk_pcie_read(base + reg, size, &val);
224bc58f211SShawn Lin if (ret)
2250e16653bSJon Lin dev_err(rk_pcie->dev, "Read APB address failed\n");
226bc58f211SShawn Lin
227bc58f211SShawn Lin return val;
228bc58f211SShawn Lin }
229bc58f211SShawn Lin
__rk_pcie_write_apb(struct rk_pcie * rk_pcie,void __iomem * base,u32 reg,size_t size,u32 val)230bc58f211SShawn Lin static void __rk_pcie_write_apb(struct rk_pcie *rk_pcie, void __iomem *base,
231bc58f211SShawn Lin u32 reg, size_t size, u32 val)
232bc58f211SShawn Lin {
233bc58f211SShawn Lin int ret;
234bc58f211SShawn Lin
235bc58f211SShawn Lin ret = rk_pcie_write(base + reg, size, val);
236bc58f211SShawn Lin if (ret)
2370e16653bSJon Lin dev_err(rk_pcie->dev, "Write APB address failed\n");
238bc58f211SShawn Lin }
239bc58f211SShawn Lin
rk_pcie_readl_apb(struct rk_pcie * rk_pcie,u32 reg)240bc58f211SShawn Lin static inline u32 rk_pcie_readl_apb(struct rk_pcie *rk_pcie, u32 reg)
241bc58f211SShawn Lin {
242bc58f211SShawn Lin return __rk_pcie_read_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4);
243bc58f211SShawn Lin }
244bc58f211SShawn Lin
rk_pcie_writel_apb(struct rk_pcie * rk_pcie,u32 reg,u32 val)245bc58f211SShawn Lin static inline void rk_pcie_writel_apb(struct rk_pcie *rk_pcie, u32 reg,
246bc58f211SShawn Lin u32 val)
247bc58f211SShawn Lin {
248bc58f211SShawn Lin __rk_pcie_write_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4, val);
249bc58f211SShawn Lin }
250bc58f211SShawn Lin
rk_pci_find_ext_capability(struct rk_pcie * rk_pcie,int cap)251*7ece1cfeSJon Lin static int rk_pci_find_ext_capability(struct rk_pcie *rk_pcie, int cap)
252*7ece1cfeSJon Lin {
253*7ece1cfeSJon Lin u32 header;
254*7ece1cfeSJon Lin int ttl;
255*7ece1cfeSJon Lin int start = 0;
256*7ece1cfeSJon Lin int pos = PCI_CFG_SPACE_SIZE;
257*7ece1cfeSJon Lin
258*7ece1cfeSJon Lin /* minimum 8 bytes per capability */
259*7ece1cfeSJon Lin ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
260*7ece1cfeSJon Lin
261*7ece1cfeSJon Lin header = readl(rk_pcie->dbi_base + pos);
262*7ece1cfeSJon Lin
263*7ece1cfeSJon Lin /*
264*7ece1cfeSJon Lin * If we have no capabilities, this is indicated by cap ID,
265*7ece1cfeSJon Lin * cap version and next pointer all being 0.
266*7ece1cfeSJon Lin */
267*7ece1cfeSJon Lin if (header == 0)
268*7ece1cfeSJon Lin return 0;
269*7ece1cfeSJon Lin
270*7ece1cfeSJon Lin while (ttl-- > 0) {
271*7ece1cfeSJon Lin if (PCI_EXT_CAP_ID(header) == cap && pos != start)
272*7ece1cfeSJon Lin return pos;
273*7ece1cfeSJon Lin
274*7ece1cfeSJon Lin pos = PCI_EXT_CAP_NEXT(header);
275*7ece1cfeSJon Lin if (pos < PCI_CFG_SPACE_SIZE)
276*7ece1cfeSJon Lin break;
277*7ece1cfeSJon Lin
278*7ece1cfeSJon Lin header = readl(rk_pcie->dbi_base + pos);
279*7ece1cfeSJon Lin if (!header)
280*7ece1cfeSJon Lin break;
281*7ece1cfeSJon Lin }
282*7ece1cfeSJon Lin
283*7ece1cfeSJon Lin return 0;
284*7ece1cfeSJon Lin }
285*7ece1cfeSJon Lin
rk_pcie_get_link_speed(struct rk_pcie * rk_pcie)286bc58f211SShawn Lin static int rk_pcie_get_link_speed(struct rk_pcie *rk_pcie)
287bc58f211SShawn Lin {
288bc58f211SShawn Lin return (readl(rk_pcie->dbi_base + PCIE_LINK_STATUS_REG) &
289bc58f211SShawn Lin PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF;
290bc58f211SShawn Lin }
291bc58f211SShawn Lin
rk_pcie_get_link_width(struct rk_pcie * rk_pcie)292bc58f211SShawn Lin static int rk_pcie_get_link_width(struct rk_pcie *rk_pcie)
293bc58f211SShawn Lin {
294bc58f211SShawn Lin return (readl(rk_pcie->dbi_base + PCIE_LINK_STATUS_REG) &
295bc58f211SShawn Lin PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
296bc58f211SShawn Lin }
297bc58f211SShawn Lin
rk_pcie_writel_ob_unroll(struct rk_pcie * rk_pcie,u32 index,u32 reg,u32 val)298bc58f211SShawn Lin static void rk_pcie_writel_ob_unroll(struct rk_pcie *rk_pcie, u32 index,
299bc58f211SShawn Lin u32 reg, u32 val)
300bc58f211SShawn Lin {
301bc58f211SShawn Lin u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
302bc58f211SShawn Lin void __iomem *base = rk_pcie->dbi_base;
303bc58f211SShawn Lin
304bc58f211SShawn Lin writel(val, base + offset + reg);
305bc58f211SShawn Lin }
306bc58f211SShawn Lin
rk_pcie_readl_ob_unroll(struct rk_pcie * rk_pcie,u32 index,u32 reg)307bc58f211SShawn Lin static u32 rk_pcie_readl_ob_unroll(struct rk_pcie *rk_pcie, u32 index, u32 reg)
308bc58f211SShawn Lin {
309bc58f211SShawn Lin u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
310bc58f211SShawn Lin void __iomem *base = rk_pcie->dbi_base;
311bc58f211SShawn Lin
312bc58f211SShawn Lin return readl(base + offset + reg);
313bc58f211SShawn Lin }
314bc58f211SShawn Lin
rk_pcie_dbi_write_enable(struct rk_pcie * rk_pcie,bool en)315bc58f211SShawn Lin static inline void rk_pcie_dbi_write_enable(struct rk_pcie *rk_pcie, bool en)
316bc58f211SShawn Lin {
317bc58f211SShawn Lin u32 val;
318bc58f211SShawn Lin
319bc58f211SShawn Lin val = readl(rk_pcie->dbi_base + PCIE_MISC_CONTROL_1_OFF);
320bc58f211SShawn Lin
321bc58f211SShawn Lin if (en)
322bc58f211SShawn Lin val |= PCIE_DBI_RO_WR_EN;
323bc58f211SShawn Lin else
324bc58f211SShawn Lin val &= ~PCIE_DBI_RO_WR_EN;
325bc58f211SShawn Lin writel(val, rk_pcie->dbi_base + PCIE_MISC_CONTROL_1_OFF);
326bc58f211SShawn Lin }
327bc58f211SShawn Lin
rk_pcie_setup_host(struct rk_pcie * rk_pcie)328bc58f211SShawn Lin static void rk_pcie_setup_host(struct rk_pcie *rk_pcie)
329bc58f211SShawn Lin {
330bc58f211SShawn Lin u32 val;
331bc58f211SShawn Lin
332bc58f211SShawn Lin rk_pcie_dbi_write_enable(rk_pcie, true);
333bc58f211SShawn Lin
334bc58f211SShawn Lin /* setup RC BARs */
335bc58f211SShawn Lin writel(PCI_BASE_ADDRESS_MEM_TYPE_64,
336bc58f211SShawn Lin rk_pcie->dbi_base + PCI_BASE_ADDRESS_0);
337bc58f211SShawn Lin writel(0x0, rk_pcie->dbi_base + PCI_BASE_ADDRESS_1);
338bc58f211SShawn Lin
339bc58f211SShawn Lin /* setup interrupt pins */
340bc58f211SShawn Lin val = readl(rk_pcie->dbi_base + PCI_INTERRUPT_LINE);
341bc58f211SShawn Lin val &= 0xffff00ff;
342bc58f211SShawn Lin val |= 0x00000100;
343bc58f211SShawn Lin writel(val, rk_pcie->dbi_base + PCI_INTERRUPT_LINE);
344bc58f211SShawn Lin
345bc58f211SShawn Lin /* setup bus numbers */
346bc58f211SShawn Lin val = readl(rk_pcie->dbi_base + PCI_PRIMARY_BUS);
347bc58f211SShawn Lin val &= 0xff000000;
348bc58f211SShawn Lin val |= 0x00ff0100;
349bc58f211SShawn Lin writel(val, rk_pcie->dbi_base + PCI_PRIMARY_BUS);
350bc58f211SShawn Lin
351bc58f211SShawn Lin val = readl(rk_pcie->dbi_base + PCI_PRIMARY_BUS);
352bc58f211SShawn Lin
353bc58f211SShawn Lin /* setup command register */
354bc58f211SShawn Lin val = readl(rk_pcie->dbi_base + PCI_COMMAND);
355bc58f211SShawn Lin val &= 0xffff0000;
356bc58f211SShawn Lin val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
357bc58f211SShawn Lin PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
358bc58f211SShawn Lin writel(val, rk_pcie->dbi_base + PCI_COMMAND);
359bc58f211SShawn Lin
360bc58f211SShawn Lin /* program correct class for RC */
361bc58f211SShawn Lin writew(PCI_CLASS_BRIDGE_PCI, rk_pcie->dbi_base + PCI_CLASS_DEVICE);
362bc58f211SShawn Lin /* Better disable write permission right after the update */
363bc58f211SShawn Lin
364bc58f211SShawn Lin val = readl(rk_pcie->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
365bc58f211SShawn Lin val |= PORT_LOGIC_SPEED_CHANGE;
366bc58f211SShawn Lin writel(val, rk_pcie->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
367bc58f211SShawn Lin
3681f452320SJon Lin /* Disable BAR0 BAR1 */
3691f452320SJon Lin writel(0, rk_pcie->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + 0 * 4);
3701f452320SJon Lin writel(0, rk_pcie->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + 1 * 4);
3711f452320SJon Lin
372bc58f211SShawn Lin rk_pcie_dbi_write_enable(rk_pcie, false);
373bc58f211SShawn Lin }
374bc58f211SShawn Lin
rk_pcie_configure(struct rk_pcie * pci,u32 cap_speed,u32 cap_lanes)375b8495bb7SShawn Lin static void rk_pcie_configure(struct rk_pcie *pci, u32 cap_speed, u32 cap_lanes)
376bc58f211SShawn Lin {
377bc58f211SShawn Lin u32 val;
378bc58f211SShawn Lin
379bc58f211SShawn Lin rk_pcie_dbi_write_enable(pci, true);
380bc58f211SShawn Lin
381bc58f211SShawn Lin val = readl(pci->dbi_base + PCIE_LINK_CAPABILITY);
382bc58f211SShawn Lin val &= ~TARGET_LINK_SPEED_MASK;
383bc58f211SShawn Lin val |= cap_speed;
384bc58f211SShawn Lin writel(val, pci->dbi_base + PCIE_LINK_CAPABILITY);
385bc58f211SShawn Lin
386bc58f211SShawn Lin val = readl(pci->dbi_base + PCIE_LINK_CTL_2);
387bc58f211SShawn Lin val &= ~TARGET_LINK_SPEED_MASK;
388bc58f211SShawn Lin val |= cap_speed;
389bc58f211SShawn Lin writel(val, pci->dbi_base + PCIE_LINK_CTL_2);
390bc58f211SShawn Lin
391b8495bb7SShawn Lin val = readl(pci->dbi_base + PCIE_PORT_LINK_CONTROL);
392b8495bb7SShawn Lin
393b8495bb7SShawn Lin /* Set the number of lanes */
394b8495bb7SShawn Lin val &= ~PORT_LINK_FAST_LINK_MODE;
395b8495bb7SShawn Lin val &= ~PORT_LINK_MODE_MASK;
396b8495bb7SShawn Lin switch (cap_lanes) {
397b8495bb7SShawn Lin case 1:
398b8495bb7SShawn Lin val |= PORT_LINK_MODE_1_LANES;
399b8495bb7SShawn Lin break;
400b8495bb7SShawn Lin case 2:
401b8495bb7SShawn Lin val |= PORT_LINK_MODE_2_LANES;
402b8495bb7SShawn Lin break;
403b8495bb7SShawn Lin case 4:
404b8495bb7SShawn Lin val |= PORT_LINK_MODE_4_LANES;
405b8495bb7SShawn Lin break;
406b8495bb7SShawn Lin case 8:
407b8495bb7SShawn Lin val |= PORT_LINK_MODE_8_LANES;
408b8495bb7SShawn Lin break;
409b8495bb7SShawn Lin default:
410b8495bb7SShawn Lin dev_err(pci->dev, "cap_lanes %u: invalid value\n", cap_lanes);
411b8495bb7SShawn Lin return;
412b8495bb7SShawn Lin }
413b8495bb7SShawn Lin writel(val, pci->dbi_base + PCIE_PORT_LINK_CONTROL);
414b8495bb7SShawn Lin
415b8495bb7SShawn Lin /* Set link width speed control register */
416b8495bb7SShawn Lin val = readl(pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
417b8495bb7SShawn Lin val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
418b8495bb7SShawn Lin switch (cap_lanes) {
419b8495bb7SShawn Lin case 1:
420b8495bb7SShawn Lin val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
421b8495bb7SShawn Lin break;
422b8495bb7SShawn Lin case 2:
423b8495bb7SShawn Lin val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
424b8495bb7SShawn Lin break;
425b8495bb7SShawn Lin case 4:
426b8495bb7SShawn Lin val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
427b8495bb7SShawn Lin break;
428b8495bb7SShawn Lin case 8:
429b8495bb7SShawn Lin val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
430b8495bb7SShawn Lin break;
431b8495bb7SShawn Lin }
432b8495bb7SShawn Lin writel(val, pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
433b8495bb7SShawn Lin
434bc58f211SShawn Lin rk_pcie_dbi_write_enable(pci, false);
435bc58f211SShawn Lin }
436bc58f211SShawn Lin
rk_pcie_prog_outbound_atu_unroll(struct rk_pcie * pci,int index,int type,u64 cpu_addr,u64 pci_addr,u32 size)437bc58f211SShawn Lin static void rk_pcie_prog_outbound_atu_unroll(struct rk_pcie *pci, int index,
438bc58f211SShawn Lin int type, u64 cpu_addr,
439bc58f211SShawn Lin u64 pci_addr, u32 size)
440bc58f211SShawn Lin {
441bc58f211SShawn Lin u32 retries, val;
442bc58f211SShawn Lin
443bc58f211SShawn Lin dev_dbg(pci->dev, "ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n",
444bc58f211SShawn Lin index, type, cpu_addr, pci_addr, size);
445bc58f211SShawn Lin
446bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
447bc58f211SShawn Lin lower_32_bits(cpu_addr));
448bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
449bc58f211SShawn Lin upper_32_bits(cpu_addr));
450bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
451bc58f211SShawn Lin lower_32_bits(cpu_addr + size - 1));
452bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
453bc58f211SShawn Lin lower_32_bits(pci_addr));
454bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
455bc58f211SShawn Lin upper_32_bits(pci_addr));
456bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
457bc58f211SShawn Lin type);
458bc58f211SShawn Lin rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
459bc58f211SShawn Lin PCIE_ATU_ENABLE);
460bc58f211SShawn Lin
461bc58f211SShawn Lin /*
462bc58f211SShawn Lin * Make sure ATU enable takes effect before any subsequent config
463bc58f211SShawn Lin * and I/O accesses.
464bc58f211SShawn Lin */
465bc58f211SShawn Lin for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
466bc58f211SShawn Lin val = rk_pcie_readl_ob_unroll(pci, index,
467bc58f211SShawn Lin PCIE_ATU_UNR_REGION_CTRL2);
468bc58f211SShawn Lin if (val & PCIE_ATU_ENABLE)
469bc58f211SShawn Lin return;
470bc58f211SShawn Lin
471bc58f211SShawn Lin udelay(LINK_WAIT_IATU);
472bc58f211SShawn Lin }
473bc58f211SShawn Lin dev_err(pci->dev, "outbound iATU is not being enabled\n");
474bc58f211SShawn Lin }
475bc58f211SShawn Lin
rk_pcie_addr_valid(pci_dev_t d,int first_busno)476bc58f211SShawn Lin static int rk_pcie_addr_valid(pci_dev_t d, int first_busno)
477bc58f211SShawn Lin {
478bc58f211SShawn Lin if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0))
479bc58f211SShawn Lin return 0;
480bc58f211SShawn Lin if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0))
481bc58f211SShawn Lin return 0;
482bc58f211SShawn Lin
483bc58f211SShawn Lin return 1;
484bc58f211SShawn Lin }
485bc58f211SShawn Lin
set_cfg_address(struct rk_pcie * pcie,pci_dev_t d,uint where)486bc58f211SShawn Lin static uintptr_t set_cfg_address(struct rk_pcie *pcie,
487bc58f211SShawn Lin pci_dev_t d, uint where)
488bc58f211SShawn Lin {
489bc58f211SShawn Lin int bus = PCI_BUS(d) - pcie->first_busno;
490bc58f211SShawn Lin uintptr_t va_address;
491bc58f211SShawn Lin u32 atu_type;
492bc58f211SShawn Lin
493bc58f211SShawn Lin /* Use dbi_base for own configuration read and write */
494bc58f211SShawn Lin if (!bus) {
495bc58f211SShawn Lin va_address = (uintptr_t)pcie->dbi_base;
496bc58f211SShawn Lin goto out;
497bc58f211SShawn Lin }
498bc58f211SShawn Lin
499bc58f211SShawn Lin if (bus == 1)
500bc58f211SShawn Lin /*
501bc58f211SShawn Lin * For local bus whose primary bus number is root bridge,
502bc58f211SShawn Lin * change TLP Type field to 4.
503bc58f211SShawn Lin */
504bc58f211SShawn Lin atu_type = PCIE_ATU_TYPE_CFG0;
505bc58f211SShawn Lin else
506bc58f211SShawn Lin /* Otherwise, change TLP Type field to 5. */
507bc58f211SShawn Lin atu_type = PCIE_ATU_TYPE_CFG1;
508bc58f211SShawn Lin
509bc58f211SShawn Lin /*
510bc58f211SShawn Lin * Not accessing root port configuration space?
511bc58f211SShawn Lin * Region #0 is used for Outbound CFG space access.
512bc58f211SShawn Lin * Direction = Outbound
513bc58f211SShawn Lin * Region Index = 0
514bc58f211SShawn Lin */
515bc58f211SShawn Lin d = PCI_MASK_BUS(d);
516bc58f211SShawn Lin d = PCI_ADD_BUS(bus, d);
517bc58f211SShawn Lin rk_pcie_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
518bc58f211SShawn Lin atu_type, (u64)pcie->cfg_base,
519bc58f211SShawn Lin d << 8, pcie->cfg_size);
520bc58f211SShawn Lin
521bc58f211SShawn Lin va_address = (uintptr_t)pcie->cfg_base;
522bc58f211SShawn Lin
523bc58f211SShawn Lin out:
524bc58f211SShawn Lin va_address += where & ~0x3;
525bc58f211SShawn Lin
526bc58f211SShawn Lin return va_address;
527bc58f211SShawn Lin }
528bc58f211SShawn Lin
rockchip_pcie_rd_conf(struct udevice * bus,pci_dev_t bdf,uint offset,ulong * valuep,enum pci_size_t size)529bc58f211SShawn Lin static int rockchip_pcie_rd_conf(struct udevice *bus, pci_dev_t bdf,
530bc58f211SShawn Lin uint offset, ulong *valuep,
531bc58f211SShawn Lin enum pci_size_t size)
532bc58f211SShawn Lin {
533bc58f211SShawn Lin struct rk_pcie *pcie = dev_get_priv(bus);
534bc58f211SShawn Lin uintptr_t va_address;
535bc58f211SShawn Lin ulong value;
536bc58f211SShawn Lin
537bc58f211SShawn Lin debug("PCIE CFG read: bdf=%2x:%2x:%2x\n",
538bc58f211SShawn Lin PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
539bc58f211SShawn Lin
540bc58f211SShawn Lin if (!rk_pcie_addr_valid(bdf, pcie->first_busno)) {
541bc58f211SShawn Lin debug("- out of range\n");
542bc58f211SShawn Lin *valuep = pci_get_ff(size);
543bc58f211SShawn Lin return 0;
544bc58f211SShawn Lin }
545bc58f211SShawn Lin
546bc58f211SShawn Lin va_address = set_cfg_address(pcie, bdf, offset);
547bc58f211SShawn Lin
548bc58f211SShawn Lin value = readl(va_address);
549bc58f211SShawn Lin
550bc58f211SShawn Lin debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
551bc58f211SShawn Lin *valuep = pci_conv_32_to_size(value, offset, size);
552bc58f211SShawn Lin
553bc58f211SShawn Lin rk_pcie_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
554bc58f211SShawn Lin PCIE_ATU_TYPE_IO, pcie->io.phys_start,
555bc58f211SShawn Lin pcie->io.bus_start, pcie->io.size);
556bc58f211SShawn Lin
557bc58f211SShawn Lin return 0;
558bc58f211SShawn Lin }
559bc58f211SShawn Lin
rockchip_pcie_wr_conf(struct udevice * bus,pci_dev_t bdf,uint offset,ulong value,enum pci_size_t size)560bc58f211SShawn Lin static int rockchip_pcie_wr_conf(struct udevice *bus, pci_dev_t bdf,
561bc58f211SShawn Lin uint offset, ulong value,
562bc58f211SShawn Lin enum pci_size_t size)
563bc58f211SShawn Lin {
564bc58f211SShawn Lin struct rk_pcie *pcie = dev_get_priv(bus);
565bc58f211SShawn Lin uintptr_t va_address;
566bc58f211SShawn Lin ulong old;
567bc58f211SShawn Lin
568bc58f211SShawn Lin debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d)\n",
569bc58f211SShawn Lin PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
570bc58f211SShawn Lin debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
571bc58f211SShawn Lin if (!rk_pcie_addr_valid(bdf, pcie->first_busno)) {
572bc58f211SShawn Lin debug("- out of range\n");
573bc58f211SShawn Lin return 0;
574bc58f211SShawn Lin }
575bc58f211SShawn Lin
576bc58f211SShawn Lin va_address = set_cfg_address(pcie, bdf, offset);
577bc58f211SShawn Lin
578bc58f211SShawn Lin old = readl(va_address);
579bc58f211SShawn Lin value = pci_conv_size_to_32(old, value, offset, size);
580bc58f211SShawn Lin writel(value, va_address);
581bc58f211SShawn Lin
582bc58f211SShawn Lin rk_pcie_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
583bc58f211SShawn Lin PCIE_ATU_TYPE_IO, pcie->io.phys_start,
584bc58f211SShawn Lin pcie->io.bus_start, pcie->io.size);
585bc58f211SShawn Lin
586bc58f211SShawn Lin return 0;
587bc58f211SShawn Lin }
588bc58f211SShawn Lin
rk_pcie_enable_debug(struct rk_pcie * rk_pcie)589bc58f211SShawn Lin static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
590bc58f211SShawn Lin {
591bc58f211SShawn Lin #if RK_PCIE_DBG
592bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0,
593bc58f211SShawn Lin PCIE_CLIENT_DBG_TRANSITION_DATA);
594bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1,
595bc58f211SShawn Lin PCIE_CLIENT_DBG_TRANSITION_DATA);
596bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0,
597bc58f211SShawn Lin PCIE_CLIENT_DBG_TRANSITION_DATA);
598bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1,
599bc58f211SShawn Lin PCIE_CLIENT_DBG_TRANSITION_DATA);
600bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_MODE_CON,
601bc58f211SShawn Lin PCIE_CLIENT_DBF_EN);
602bc58f211SShawn Lin #endif
603bc58f211SShawn Lin }
604bc58f211SShawn Lin
rk_pcie_debug_dump(struct rk_pcie * rk_pcie)605bc58f211SShawn Lin static void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
606bc58f211SShawn Lin {
607bc58f211SShawn Lin #if RK_PCIE_DBG
608bc58f211SShawn Lin u32 loop;
609bc58f211SShawn Lin
6100e16653bSJon Lin dev_err(rk_pcie->dev, "ltssm = 0x%x\n",
611bc58f211SShawn Lin rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
612bc58f211SShawn Lin for (loop = 0; loop < 64; loop++)
6130e16653bSJon Lin dev_err(rk_pcie->dev, "fifo_status = 0x%x\n",
614bc58f211SShawn Lin rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_STATUS));
615bc58f211SShawn Lin #endif
616bc58f211SShawn Lin }
617bc58f211SShawn Lin
rk_pcie_link_status_clear(struct rk_pcie * rk_pcie)618bc58f211SShawn Lin static inline void rk_pcie_link_status_clear(struct rk_pcie *rk_pcie)
619bc58f211SShawn Lin {
620bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG, 0x0);
621bc58f211SShawn Lin }
622bc58f211SShawn Lin
rk_pcie_disable_ltssm(struct rk_pcie * rk_pcie)623bc58f211SShawn Lin static inline void rk_pcie_disable_ltssm(struct rk_pcie *rk_pcie)
624bc58f211SShawn Lin {
625bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, 0x0, 0xc0008);
626bc58f211SShawn Lin }
627bc58f211SShawn Lin
rk_pcie_enable_ltssm(struct rk_pcie * rk_pcie)628bc58f211SShawn Lin static inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie)
629bc58f211SShawn Lin {
630bc58f211SShawn Lin rk_pcie_writel_apb(rk_pcie, 0x0, 0xc000c);
631bc58f211SShawn Lin }
632bc58f211SShawn Lin
is_link_up(struct rk_pcie * priv)633bc58f211SShawn Lin static int is_link_up(struct rk_pcie *priv)
634bc58f211SShawn Lin {
635bc58f211SShawn Lin u32 val;
636bc58f211SShawn Lin
637bc58f211SShawn Lin val = rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS);
638bc58f211SShawn Lin if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000 &&
639bc58f211SShawn Lin (val & GENMASK(5, 0)) == 0x11)
640bc58f211SShawn Lin return 1;
641bc58f211SShawn Lin
642bc58f211SShawn Lin return 0;
643bc58f211SShawn Lin }
644bc58f211SShawn Lin
rk_pcie_link_up(struct rk_pcie * priv,u32 cap_speed,u32 cap_lanes)645b8495bb7SShawn Lin static int rk_pcie_link_up(struct rk_pcie *priv, u32 cap_speed, u32 cap_lanes)
646bc58f211SShawn Lin {
647bc58f211SShawn Lin int retries;
648bc58f211SShawn Lin
649bc58f211SShawn Lin if (is_link_up(priv)) {
650bc58f211SShawn Lin printf("PCI Link already up before configuration!\n");
651bc58f211SShawn Lin return 1;
652bc58f211SShawn Lin }
653bc58f211SShawn Lin
654bc58f211SShawn Lin /* DW pre link configurations */
655b8495bb7SShawn Lin rk_pcie_configure(priv, cap_speed, cap_lanes);
656bc58f211SShawn Lin
65792d35878SJon Lin /* Release the device */
6586d508927SJon Lin if (dm_gpio_is_valid(&priv->rst_gpio)) {
6596d508927SJon Lin /*
6606d508927SJon Lin * T_PVPERL (Power stable to PERST# inactive) should be a minimum of 100ms.
6616d508927SJon Lin * We add a 200ms by default for sake of hoping everthings
6626d508927SJon Lin * work fine.
6636d508927SJon Lin */
6646d508927SJon Lin msleep(200);
665bc58f211SShawn Lin dm_gpio_set_value(&priv->rst_gpio, 1);
6666d508927SJon Lin /*
6676d508927SJon Lin * Add this 20ms delay because we observe link is always up stably after it and
6686d508927SJon Lin * could help us save 20ms for scanning devices.
6696d508927SJon Lin */
6706d508927SJon Lin msleep(20);
6716d508927SJon Lin }
672bc58f211SShawn Lin
673bc58f211SShawn Lin rk_pcie_disable_ltssm(priv);
674bc58f211SShawn Lin rk_pcie_link_status_clear(priv);
675bc58f211SShawn Lin rk_pcie_enable_debug(priv);
676bc58f211SShawn Lin
677bc58f211SShawn Lin /* Enable LTSSM */
678bc58f211SShawn Lin rk_pcie_enable_ltssm(priv);
679bc58f211SShawn Lin
680beef0f23SShawn Lin for (retries = 0; retries < 50; retries++) {
681bc58f211SShawn Lin if (is_link_up(priv)) {
682bc58f211SShawn Lin dev_info(priv->dev, "PCIe Link up, LTSSM is 0x%x\n",
683bc58f211SShawn Lin rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
684bc58f211SShawn Lin rk_pcie_debug_dump(priv);
685ff2f1e41SShawn Lin /* Link maybe in Gen switch recovery but we need to wait more 1s */
686ff2f1e41SShawn Lin msleep(1000);
687bc58f211SShawn Lin return 0;
688bc58f211SShawn Lin }
689bc58f211SShawn Lin
690bc58f211SShawn Lin dev_info(priv->dev, "PCIe Linking... LTSSM is 0x%x\n",
691bc58f211SShawn Lin rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
692bc58f211SShawn Lin rk_pcie_debug_dump(priv);
69392d35878SJon Lin msleep(10);
694bc58f211SShawn Lin }
695bc58f211SShawn Lin
696bc58f211SShawn Lin dev_err(priv->dev, "PCIe-%d Link Fail\n", priv->dev->seq);
697b2a4eeb5SShawn Lin rk_pcie_disable_ltssm(priv);
698fec7a75eSShawn Lin if (dm_gpio_is_valid(&priv->rst_gpio))
699fec7a75eSShawn Lin dm_gpio_set_value(&priv->rst_gpio, 0);
700fec7a75eSShawn Lin
701bc58f211SShawn Lin return -EINVAL;
702bc58f211SShawn Lin }
703bc58f211SShawn Lin
rockchip_pcie_init_port(struct udevice * dev)704bc58f211SShawn Lin static int rockchip_pcie_init_port(struct udevice *dev)
705bc58f211SShawn Lin {
706fec7a75eSShawn Lin int ret, retries;
707bc58f211SShawn Lin u32 val;
708bc58f211SShawn Lin struct rk_pcie *priv = dev_get_priv(dev);
709c2482762SShawn Lin union phy_configure_opts phy_cfg;
710bc58f211SShawn Lin
71192d35878SJon Lin /* Rest the device */
71292d35878SJon Lin if (dm_gpio_is_valid(&priv->rst_gpio))
71392d35878SJon Lin dm_gpio_set_value(&priv->rst_gpio, 0);
71492d35878SJon Lin
715bc58f211SShawn Lin /* Set power and maybe external ref clk input */
716bc58f211SShawn Lin if (priv->vpcie3v3) {
71732aabf13SJon Lin ret = regulator_set_enable(priv->vpcie3v3, true);
718bc58f211SShawn Lin if (ret) {
719bc58f211SShawn Lin dev_err(priv->dev, "failed to enable vpcie3v3 (ret=%d)\n",
720bc58f211SShawn Lin ret);
721bc58f211SShawn Lin return ret;
722bc58f211SShawn Lin }
723bc58f211SShawn Lin }
724bc58f211SShawn Lin
725c2482762SShawn Lin if (priv->is_bifurcation) {
726c2482762SShawn Lin phy_cfg.pcie.is_bifurcation = true;
727c2482762SShawn Lin ret = generic_phy_configure(&priv->phy, &phy_cfg);
728c2482762SShawn Lin if (ret)
729c2482762SShawn Lin dev_err(dev, "failed to set bifurcation for phy (ret=%d)\n", ret);
730c2482762SShawn Lin }
731c2482762SShawn Lin
732bc58f211SShawn Lin ret = generic_phy_init(&priv->phy);
733bc58f211SShawn Lin if (ret) {
734bc58f211SShawn Lin dev_err(dev, "failed to init phy (ret=%d)\n", ret);
735b2a4eeb5SShawn Lin goto err_disable_3v3;
736bc58f211SShawn Lin }
737bc58f211SShawn Lin
738bc58f211SShawn Lin ret = generic_phy_power_on(&priv->phy);
739bc58f211SShawn Lin if (ret) {
740bc58f211SShawn Lin dev_err(dev, "failed to power on phy (ret=%d)\n", ret);
741bc58f211SShawn Lin goto err_exit_phy;
742bc58f211SShawn Lin }
743bc58f211SShawn Lin
744bc58f211SShawn Lin ret = reset_deassert_bulk(&priv->rsts);
745bc58f211SShawn Lin if (ret) {
746bc58f211SShawn Lin dev_err(dev, "failed to deassert resets (ret=%d)\n", ret);
747bc58f211SShawn Lin goto err_power_off_phy;
748bc58f211SShawn Lin }
749bc58f211SShawn Lin
750bc58f211SShawn Lin ret = clk_enable_bulk(&priv->clks);
751bc58f211SShawn Lin if (ret) {
752bc58f211SShawn Lin dev_err(dev, "failed to enable clks (ret=%d)\n", ret);
753bc58f211SShawn Lin goto err_deassert_bulk;
754bc58f211SShawn Lin }
755bc58f211SShawn Lin
756bc58f211SShawn Lin /* LTSSM EN ctrl mode */
757bc58f211SShawn Lin val = rk_pcie_readl_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL);
758bc58f211SShawn Lin val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
759bc58f211SShawn Lin rk_pcie_writel_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL, val);
760bc58f211SShawn Lin
761bc58f211SShawn Lin /* Set RC mode */
762bc58f211SShawn Lin rk_pcie_writel_apb(priv, 0x0, 0xf00040);
763bc58f211SShawn Lin rk_pcie_setup_host(priv);
764bc58f211SShawn Lin
765fec7a75eSShawn Lin for (retries = MAX_LINKUP_RETRIES; retries > 0; retries--) {
766b8495bb7SShawn Lin ret = rk_pcie_link_up(priv, priv->gen, priv->lanes);
767fec7a75eSShawn Lin if (ret >= 0)
768fec7a75eSShawn Lin return 0;
769fec7a75eSShawn Lin if(priv->vpcie3v3) {
770fec7a75eSShawn Lin regulator_set_enable(priv->vpcie3v3, false);
771fec7a75eSShawn Lin msleep(200);
772fec7a75eSShawn Lin regulator_set_enable(priv->vpcie3v3, true);
773fec7a75eSShawn Lin }
774fec7a75eSShawn Lin }
775fec7a75eSShawn Lin
776fec7a75eSShawn Lin if (retries <= 0)
777bc58f211SShawn Lin goto err_link_up;
778bc58f211SShawn Lin
779bc58f211SShawn Lin return 0;
780bc58f211SShawn Lin err_link_up:
781bc58f211SShawn Lin clk_disable_bulk(&priv->clks);
782bc58f211SShawn Lin err_deassert_bulk:
783bc58f211SShawn Lin reset_assert_bulk(&priv->rsts);
784bc58f211SShawn Lin err_power_off_phy:
78568abe0efSShawn Lin if (!priv->is_bifurcation)
786bc58f211SShawn Lin generic_phy_power_off(&priv->phy);
787bc58f211SShawn Lin err_exit_phy:
78868abe0efSShawn Lin if (!priv->is_bifurcation)
789bc58f211SShawn Lin generic_phy_exit(&priv->phy);
790b2a4eeb5SShawn Lin err_disable_3v3:
79168abe0efSShawn Lin if(priv->vpcie3v3 && !priv->is_bifurcation)
792b2a4eeb5SShawn Lin regulator_set_enable(priv->vpcie3v3, false);
793bc58f211SShawn Lin return ret;
794bc58f211SShawn Lin }
795bc58f211SShawn Lin
rockchip_pcie_parse_dt(struct udevice * dev)796bc58f211SShawn Lin static int rockchip_pcie_parse_dt(struct udevice *dev)
797bc58f211SShawn Lin {
798bc58f211SShawn Lin struct rk_pcie *priv = dev_get_priv(dev);
799b8495bb7SShawn Lin u32 max_link_speed, num_lanes;
800bc58f211SShawn Lin int ret;
801fbc8ca74SJon Lin struct resource res;
802bc58f211SShawn Lin
803fbc8ca74SJon Lin ret = dev_read_resource_byname(dev, "pcie-dbi", &res);
804fbc8ca74SJon Lin if (ret)
805bc58f211SShawn Lin return -ENODEV;
806fbc8ca74SJon Lin priv->dbi_base = (void *)(res.start);
807bc58f211SShawn Lin dev_dbg(dev, "DBI address is 0x%p\n", priv->dbi_base);
808bc58f211SShawn Lin
809fbc8ca74SJon Lin ret = dev_read_resource_byname(dev, "pcie-apb", &res);
810fbc8ca74SJon Lin if (ret)
811bc58f211SShawn Lin return -ENODEV;
812fbc8ca74SJon Lin priv->apb_base = (void *)(res.start);
813bc58f211SShawn Lin dev_dbg(dev, "APB address is 0x%p\n", priv->apb_base);
814bc58f211SShawn Lin
815bc58f211SShawn Lin ret = gpio_request_by_name(dev, "reset-gpios", 0,
816bc58f211SShawn Lin &priv->rst_gpio, GPIOD_IS_OUT);
817bc58f211SShawn Lin if (ret) {
818bc58f211SShawn Lin dev_err(dev, "failed to find reset-gpios property\n");
819bc58f211SShawn Lin return ret;
820bc58f211SShawn Lin }
821bc58f211SShawn Lin
822bc58f211SShawn Lin ret = reset_get_bulk(dev, &priv->rsts);
823bc58f211SShawn Lin if (ret) {
824bc58f211SShawn Lin dev_err(dev, "Can't get reset: %d\n", ret);
825bc58f211SShawn Lin return ret;
826bc58f211SShawn Lin }
827bc58f211SShawn Lin
828bc58f211SShawn Lin ret = clk_get_bulk(dev, &priv->clks);
829bc58f211SShawn Lin if (ret) {
830bc58f211SShawn Lin dev_err(dev, "Can't get clock: %d\n", ret);
831bc58f211SShawn Lin return ret;
832bc58f211SShawn Lin }
833bc58f211SShawn Lin
834bc58f211SShawn Lin ret = device_get_supply_regulator(dev, "vpcie3v3-supply",
835bc58f211SShawn Lin &priv->vpcie3v3);
836bc58f211SShawn Lin if (ret && ret != -ENOENT) {
837bc58f211SShawn Lin dev_err(dev, "failed to get vpcie3v3 supply (ret=%d)\n", ret);
838bc58f211SShawn Lin return ret;
839bc58f211SShawn Lin }
840bc58f211SShawn Lin
841bc58f211SShawn Lin ret = generic_phy_get_by_index(dev, 0, &priv->phy);
842bc58f211SShawn Lin if (ret) {
843bc58f211SShawn Lin dev_err(dev, "failed to get pcie phy (ret=%d)\n", ret);
844bc58f211SShawn Lin return ret;
845bc58f211SShawn Lin }
846bc58f211SShawn Lin
847c2482762SShawn Lin if (dev_read_bool(dev, "rockchip,bifurcation"))
848c2482762SShawn Lin priv->is_bifurcation = true;
849c2482762SShawn Lin
850abcec002SJon Lin ret = ofnode_read_u32(dev->node, "max-link-speed", &max_link_speed);
851abcec002SJon Lin if (ret < 0 || max_link_speed > 4)
852abcec002SJon Lin priv->gen = 0;
853abcec002SJon Lin else
854abcec002SJon Lin priv->gen = max_link_speed;
855abcec002SJon Lin
856b8495bb7SShawn Lin ret = ofnode_read_u32(dev->node, "num-lanes", &num_lanes);
857b8495bb7SShawn Lin if (ret >= 0 && ilog2(num_lanes) >= 0 && ilog2(num_lanes) <= 3)
858b8495bb7SShawn Lin priv->lanes = num_lanes;
859b8495bb7SShawn Lin
860bc58f211SShawn Lin return 0;
861bc58f211SShawn Lin }
862bc58f211SShawn Lin
rockchip_pcie_probe(struct udevice * dev)863bc58f211SShawn Lin static int rockchip_pcie_probe(struct udevice *dev)
864bc58f211SShawn Lin {
865bc58f211SShawn Lin struct rk_pcie *priv = dev_get_priv(dev);
866bc58f211SShawn Lin struct udevice *ctlr = pci_get_controller(dev);
867bc58f211SShawn Lin struct pci_controller *hose = dev_get_uclass_priv(ctlr);
868bc58f211SShawn Lin int ret;
869bc58f211SShawn Lin
870bc58f211SShawn Lin priv->first_busno = dev->seq;
871bc58f211SShawn Lin priv->dev = dev;
872bc58f211SShawn Lin
873bc58f211SShawn Lin ret = rockchip_pcie_parse_dt(dev);
874bc58f211SShawn Lin if (ret)
875bc58f211SShawn Lin return ret;
876bc58f211SShawn Lin
877bc58f211SShawn Lin ret = rockchip_pcie_init_port(dev);
878bc58f211SShawn Lin if (ret)
879b2a4eeb5SShawn Lin goto free_rst;
880bc58f211SShawn Lin
881bc58f211SShawn Lin dev_info(dev, "PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
882bc58f211SShawn Lin dev->seq, rk_pcie_get_link_speed(priv),
883bc58f211SShawn Lin rk_pcie_get_link_width(priv),
884bc58f211SShawn Lin hose->first_busno);
885bc58f211SShawn Lin
886bc58f211SShawn Lin for (ret = 0; ret < hose->region_count; ret++) {
887bc58f211SShawn Lin if (hose->regions[ret].flags == PCI_REGION_IO) {
888bc58f211SShawn Lin priv->io.phys_start = hose->regions[ret].phys_start; /* IO base */
889bc58f211SShawn Lin priv->io.bus_start = hose->regions[ret].bus_start; /* IO_bus_addr */
890bc58f211SShawn Lin priv->io.size = hose->regions[ret].size; /* IO size */
891bc58f211SShawn Lin } else if (hose->regions[ret].flags == PCI_REGION_MEM) {
8927ff76e75SShawn Lin if (upper_32_bits(hose->regions[ret].bus_start)) {/* MEM64 base */
8937ff76e75SShawn Lin priv->mem64.phys_start = hose->regions[ret].phys_start;
8947ff76e75SShawn Lin priv->mem64.bus_start = hose->regions[ret].bus_start;
8957ff76e75SShawn Lin priv->mem64.size = hose->regions[ret].size;
8967ff76e75SShawn Lin } else { /* MEM32 base */
8977ff76e75SShawn Lin priv->mem.phys_start = hose->regions[ret].phys_start;
8987ff76e75SShawn Lin priv->mem.bus_start = hose->regions[ret].bus_start;
8997ff76e75SShawn Lin priv->mem.size = hose->regions[ret].size;
9007ff76e75SShawn Lin }
901bc58f211SShawn Lin } else if (hose->regions[ret].flags == PCI_REGION_SYS_MEMORY) {
902bc58f211SShawn Lin priv->cfg_base = (void *)(priv->io.phys_start - priv->io.size);
903bc58f211SShawn Lin priv->cfg_size = priv->io.size;
9047ff76e75SShawn Lin } else if (hose->regions[ret].flags == PCI_REGION_PREFETCH) {
9057ff76e75SShawn Lin dev_err(dev, "don't support prefetchable memory, please fix your dtb.\n");
906bc58f211SShawn Lin } else {
9077ff76e75SShawn Lin dev_err(dev, "invalid flags type\n");
908bc58f211SShawn Lin }
909bc58f211SShawn Lin }
910bc58f211SShawn Lin
9117ff76e75SShawn Lin #ifdef CONFIG_SYS_PCI_64BIT
9127ff76e75SShawn Lin dev_dbg(dev, "Config space: [0x%p - 0x%p, size 0x%llx]\n",
9137ff76e75SShawn Lin priv->cfg_base, priv->cfg_base + priv->cfg_size,
9147ff76e75SShawn Lin priv->cfg_size);
9157ff76e75SShawn Lin
9167ff76e75SShawn Lin dev_dbg(dev, "IO space: [0x%llx - 0x%llx, size 0x%llx]\n",
9177ff76e75SShawn Lin priv->io.phys_start, priv->io.phys_start + priv->io.size,
9187ff76e75SShawn Lin priv->io.size);
9197ff76e75SShawn Lin
9207ff76e75SShawn Lin dev_dbg(dev, "IO bus: [0x%llx - 0x%llx, size 0x%llx]\n",
9217ff76e75SShawn Lin priv->io.bus_start, priv->io.bus_start + priv->io.size,
9227ff76e75SShawn Lin priv->io.size);
9237ff76e75SShawn Lin
9247ff76e75SShawn Lin dev_dbg(dev, "MEM32 space: [0x%llx - 0x%llx, size 0x%llx]\n",
9257ff76e75SShawn Lin priv->mem.phys_start, priv->mem.phys_start + priv->mem.size,
9267ff76e75SShawn Lin priv->mem.size);
9277ff76e75SShawn Lin
9287ff76e75SShawn Lin dev_dbg(dev, "MEM32 bus: [0x%llx - 0x%llx, size 0x%llx]\n",
9297ff76e75SShawn Lin priv->mem.bus_start, priv->mem.bus_start + priv->mem.size,
9307ff76e75SShawn Lin priv->mem.size);
9317ff76e75SShawn Lin
9327ff76e75SShawn Lin dev_dbg(dev, "MEM64 space: [0x%llx - 0x%llx, size 0x%llx]\n",
9337ff76e75SShawn Lin priv->mem64.phys_start, priv->mem64.phys_start + priv->mem64.size,
9347ff76e75SShawn Lin priv->mem64.size);
9357ff76e75SShawn Lin
9367ff76e75SShawn Lin dev_dbg(dev, "MEM64 bus: [0x%llx - 0x%llx, size 0x%llx]\n",
9377ff76e75SShawn Lin priv->mem64.bus_start, priv->mem64.bus_start + priv->mem64.size,
9387ff76e75SShawn Lin priv->mem64.size);
9397ff76e75SShawn Lin
9407ff76e75SShawn Lin rk_pcie_prog_outbound_atu_unroll(priv, PCIE_ATU_REGION_INDEX2,
9417ff76e75SShawn Lin PCIE_ATU_TYPE_MEM,
9427ff76e75SShawn Lin priv->mem64.phys_start,
9437ff76e75SShawn Lin priv->mem64.bus_start, priv->mem64.size);
9447ff76e75SShawn Lin #else
945bc58f211SShawn Lin dev_dbg(dev, "Config space: [0x%p - 0x%p, size 0x%llx]\n",
946bc58f211SShawn Lin priv->cfg_base, priv->cfg_base + priv->cfg_size,
947bc58f211SShawn Lin priv->cfg_size);
948bc58f211SShawn Lin
949bc58f211SShawn Lin dev_dbg(dev, "IO space: [0x%llx - 0x%llx, size 0x%x]\n",
950bc58f211SShawn Lin priv->io.phys_start, priv->io.phys_start + priv->io.size,
951bc58f211SShawn Lin priv->io.size);
952bc58f211SShawn Lin
953bc58f211SShawn Lin dev_dbg(dev, "IO bus: [0x%x - 0x%x, size 0x%x]\n",
954bc58f211SShawn Lin priv->io.bus_start, priv->io.bus_start + priv->io.size,
955bc58f211SShawn Lin priv->io.size);
956bc58f211SShawn Lin
9577ff76e75SShawn Lin dev_dbg(dev, "MEM32 space: [0x%llx - 0x%llx, size 0x%x]\n",
958bc58f211SShawn Lin priv->mem.phys_start, priv->mem.phys_start + priv->mem.size,
959bc58f211SShawn Lin priv->mem.size);
960bc58f211SShawn Lin
9617ff76e75SShawn Lin dev_dbg(dev, "MEM32 bus: [0x%x - 0x%x, size 0x%x]\n",
962bc58f211SShawn Lin priv->mem.bus_start, priv->mem.bus_start + priv->mem.size,
963bc58f211SShawn Lin priv->mem.size);
964bc58f211SShawn Lin
9657ff76e75SShawn Lin #endif
966bc58f211SShawn Lin rk_pcie_prog_outbound_atu_unroll(priv, PCIE_ATU_REGION_INDEX0,
967bc58f211SShawn Lin PCIE_ATU_TYPE_MEM,
968bc58f211SShawn Lin priv->mem.phys_start,
969bc58f211SShawn Lin priv->mem.bus_start, priv->mem.size);
9707ff76e75SShawn Lin
971*7ece1cfeSJon Lin priv->rasdes_off = rk_pci_find_ext_capability(priv, PCI_EXT_CAP_ID_VNDR);
972769b1920SShawn Lin if (priv->rasdes_off) {
973fbafd477SShawn Lin /* Enable RC's err dump */
974769b1920SShawn Lin writel(0x1c, priv->dbi_base + priv->rasdes_off + 8);
975769b1920SShawn Lin writel(0x3, priv->dbi_base + priv->rasdes_off + 8);
976769b1920SShawn Lin }
977fbafd477SShawn Lin
978bc58f211SShawn Lin return 0;
979b2a4eeb5SShawn Lin free_rst:
980b2a4eeb5SShawn Lin dm_gpio_free(dev, &priv->rst_gpio);
981b2a4eeb5SShawn Lin return ret;
982bc58f211SShawn Lin }
983bc58f211SShawn Lin
984fbafd477SShawn Lin #define RAS_DES_EVENT(ss, v) \
985fbafd477SShawn Lin do { \
986fbafd477SShawn Lin writel(v, priv->dbi_base + cap_base + 8); \
987fbafd477SShawn Lin printf(ss "0x%x\n", readl(priv->dbi_base + cap_base + 0xc)); \
988fbafd477SShawn Lin } while (0)
989fbafd477SShawn Lin
rockchip_pcie_err_dump(struct udevice * bus)990fbafd477SShawn Lin static int rockchip_pcie_err_dump(struct udevice *bus)
991fbafd477SShawn Lin {
992fbafd477SShawn Lin struct rk_pcie *priv = dev_get_priv(bus);
993fbafd477SShawn Lin u32 val = rk_pcie_readl_apb(priv, PCIE_CLIENT_CDM_RASDES_TBA_INFO_CMN);
994fbafd477SShawn Lin int cap_base;
995fbafd477SShawn Lin char *pm;
996fbafd477SShawn Lin
997fbafd477SShawn Lin if (val & BIT(6))
998fbafd477SShawn Lin pm = "In training";
999fbafd477SShawn Lin else if (val & BIT(5))
1000fbafd477SShawn Lin pm = "L1.2";
1001fbafd477SShawn Lin else if (val & BIT(4))
1002fbafd477SShawn Lin pm = "L1.1";
1003fbafd477SShawn Lin else if (val & BIT(3))
1004fbafd477SShawn Lin pm = "L1";
1005fbafd477SShawn Lin else if (val & BIT(2))
1006fbafd477SShawn Lin pm = "L0";
1007fbafd477SShawn Lin else if (val & 0x3)
1008fbafd477SShawn Lin pm = (val == 0x3) ? "L0s" : (val & BIT(1) ? "RX L0s" : "TX L0s");
1009fbafd477SShawn Lin else
1010fbafd477SShawn Lin pm = "Invalid";
1011fbafd477SShawn Lin
1012fbafd477SShawn Lin printf("Common event signal status: %s\n", pm);
1013fbafd477SShawn Lin
1014769b1920SShawn Lin cap_base = priv->rasdes_off;
1015769b1920SShawn Lin if (!priv->rasdes_off)
1016769b1920SShawn Lin return 0;
1017fbafd477SShawn Lin
1018fbafd477SShawn Lin RAS_DES_EVENT("EBUF Overflow: ", 0);
1019fbafd477SShawn Lin RAS_DES_EVENT("EBUF Under-run: ", 0x0010000);
1020fbafd477SShawn Lin RAS_DES_EVENT("Decode Error: ", 0x0020000);
1021fbafd477SShawn Lin RAS_DES_EVENT("Running Disparity Error: ", 0x0030000);
1022fbafd477SShawn Lin RAS_DES_EVENT("SKP OS Parity Error: ", 0x0040000);
1023fbafd477SShawn Lin RAS_DES_EVENT("SYNC Header Error: ", 0x0050000);
1024fbafd477SShawn Lin RAS_DES_EVENT("CTL SKP OS Parity Error: ", 0x0060000);
1025fbafd477SShawn Lin RAS_DES_EVENT("Detect EI Infer: ", 0x1050000);
1026fbafd477SShawn Lin RAS_DES_EVENT("Receiver Error: ", 0x1060000);
1027fbafd477SShawn Lin RAS_DES_EVENT("Rx Recovery Request: ", 0x1070000);
1028fbafd477SShawn Lin RAS_DES_EVENT("N_FTS Timeout: ", 0x1080000);
1029fbafd477SShawn Lin RAS_DES_EVENT("Framing Error: ", 0x1090000);
1030fbafd477SShawn Lin RAS_DES_EVENT("Deskew Error: ", 0x10a0000);
1031fbafd477SShawn Lin RAS_DES_EVENT("BAD TLP: ", 0x2000000);
1032fbafd477SShawn Lin RAS_DES_EVENT("LCRC Error: ", 0x2010000);
1033fbafd477SShawn Lin RAS_DES_EVENT("BAD DLLP: ", 0x2020000);
1034fbafd477SShawn Lin RAS_DES_EVENT("Replay Number Rollover: ", 0x2030000);
1035fbafd477SShawn Lin RAS_DES_EVENT("Replay Timeout: ", 0x2040000);
1036fbafd477SShawn Lin RAS_DES_EVENT("Rx Nak DLLP: ", 0x2050000);
1037fbafd477SShawn Lin RAS_DES_EVENT("Tx Nak DLLP: ", 0x2060000);
1038fbafd477SShawn Lin RAS_DES_EVENT("Retry TLP: ", 0x2070000);
1039fbafd477SShawn Lin RAS_DES_EVENT("FC Timeout: ", 0x3000000);
1040fbafd477SShawn Lin RAS_DES_EVENT("Poisoned TLP: ", 0x3010000);
1041fbafd477SShawn Lin RAS_DES_EVENT("ECRC Error: ", 0x3020000);
1042fbafd477SShawn Lin RAS_DES_EVENT("Unsupported Request: ", 0x3030000);
1043fbafd477SShawn Lin RAS_DES_EVENT("Completer Abort: ", 0x3040000);
1044fbafd477SShawn Lin RAS_DES_EVENT("Completion Timeout: ", 0x3050000);
1045fbafd477SShawn Lin
1046fbafd477SShawn Lin return 0;
1047fbafd477SShawn Lin }
1048fbafd477SShawn Lin
1049bc58f211SShawn Lin static const struct dm_pci_ops rockchip_pcie_ops = {
1050bc58f211SShawn Lin .read_config = rockchip_pcie_rd_conf,
1051bc58f211SShawn Lin .write_config = rockchip_pcie_wr_conf,
1052fbafd477SShawn Lin .vendor_aer_dump = rockchip_pcie_err_dump,
1053bc58f211SShawn Lin };
1054bc58f211SShawn Lin
1055bc58f211SShawn Lin static const struct udevice_id rockchip_pcie_ids[] = {
1056793cb46eSJon Lin { .compatible = "rockchip,rk3528-pcie" },
1057e751b113SJon Lin { .compatible = "rockchip,rk3562-pcie" },
1058bc58f211SShawn Lin { .compatible = "rockchip,rk3568-pcie" },
105943ede60cSJon Lin { .compatible = "rockchip,rk3588-pcie" },
106053314ce8SJon Lin { .compatible = "rockchip,rk3576-pcie" },
1061bc58f211SShawn Lin { }
1062bc58f211SShawn Lin };
1063bc58f211SShawn Lin
1064bc58f211SShawn Lin U_BOOT_DRIVER(rockchip_pcie) = {
1065bc58f211SShawn Lin .name = "pcie_dw_rockchip",
1066bc58f211SShawn Lin .id = UCLASS_PCI,
1067bc58f211SShawn Lin .of_match = rockchip_pcie_ids,
1068bc58f211SShawn Lin .ops = &rockchip_pcie_ops,
1069bc58f211SShawn Lin .probe = rockchip_pcie_probe,
1070bc58f211SShawn Lin .priv_auto_alloc_size = sizeof(struct rk_pcie),
1071bc58f211SShawn Lin };
1072