blob: bc4635f67136ae188334bca9f83f7e838fc4d99e [file] [log] [blame]
Shawn Linc0649da2021-01-15 18:01:22 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Rockchip DesignWare based PCIe host controller driver
4 *
5 * Copyright (c) 2021 Rockchip, Inc.
6 */
7
8#include <common.h>
9#include <clk.h>
10#include <dm.h>
11#include <generic-phy.h>
12#include <pci.h>
13#include <power-domain.h>
14#include <reset.h>
15#include <syscon.h>
16#include <asm/arch-rockchip/clock.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060017#include <asm/global_data.h>
Shawn Linc0649da2021-01-15 18:01:22 +080018#include <asm/io.h>
19#include <asm-generic/gpio.h>
20#include <dm/device_compat.h>
Jonas Karlmana635bcd2023-08-02 19:25:51 +000021#include <linux/bitfield.h>
Shawn Linc0649da2021-01-15 18:01:22 +080022#include <linux/iopoll.h>
23#include <linux/delay.h>
24#include <power/regulator.h>
25
Neil Armstrongcf214c62021-03-25 15:49:20 +010026#include "pcie_dw_common.h"
27
Shawn Linc0649da2021-01-15 18:01:22 +080028DECLARE_GLOBAL_DATA_PTR;
29
30/**
31 * struct rk_pcie - RK DW PCIe controller state
32 *
33 * @vpcie3v3: The 3.3v power supply for slot
Shawn Linc0649da2021-01-15 18:01:22 +080034 * @apb_base: The base address of vendor regs
Shawn Linc0649da2021-01-15 18:01:22 +080035 * @rst_gpio: The #PERST signal for slot
Shawn Linc0649da2021-01-15 18:01:22 +080036 */
37struct rk_pcie {
Neil Armstrongcf214c62021-03-25 15:49:20 +010038 /* Must be first member of the struct */
39 struct pcie_dw dw;
Shawn Linc0649da2021-01-15 18:01:22 +080040 struct udevice *vpcie3v3;
Shawn Linc0649da2021-01-15 18:01:22 +080041 void *apb_base;
Shawn Linc0649da2021-01-15 18:01:22 +080042 struct phy phy;
43 struct clk_bulk clks;
Shawn Linc0649da2021-01-15 18:01:22 +080044 struct reset_ctl_bulk rsts;
45 struct gpio_desc rst_gpio;
Jon Lin793de192023-04-27 10:35:33 +030046 u32 gen;
Jonas Karlmana635bcd2023-08-02 19:25:51 +000047 u32 num_lanes;
Shawn Linc0649da2021-01-15 18:01:22 +080048};
49
50/* Parameters for the waiting for iATU enabled routine */
51#define PCIE_CLIENT_GENERAL_DEBUG 0x104
52#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
53#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4)
54#define PCIE_CLIENT_LTSSM_STATUS 0x300
55#define SMLH_LINKUP BIT(16)
56#define RDLH_LINKUP BIT(17)
57#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
58#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
59#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
60#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
61#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
62#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
63#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
64#define PCIE_CLIENT_DBF_EN 0xffff0003
65
Jon Lin97be1652023-07-22 13:30:20 +000066#define PCIE_TYPE0_HDR_DBI2_OFFSET 0x100000
67
Shawn Linc0649da2021-01-15 18:01:22 +080068static int rk_pcie_read(void __iomem *addr, int size, u32 *val)
69{
70 if ((uintptr_t)addr & (size - 1)) {
71 *val = 0;
Anand Moone4e87452021-06-05 14:38:41 +000072 return -EOPNOTSUPP;
Shawn Linc0649da2021-01-15 18:01:22 +080073 }
74
75 if (size == 4) {
76 *val = readl(addr);
77 } else if (size == 2) {
78 *val = readw(addr);
79 } else if (size == 1) {
80 *val = readb(addr);
81 } else {
82 *val = 0;
83 return -ENODEV;
84 }
85
86 return 0;
87}
88
89static int rk_pcie_write(void __iomem *addr, int size, u32 val)
90{
91 if ((uintptr_t)addr & (size - 1))
Anand Moone4e87452021-06-05 14:38:41 +000092 return -EOPNOTSUPP;
Shawn Linc0649da2021-01-15 18:01:22 +080093
94 if (size == 4)
95 writel(val, addr);
96 else if (size == 2)
97 writew(val, addr);
98 else if (size == 1)
99 writeb(val, addr);
100 else
101 return -ENODEV;
102
103 return 0;
104}
105
106static u32 __rk_pcie_read_apb(struct rk_pcie *rk_pcie, void __iomem *base,
107 u32 reg, size_t size)
108{
109 int ret;
110 u32 val;
111
112 ret = rk_pcie_read(base + reg, size, &val);
113 if (ret)
Neil Armstrongcf214c62021-03-25 15:49:20 +0100114 dev_err(rk_pcie->dw.dev, "Read APB address failed\n");
Shawn Linc0649da2021-01-15 18:01:22 +0800115
116 return val;
117}
118
119static void __rk_pcie_write_apb(struct rk_pcie *rk_pcie, void __iomem *base,
120 u32 reg, size_t size, u32 val)
121{
122 int ret;
123
124 ret = rk_pcie_write(base + reg, size, val);
125 if (ret)
Neil Armstrongcf214c62021-03-25 15:49:20 +0100126 dev_err(rk_pcie->dw.dev, "Write APB address failed\n");
Shawn Linc0649da2021-01-15 18:01:22 +0800127}
128
129/**
130 * rk_pcie_readl_apb() - Read vendor regs
131 *
132 * @rk_pcie: Pointer to the PCI controller state
133 * @reg: Offset of regs
134 */
135static inline u32 rk_pcie_readl_apb(struct rk_pcie *rk_pcie, u32 reg)
136{
137 return __rk_pcie_read_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4);
138}
139
140/**
141 * rk_pcie_writel_apb() - Write vendor regs
142 *
143 * @rk_pcie: Pointer to the PCI controller state
144 * @reg: Offset of regs
145 * @val: Value to be writen
146 */
147static inline void rk_pcie_writel_apb(struct rk_pcie *rk_pcie, u32 reg,
148 u32 val)
149{
150 __rk_pcie_write_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4, val);
151}
152
Shawn Linc0649da2021-01-15 18:01:22 +0800153/**
154 * rk_pcie_configure() - Configure link capabilities and speed
155 *
156 * @rk_pcie: Pointer to the PCI controller state
Shawn Linc0649da2021-01-15 18:01:22 +0800157 *
158 * Configure the link capabilities and speed in the PCIe root complex.
159 */
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000160static void rk_pcie_configure(struct rk_pcie *pci)
Shawn Linc0649da2021-01-15 18:01:22 +0800161{
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000162 u32 val;
163
Neil Armstrongcf214c62021-03-25 15:49:20 +0100164 dw_pcie_dbi_write_enable(&pci->dw, true);
Shawn Linc0649da2021-01-15 18:01:22 +0800165
Jon Lin97be1652023-07-22 13:30:20 +0000166 /* Disable BAR 0 and BAR 1 */
167 writel(0, pci->dw.dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET +
168 PCI_BASE_ADDRESS_0);
169 writel(0, pci->dw.dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET +
170 PCI_BASE_ADDRESS_1);
171
Neil Armstrongcf214c62021-03-25 15:49:20 +0100172 clrsetbits_le32(pci->dw.dbi_base + PCIE_LINK_CAPABILITY,
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000173 TARGET_LINK_SPEED_MASK, pci->gen);
Shawn Linc0649da2021-01-15 18:01:22 +0800174
Neil Armstrongcf214c62021-03-25 15:49:20 +0100175 clrsetbits_le32(pci->dw.dbi_base + PCIE_LINK_CTL_2,
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000176 TARGET_LINK_SPEED_MASK, pci->gen);
Shawn Linc0649da2021-01-15 18:01:22 +0800177
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000178 /* Set the number of lanes */
179 val = readl(pci->dw.dbi_base + PCIE_PORT_LINK_CONTROL);
180 val &= ~PORT_LINK_FAST_LINK_MODE;
181 val |= PORT_LINK_DLL_LINK_EN;
182 val &= ~PORT_LINK_MODE_MASK;
183 switch (pci->num_lanes) {
184 case 1:
185 val |= PORT_LINK_MODE_1_LANES;
186 break;
187 case 2:
188 val |= PORT_LINK_MODE_2_LANES;
189 break;
190 case 4:
191 val |= PORT_LINK_MODE_4_LANES;
192 break;
193 default:
194 dev_err(pci->dw.dev, "num-lanes %u: invalid value\n", pci->num_lanes);
195 goto out;
196 }
197 writel(val, pci->dw.dbi_base + PCIE_PORT_LINK_CONTROL);
198
199 /* Set link width speed control register */
200 val = readl(pci->dw.dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
201 val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
202 switch (pci->num_lanes) {
203 case 1:
204 val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
205 break;
206 case 2:
207 val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
208 break;
209 case 4:
210 val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
211 break;
212 }
213 writel(val, pci->dw.dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
214
215out:
Neil Armstrongcf214c62021-03-25 15:49:20 +0100216 dw_pcie_dbi_write_enable(&pci->dw, false);
Shawn Linc0649da2021-01-15 18:01:22 +0800217}
218
Shawn Linc0649da2021-01-15 18:01:22 +0800219static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
220{
221 rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0,
222 PCIE_CLIENT_DBG_TRANSITION_DATA);
223 rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1,
224 PCIE_CLIENT_DBG_TRANSITION_DATA);
225 rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0,
226 PCIE_CLIENT_DBG_TRANSITION_DATA);
227 rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1,
228 PCIE_CLIENT_DBG_TRANSITION_DATA);
229 rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_MODE_CON,
230 PCIE_CLIENT_DBF_EN);
231}
232
233static void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
234{
235 u32 loop;
236
237 debug("ltssm = 0x%x\n",
238 rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
239 for (loop = 0; loop < 64; loop++)
240 debug("fifo_status = 0x%x\n",
241 rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_STATUS));
242}
243
244static inline void rk_pcie_link_status_clear(struct rk_pcie *rk_pcie)
245{
246 rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG, 0x0);
247}
248
249static inline void rk_pcie_disable_ltssm(struct rk_pcie *rk_pcie)
250{
251 rk_pcie_writel_apb(rk_pcie, 0x0, 0xc0008);
252}
253
254static inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie)
255{
256 rk_pcie_writel_apb(rk_pcie, 0x0, 0xc000c);
257}
258
259static int is_link_up(struct rk_pcie *priv)
260{
261 u32 val;
262
263 val = rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS);
264 if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000 &&
265 (val & GENMASK(5, 0)) == 0x11)
266 return 1;
267
268 return 0;
269}
270
271/**
272 * rk_pcie_link_up() - Wait for the link to come up
273 *
274 * @rk_pcie: Pointer to the PCI controller state
Shawn Linc0649da2021-01-15 18:01:22 +0800275 *
276 * Return: 1 (true) for active line and negetive (false) for no link (timeout)
277 */
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000278static int rk_pcie_link_up(struct rk_pcie *priv)
Shawn Linc0649da2021-01-15 18:01:22 +0800279{
280 int retries;
281
282 if (is_link_up(priv)) {
283 printf("PCI Link already up before configuration!\n");
284 return 1;
285 }
286
287 /* DW pre link configurations */
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000288 rk_pcie_configure(priv);
Shawn Linc0649da2021-01-15 18:01:22 +0800289
Shawn Linc0649da2021-01-15 18:01:22 +0800290 rk_pcie_disable_ltssm(priv);
291 rk_pcie_link_status_clear(priv);
292 rk_pcie_enable_debug(priv);
293
Jonas Karlman64942b72023-07-22 13:30:19 +0000294 /* Reset the device */
295 if (dm_gpio_is_valid(&priv->rst_gpio))
296 dm_gpio_set_value(&priv->rst_gpio, 0);
297
Shawn Linc0649da2021-01-15 18:01:22 +0800298 /* Enable LTSSM */
299 rk_pcie_enable_ltssm(priv);
300
Jonas Karlman64942b72023-07-22 13:30:19 +0000301 /*
302 * PCIe requires the refclk to be stable for 100ms prior to releasing
303 * PERST. See table 2-4 in section 2.6.2 AC Specifications of the PCI
304 * Express Card Electromechanical Specification, 1.1. However, we don't
305 * know if the refclk is coming from RC's PHY or external OSC. If it's
306 * from RC, so enabling LTSSM is the just right place to release #PERST.
307 */
308 mdelay(100);
309 if (dm_gpio_is_valid(&priv->rst_gpio))
310 dm_gpio_set_value(&priv->rst_gpio, 1);
311
312 /* Check if the link is up or not */
313 for (retries = 0; retries < 10; retries++) {
314 if (is_link_up(priv))
315 break;
316
317 mdelay(100);
318 }
Shawn Linc0649da2021-01-15 18:01:22 +0800319
Jonas Karlman64942b72023-07-22 13:30:19 +0000320 if (retries >= 10) {
321 dev_err(priv->dw.dev, "PCIe-%d Link Fail\n",
322 dev_seq(priv->dw.dev));
323 return -EIO;
Shawn Linc0649da2021-01-15 18:01:22 +0800324 }
325
Jonas Karlman64942b72023-07-22 13:30:19 +0000326 dev_info(priv->dw.dev, "PCIe Link up, LTSSM is 0x%x\n",
327 rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
328 rk_pcie_debug_dump(priv);
329 return 0;
Shawn Linc0649da2021-01-15 18:01:22 +0800330}
331
332static int rockchip_pcie_init_port(struct udevice *dev)
333{
334 int ret;
335 u32 val;
336 struct rk_pcie *priv = dev_get_priv(dev);
337
Jonas Karlman64942b72023-07-22 13:30:19 +0000338 ret = reset_assert_bulk(&priv->rsts);
339 if (ret) {
340 dev_err(dev, "failed to assert resets (ret=%d)\n", ret);
341 return ret;
342 }
343
Shawn Linc0649da2021-01-15 18:01:22 +0800344 /* Set power and maybe external ref clk input */
Jonas Karlman39993bc2023-07-22 13:30:18 +0000345 ret = regulator_set_enable_if_allowed(priv->vpcie3v3, true);
346 if (ret && ret != -ENOSYS) {
347 dev_err(dev, "failed to enable vpcie3v3 (ret=%d)\n", ret);
348 return ret;
Shawn Linc0649da2021-01-15 18:01:22 +0800349 }
350
Shawn Linc0649da2021-01-15 18:01:22 +0800351 ret = generic_phy_init(&priv->phy);
352 if (ret) {
353 dev_err(dev, "failed to init phy (ret=%d)\n", ret);
Jonas Karlman39993bc2023-07-22 13:30:18 +0000354 goto err_disable_regulator;
Shawn Linc0649da2021-01-15 18:01:22 +0800355 }
356
357 ret = generic_phy_power_on(&priv->phy);
358 if (ret) {
359 dev_err(dev, "failed to power on phy (ret=%d)\n", ret);
360 goto err_exit_phy;
361 }
362
363 ret = reset_deassert_bulk(&priv->rsts);
364 if (ret) {
365 dev_err(dev, "failed to deassert resets (ret=%d)\n", ret);
366 goto err_power_off_phy;
367 }
368
369 ret = clk_enable_bulk(&priv->clks);
370 if (ret) {
371 dev_err(dev, "failed to enable clks (ret=%d)\n", ret);
372 goto err_deassert_bulk;
373 }
374
375 /* LTSSM EN ctrl mode */
376 val = rk_pcie_readl_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL);
377 val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
378 rk_pcie_writel_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL, val);
379
380 /* Set RC mode */
381 rk_pcie_writel_apb(priv, 0x0, 0xf00040);
Neil Armstrongcf214c62021-03-25 15:49:20 +0100382 pcie_dw_setup_host(&priv->dw);
Shawn Linc0649da2021-01-15 18:01:22 +0800383
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000384 ret = rk_pcie_link_up(priv);
Shawn Linc0649da2021-01-15 18:01:22 +0800385 if (ret < 0)
386 goto err_link_up;
387
388 return 0;
389err_link_up:
390 clk_disable_bulk(&priv->clks);
391err_deassert_bulk:
392 reset_assert_bulk(&priv->rsts);
393err_power_off_phy:
394 generic_phy_power_off(&priv->phy);
395err_exit_phy:
396 generic_phy_exit(&priv->phy);
Jonas Karlman39993bc2023-07-22 13:30:18 +0000397err_disable_regulator:
398 regulator_set_enable_if_allowed(priv->vpcie3v3, false);
Shawn Linc0649da2021-01-15 18:01:22 +0800399
400 return ret;
401}
402
403static int rockchip_pcie_parse_dt(struct udevice *dev)
404{
405 struct rk_pcie *priv = dev_get_priv(dev);
406 int ret;
407
Johan Jonker5ff88122023-03-13 01:31:49 +0100408 priv->dw.dbi_base = dev_read_addr_index_ptr(dev, 0);
Neil Armstrongcf214c62021-03-25 15:49:20 +0100409 if (!priv->dw.dbi_base)
Johan Jonker5ff88122023-03-13 01:31:49 +0100410 return -EINVAL;
Shawn Linc0649da2021-01-15 18:01:22 +0800411
Neil Armstrongcf214c62021-03-25 15:49:20 +0100412 dev_dbg(dev, "DBI address is 0x%p\n", priv->dw.dbi_base);
Shawn Linc0649da2021-01-15 18:01:22 +0800413
Johan Jonker5ff88122023-03-13 01:31:49 +0100414 priv->apb_base = dev_read_addr_index_ptr(dev, 1);
Shawn Linc0649da2021-01-15 18:01:22 +0800415 if (!priv->apb_base)
Johan Jonker5ff88122023-03-13 01:31:49 +0100416 return -EINVAL;
Shawn Linc0649da2021-01-15 18:01:22 +0800417
418 dev_dbg(dev, "APB address is 0x%p\n", priv->apb_base);
419
Jonas Karlman8746d9c2023-07-22 13:30:16 +0000420 priv->dw.cfg_base = dev_read_addr_size_index_ptr(dev, 2,
421 &priv->dw.cfg_size);
422 if (!priv->dw.cfg_base)
423 return -EINVAL;
424
425 dev_dbg(dev, "CFG address is 0x%p\n", priv->dw.cfg_base);
426
Shawn Linc0649da2021-01-15 18:01:22 +0800427 ret = gpio_request_by_name(dev, "reset-gpios", 0,
428 &priv->rst_gpio, GPIOD_IS_OUT);
429 if (ret) {
430 dev_err(dev, "failed to find reset-gpios property\n");
431 return ret;
432 }
433
434 ret = reset_get_bulk(dev, &priv->rsts);
435 if (ret) {
436 dev_err(dev, "Can't get reset: %d\n", ret);
Eugen Hristev32a51032023-04-13 17:11:03 +0300437 goto rockchip_pcie_parse_dt_err_reset_get_bulk;
Shawn Linc0649da2021-01-15 18:01:22 +0800438 }
439
440 ret = clk_get_bulk(dev, &priv->clks);
441 if (ret) {
442 dev_err(dev, "Can't get clock: %d\n", ret);
Eugen Hristev32a51032023-04-13 17:11:03 +0300443 goto rockchip_pcie_parse_dt_err_clk_get_bulk;
Shawn Linc0649da2021-01-15 18:01:22 +0800444 }
445
446 ret = device_get_supply_regulator(dev, "vpcie3v3-supply",
447 &priv->vpcie3v3);
448 if (ret && ret != -ENOENT) {
449 dev_err(dev, "failed to get vpcie3v3 supply (ret=%d)\n", ret);
Eugen Hristev32a51032023-04-13 17:11:03 +0300450 goto rockchip_pcie_parse_dt_err_supply_regulator;
Shawn Linc0649da2021-01-15 18:01:22 +0800451 }
452
453 ret = generic_phy_get_by_index(dev, 0, &priv->phy);
454 if (ret) {
455 dev_err(dev, "failed to get pcie phy (ret=%d)\n", ret);
Eugen Hristev32a51032023-04-13 17:11:03 +0300456 goto rockchip_pcie_parse_dt_err_phy_get_by_index;
Shawn Linc0649da2021-01-15 18:01:22 +0800457 }
458
Jon Lin793de192023-04-27 10:35:33 +0300459 priv->gen = dev_read_u32_default(dev, "max-link-speed",
460 LINK_SPEED_GEN_3);
461
Jonas Karlmana635bcd2023-08-02 19:25:51 +0000462 priv->num_lanes = dev_read_u32_default(dev, "num-lanes", 1);
463
Shawn Linc0649da2021-01-15 18:01:22 +0800464 return 0;
Eugen Hristev32a51032023-04-13 17:11:03 +0300465
466rockchip_pcie_parse_dt_err_phy_get_by_index:
467 /* regulators don't need release */
468rockchip_pcie_parse_dt_err_supply_regulator:
469 clk_release_bulk(&priv->clks);
470rockchip_pcie_parse_dt_err_clk_get_bulk:
471 reset_release_bulk(&priv->rsts);
472rockchip_pcie_parse_dt_err_reset_get_bulk:
473 dm_gpio_free(dev, &priv->rst_gpio);
474 return ret;
Shawn Linc0649da2021-01-15 18:01:22 +0800475}
476
477/**
478 * rockchip_pcie_probe() - Probe the PCIe bus for active link
479 *
480 * @dev: A pointer to the device being operated on
481 *
482 * Probe for an active link on the PCIe bus and configure the controller
483 * to enable this port.
484 *
485 * Return: 0 on success, else -ENODEV
486 */
487static int rockchip_pcie_probe(struct udevice *dev)
488{
489 struct rk_pcie *priv = dev_get_priv(dev);
490 struct udevice *ctlr = pci_get_controller(dev);
491 struct pci_controller *hose = dev_get_uclass_priv(ctlr);
Neil Armstrongcf214c62021-03-25 15:49:20 +0100492 int ret = 0;
Shawn Linc0649da2021-01-15 18:01:22 +0800493
Neil Armstrongcf214c62021-03-25 15:49:20 +0100494 priv->dw.first_busno = dev_seq(dev);
495 priv->dw.dev = dev;
Shawn Linc0649da2021-01-15 18:01:22 +0800496
497 ret = rockchip_pcie_parse_dt(dev);
498 if (ret)
499 return ret;
500
501 ret = rockchip_pcie_init_port(dev);
502 if (ret)
Eugen Hristev32a51032023-04-13 17:11:03 +0300503 goto rockchip_pcie_probe_err_init_port;
Shawn Linc0649da2021-01-15 18:01:22 +0800504
505 dev_info(dev, "PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
Neil Armstrongcf214c62021-03-25 15:49:20 +0100506 dev_seq(dev), pcie_dw_get_link_speed(&priv->dw),
507 pcie_dw_get_link_width(&priv->dw),
Shawn Linc0649da2021-01-15 18:01:22 +0800508 hose->first_busno);
509
Eugen Hristev32a51032023-04-13 17:11:03 +0300510
511 ret = pcie_dw_prog_outbound_atu_unroll(&priv->dw,
512 PCIE_ATU_REGION_INDEX0,
513 PCIE_ATU_TYPE_MEM,
514 priv->dw.mem.phys_start,
515 priv->dw.mem.bus_start,
516 priv->dw.mem.size);
517 if (!ret)
518 return ret;
519
520rockchip_pcie_probe_err_init_port:
521 clk_release_bulk(&priv->clks);
522 reset_release_bulk(&priv->rsts);
523 dm_gpio_free(dev, &priv->rst_gpio);
Shawn Linc0649da2021-01-15 18:01:22 +0800524
Eugen Hristev32a51032023-04-13 17:11:03 +0300525 return ret;
Shawn Linc0649da2021-01-15 18:01:22 +0800526}
527
528static const struct dm_pci_ops rockchip_pcie_ops = {
Neil Armstrongcf214c62021-03-25 15:49:20 +0100529 .read_config = pcie_dw_read_config,
530 .write_config = pcie_dw_write_config,
Shawn Linc0649da2021-01-15 18:01:22 +0800531};
532
533static const struct udevice_id rockchip_pcie_ids[] = {
534 { .compatible = "rockchip,rk3568-pcie" },
Jon Lin2bdea352023-04-27 10:35:32 +0300535 { .compatible = "rockchip,rk3588-pcie" },
Shawn Linc0649da2021-01-15 18:01:22 +0800536 { }
537};
538
539U_BOOT_DRIVER(rockchip_dw_pcie) = {
540 .name = "pcie_dw_rockchip",
541 .id = UCLASS_PCI,
542 .of_match = rockchip_pcie_ids,
543 .ops = &rockchip_pcie_ops,
544 .probe = rockchip_pcie_probe,
545 .priv_auto = sizeof(struct rk_pcie),
546};