blob: 59c38f9057712f7f822795a96bb5337b9db96e0a [file] [log] [blame]
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +08001// SPDX-License-Identifier: GPL-2.0+ OR X11
2/*
3 * Copyright 2019 NXP
4 *
5 * PCIe DM U-Boot driver for Freescale PowerPC SoCs
6 * Author: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
7 */
8
9#include <common.h>
10#include <dm.h>
11#include <malloc.h>
12#include <mapmem.h>
13#include <pci.h>
14#include <asm/fsl_pci.h>
15#include <asm/fsl_serdes.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060016#include <asm/global_data.h>
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080017#include <asm/io.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080019#include "pcie_fsl.h"
Simon Glass9bc15642020-02-03 07:36:16 -070020#include <dm/device_compat.h>
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080021
22LIST_HEAD(fsl_pcie_list);
23
24static int fsl_pcie_link_up(struct fsl_pcie *pcie);
25
26static int fsl_pcie_addr_valid(struct fsl_pcie *pcie, pci_dev_t bdf)
27{
28 struct udevice *bus = pcie->bus;
29
30 if (!pcie->enabled)
31 return -ENXIO;
32
Simon Glass75e534b2020-12-16 21:20:07 -070033 if (PCI_BUS(bdf) < dev_seq(bus))
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080034 return -EINVAL;
35
Simon Glass75e534b2020-12-16 21:20:07 -070036 if (PCI_BUS(bdf) > dev_seq(bus) && (!fsl_pcie_link_up(pcie) || pcie->mode))
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080037 return -EINVAL;
38
Simon Glass75e534b2020-12-16 21:20:07 -070039 if (PCI_BUS(bdf) == dev_seq(bus) && (PCI_DEV(bdf) > 0 || PCI_FUNC(bdf) > 0))
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080040 return -EINVAL;
41
Simon Glass75e534b2020-12-16 21:20:07 -070042 if (PCI_BUS(bdf) == (dev_seq(bus) + 1) && (PCI_DEV(bdf) > 0))
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080043 return -EINVAL;
44
45 return 0;
46}
47
Simon Glass2a311e82020-01-27 08:49:37 -070048static int fsl_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080049 uint offset, ulong *valuep,
50 enum pci_size_t size)
51{
52 struct fsl_pcie *pcie = dev_get_priv(bus);
53 ccsr_fsl_pci_t *regs = pcie->regs;
54 u32 val;
55
56 if (fsl_pcie_addr_valid(pcie, bdf)) {
57 *valuep = pci_get_ff(size);
58 return 0;
59 }
60
Pali Rohárc8bb2872021-11-26 11:42:47 +010061 val = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf) - dev_seq(bus),
62 PCI_DEV(bdf), PCI_FUNC(bdf),
63 offset);
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +080064 out_be32(&regs->cfg_addr, val);
65
66 sync();
67
68 switch (size) {
69 case PCI_SIZE_8:
70 *valuep = in_8((u8 *)&regs->cfg_data + (offset & 3));
71 break;
72 case PCI_SIZE_16:
73 *valuep = in_le16((u16 *)((u8 *)&regs->cfg_data +
74 (offset & 2)));
75 break;
76 case PCI_SIZE_32:
77 *valuep = in_le32(&regs->cfg_data);
78 break;
79 }
80
81 return 0;
82}
83
84static int fsl_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
85 uint offset, ulong value,
86 enum pci_size_t size)
87{
88 struct fsl_pcie *pcie = dev_get_priv(bus);
89 ccsr_fsl_pci_t *regs = pcie->regs;
90 u32 val;
91 u8 val_8;
92 u16 val_16;
93 u32 val_32;
94
95 if (fsl_pcie_addr_valid(pcie, bdf))
96 return 0;
97
Pali Rohárc8bb2872021-11-26 11:42:47 +010098 val = PCI_CONF1_EXT_ADDRESS(PCI_BUS(bdf) - dev_seq(bus),
99 PCI_DEV(bdf), PCI_FUNC(bdf),
100 offset);
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800101 out_be32(&regs->cfg_addr, val);
102
103 sync();
104
105 switch (size) {
106 case PCI_SIZE_8:
107 val_8 = value;
108 out_8((u8 *)&regs->cfg_data + (offset & 3), val_8);
109 break;
110 case PCI_SIZE_16:
111 val_16 = value;
112 out_le16((u16 *)((u8 *)&regs->cfg_data + (offset & 2)), val_16);
113 break;
114 case PCI_SIZE_32:
115 val_32 = value;
116 out_le32(&regs->cfg_data, val_32);
117 break;
118 }
119
120 return 0;
121}
122
123static int fsl_pcie_hose_read_config(struct fsl_pcie *pcie, uint offset,
124 ulong *valuep, enum pci_size_t size)
125{
126 int ret;
127 struct udevice *bus = pcie->bus;
128
Simon Glass75e534b2020-12-16 21:20:07 -0700129 ret = fsl_pcie_read_config(bus, PCI_BDF(dev_seq(bus), 0, 0),
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800130 offset, valuep, size);
131
132 return ret;
133}
134
135static int fsl_pcie_hose_write_config(struct fsl_pcie *pcie, uint offset,
136 ulong value, enum pci_size_t size)
137{
138 struct udevice *bus = pcie->bus;
139
Simon Glass75e534b2020-12-16 21:20:07 -0700140 return fsl_pcie_write_config(bus, PCI_BDF(dev_seq(bus), 0, 0),
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800141 offset, value, size);
142}
143
144static int fsl_pcie_hose_read_config_byte(struct fsl_pcie *pcie, uint offset,
145 u8 *valuep)
146{
147 ulong val;
148 int ret;
149
150 ret = fsl_pcie_hose_read_config(pcie, offset, &val, PCI_SIZE_8);
151 *valuep = val;
152
153 return ret;
154}
155
156static int fsl_pcie_hose_read_config_word(struct fsl_pcie *pcie, uint offset,
157 u16 *valuep)
158{
159 ulong val;
160 int ret;
161
162 ret = fsl_pcie_hose_read_config(pcie, offset, &val, PCI_SIZE_16);
163 *valuep = val;
164
165 return ret;
166}
167
168static int fsl_pcie_hose_read_config_dword(struct fsl_pcie *pcie, uint offset,
169 u32 *valuep)
170{
171 ulong val;
172 int ret;
173
174 ret = fsl_pcie_hose_read_config(pcie, offset, &val, PCI_SIZE_32);
175 *valuep = val;
176
177 return ret;
178}
179
180static int fsl_pcie_hose_write_config_byte(struct fsl_pcie *pcie, uint offset,
181 u8 value)
182{
183 return fsl_pcie_hose_write_config(pcie, offset, value, PCI_SIZE_8);
184}
185
186static int fsl_pcie_hose_write_config_word(struct fsl_pcie *pcie, uint offset,
187 u16 value)
188{
189 return fsl_pcie_hose_write_config(pcie, offset, value, PCI_SIZE_16);
190}
191
192static int fsl_pcie_hose_write_config_dword(struct fsl_pcie *pcie, uint offset,
193 u32 value)
194{
195 return fsl_pcie_hose_write_config(pcie, offset, value, PCI_SIZE_32);
196}
197
198static int fsl_pcie_link_up(struct fsl_pcie *pcie)
199{
200 ccsr_fsl_pci_t *regs = pcie->regs;
201 u16 ltssm;
202
203 if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
204 ltssm = (in_be32(&regs->pex_csr0)
205 & PEX_CSR0_LTSSM_MASK) >> PEX_CSR0_LTSSM_SHIFT;
206 return ltssm == LTSSM_L0_REV3;
207 }
208
209 fsl_pcie_hose_read_config_word(pcie, PCI_LTSSM, &ltssm);
210
211 return ltssm == LTSSM_L0;
212}
213
214static bool fsl_pcie_is_agent(struct fsl_pcie *pcie)
215{
216 u8 header_type;
217
218 fsl_pcie_hose_read_config_byte(pcie, PCI_HEADER_TYPE, &header_type);
219
220 return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL;
221}
222
223static int fsl_pcie_setup_law(struct fsl_pcie *pcie)
224{
225 struct pci_region *io, *mem, *pref;
226
227 pci_get_regions(pcie->bus, &io, &mem, &pref);
228
229 if (mem)
230 set_next_law(mem->phys_start,
231 law_size_bits(mem->size),
232 pcie->law_trgt_if);
233
234 if (io)
235 set_next_law(io->phys_start,
236 law_size_bits(io->size),
237 pcie->law_trgt_if);
238
239 return 0;
240}
241
242static void fsl_pcie_config_ready(struct fsl_pcie *pcie)
243{
244 ccsr_fsl_pci_t *regs = pcie->regs;
245
246 if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
247 setbits_be32(&regs->config, FSL_PCIE_V3_CFG_RDY);
248 return;
249 }
250
251 fsl_pcie_hose_write_config_byte(pcie, FSL_PCIE_CFG_RDY, 0x1);
252}
253
254static int fsl_pcie_setup_outbound_win(struct fsl_pcie *pcie, int idx,
255 int type, u64 phys, u64 bus_addr,
256 pci_size_t size)
257{
258 ccsr_fsl_pci_t *regs = pcie->regs;
259 pot_t *po = &regs->pot[idx];
260 u32 war, sz;
261
262 if (idx < 0)
263 return -EINVAL;
264
265 out_be32(&po->powbar, phys >> 12);
266 out_be32(&po->potar, bus_addr >> 12);
267#ifdef CONFIG_SYS_PCI_64BIT
268 out_be32(&po->potear, bus_addr >> 44);
269#else
270 out_be32(&po->potear, 0);
271#endif
272
273 sz = (__ilog2_u64((u64)size) - 1);
274 war = POWAR_EN | sz;
275
276 if (type == PCI_REGION_IO)
277 war |= POWAR_IO_READ | POWAR_IO_WRITE;
278 else
279 war |= POWAR_MEM_READ | POWAR_MEM_WRITE;
280
281 out_be32(&po->powar, war);
282
283 return 0;
284}
285
286static int fsl_pcie_setup_inbound_win(struct fsl_pcie *pcie, int idx,
287 bool pf, u64 phys, u64 bus_addr,
288 pci_size_t size)
289{
290 ccsr_fsl_pci_t *regs = pcie->regs;
291 pit_t *pi = &regs->pit[idx];
292 u32 sz = (__ilog2_u64(size) - 1);
293 u32 flag = PIWAR_LOCAL;
294
295 if (idx < 0)
296 return -EINVAL;
297
298 out_be32(&pi->pitar, phys >> 12);
299 out_be32(&pi->piwbar, bus_addr >> 12);
300
301#ifdef CONFIG_SYS_PCI_64BIT
302 out_be32(&pi->piwbear, bus_addr >> 44);
303#else
304 out_be32(&pi->piwbear, 0);
305#endif
306
Hou Zhiqiang87383332019-08-27 10:13:48 +0000307#ifdef CONFIG_SYS_FSL_ERRATUM_A005434
308 flag = 0;
309#endif
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800310
311 flag |= PIWAR_EN | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
312 if (pf)
313 flag |= PIWAR_PF;
314 out_be32(&pi->piwar, flag | sz);
315
316 return 0;
317}
318
319static int fsl_pcie_setup_outbound_wins(struct fsl_pcie *pcie)
320{
321 struct pci_region *io, *mem, *pref;
322 int idx = 1; /* skip 0 */
323
324 pci_get_regions(pcie->bus, &io, &mem, &pref);
325
326 if (io)
327 /* ATU : OUTBOUND : IO */
328 fsl_pcie_setup_outbound_win(pcie, idx++,
329 PCI_REGION_IO,
330 io->phys_start,
331 io->bus_start,
332 io->size);
333
334 if (mem)
335 /* ATU : OUTBOUND : MEM */
336 fsl_pcie_setup_outbound_win(pcie, idx++,
337 PCI_REGION_MEM,
338 mem->phys_start,
339 mem->bus_start,
340 mem->size);
341 return 0;
342}
343
344static int fsl_pcie_setup_inbound_wins(struct fsl_pcie *pcie)
345{
346 phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS;
347 pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS;
348 u64 sz = min((u64)gd->ram_size, (1ull << 32));
349 pci_size_t pci_sz;
350 int idx;
351
352 if (pcie->block_rev >= PEX_IP_BLK_REV_2_2)
353 idx = 2;
354 else
355 idx = 3;
356
357 pci_sz = 1ull << __ilog2_u64(sz);
358
359 dev_dbg(pcie->bus, "R0 bus_start: %llx phys_start: %llx size: %llx\n",
360 (u64)bus_start, (u64)phys_start, (u64)sz);
361
362 /* if we aren't an exact power of two match, pci_sz is smaller
363 * round it up to the next power of two. We report the actual
364 * size to pci region tracking.
365 */
366 if (pci_sz != sz)
367 sz = 2ull << __ilog2_u64(sz);
368
369 fsl_pcie_setup_inbound_win(pcie, idx--, true,
370 CONFIG_SYS_PCI_MEMORY_PHYS,
371 CONFIG_SYS_PCI_MEMORY_BUS, sz);
372#if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT)
373 /*
374 * On 64-bit capable systems, set up a mapping for all of DRAM
375 * in high pci address space.
376 */
377 pci_sz = 1ull << __ilog2_u64(gd->ram_size);
378 /* round up to the next largest power of two */
379 if (gd->ram_size > pci_sz)
380 pci_sz = 1ull << (__ilog2_u64(gd->ram_size) + 1);
381
382 dev_dbg(pcie->bus, "R64 bus_start: %llx phys_start: %llx size: %llx\n",
383 (u64)CONFIG_SYS_PCI64_MEMORY_BUS,
384 (u64)CONFIG_SYS_PCI_MEMORY_PHYS, (u64)pci_sz);
385
386 fsl_pcie_setup_inbound_win(pcie, idx--, true,
387 CONFIG_SYS_PCI_MEMORY_PHYS,
388 CONFIG_SYS_PCI64_MEMORY_BUS, pci_sz);
389#endif
390
391 return 0;
392}
393
394static int fsl_pcie_init_atmu(struct fsl_pcie *pcie)
395{
396 fsl_pcie_setup_outbound_wins(pcie);
397 fsl_pcie_setup_inbound_wins(pcie);
398
399 return 0;
400}
401
Hou Zhiqiangc5977b12020-10-15 14:54:34 +0800402static void fsl_pcie_dbi_read_only_reg_write_enable(struct fsl_pcie *pcie,
403 bool enable)
404{
405 u32 val;
406
407 fsl_pcie_hose_read_config_dword(pcie, DBI_RO_WR_EN, &val);
408 if (enable)
409 val |= 1;
410 else
411 val &= ~1;
412 fsl_pcie_hose_write_config_dword(pcie, DBI_RO_WR_EN, val);
413}
414
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800415static int fsl_pcie_init_port(struct fsl_pcie *pcie)
416{
417 ccsr_fsl_pci_t *regs = pcie->regs;
418 u32 val_32;
419 u16 val_16;
420
421 fsl_pcie_init_atmu(pcie);
422
Hou Zhiqiang87383332019-08-27 10:13:48 +0000423#ifdef CONFIG_FSL_PCIE_DISABLE_ASPM
424 val_32 = 0;
425 fsl_pcie_hose_read_config_dword(pcie, PCI_LCR, &val_32);
426 val_32 &= ~0x03;
427 fsl_pcie_hose_write_config_dword(pcie, PCI_LCR, val_32);
428 udelay(1);
429#endif
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800430
Hou Zhiqiang87383332019-08-27 10:13:48 +0000431#ifdef CONFIG_FSL_PCIE_RESET
432 u16 ltssm;
433 int i;
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800434
Hou Zhiqiang87383332019-08-27 10:13:48 +0000435 if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
436 /* assert PCIe reset */
437 setbits_be32(&regs->pdb_stat, 0x08000000);
438 (void)in_be32(&regs->pdb_stat);
439 udelay(1000);
440 /* clear PCIe reset */
441 clrbits_be32(&regs->pdb_stat, 0x08000000);
442 asm("sync;isync");
443 for (i = 0; i < 100 && !fsl_pcie_link_up(pcie); i++)
444 udelay(1000);
445 } else {
446 fsl_pcie_hose_read_config_word(pcie, PCI_LTSSM, &ltssm);
447 if (ltssm == 1) {
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800448 /* assert PCIe reset */
449 setbits_be32(&regs->pdb_stat, 0x08000000);
450 (void)in_be32(&regs->pdb_stat);
Hou Zhiqiang87383332019-08-27 10:13:48 +0000451 udelay(100);
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800452 /* clear PCIe reset */
453 clrbits_be32(&regs->pdb_stat, 0x08000000);
454 asm("sync;isync");
Hou Zhiqiang87383332019-08-27 10:13:48 +0000455 for (i = 0; i < 100 &&
456 !fsl_pcie_link_up(pcie); i++)
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800457 udelay(1000);
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800458 }
459 }
Hou Zhiqiang87383332019-08-27 10:13:48 +0000460#endif
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800461
Hou Zhiqiang87383332019-08-27 10:13:48 +0000462#ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
463 if (!fsl_pcie_link_up(pcie)) {
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800464 serdes_corenet_t *srds_regs;
465
466 srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
467 val_32 = in_be32(&srds_regs->srdspccr0);
468
469 if ((val_32 >> 28) == 3) {
470 int i;
471
472 out_be32(&srds_regs->srdspccr0, 2 << 28);
473 setbits_be32(&regs->pdb_stat, 0x08000000);
474 in_be32(&regs->pdb_stat);
475 udelay(100);
476 clrbits_be32(&regs->pdb_stat, 0x08000000);
477 asm("sync;isync");
478 for (i = 0; i < 100 && !fsl_pcie_link_up(pcie); i++)
479 udelay(1000);
480 }
481 }
Hou Zhiqiang87383332019-08-27 10:13:48 +0000482#endif
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800483
484 /*
485 * The Read-Only Write Enable bit defaults to 1 instead of 0.
486 * Set to 0 to protect the read-only registers.
487 */
Hou Zhiqiang87383332019-08-27 10:13:48 +0000488#ifdef CONFIG_SYS_FSL_ERRATUM_A007815
Hou Zhiqiangc5977b12020-10-15 14:54:34 +0800489 fsl_pcie_dbi_read_only_reg_write_enable(pcie, false);
Hou Zhiqiang87383332019-08-27 10:13:48 +0000490#endif
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800491
492 /*
493 * Enable All Error Interrupts except
494 * - Master abort (pci)
495 * - Master PERR (pci)
496 * - ICCA (PCIe)
497 */
498 out_be32(&regs->peer, ~0x20140);
499
500 /* set URR, FER, NFER (but not CER) */
501 fsl_pcie_hose_read_config_dword(pcie, PCI_DCR, &val_32);
502 val_32 |= 0xf000e;
503 fsl_pcie_hose_write_config_dword(pcie, PCI_DCR, val_32);
504
505 /* Clear all error indications */
506 out_be32(&regs->pme_msg_det, 0xffffffff);
507 out_be32(&regs->pme_msg_int_en, 0xffffffff);
508 out_be32(&regs->pedr, 0xffffffff);
509
510 fsl_pcie_hose_read_config_word(pcie, PCI_DSR, &val_16);
511 if (val_16)
512 fsl_pcie_hose_write_config_word(pcie, PCI_DSR, 0xffff);
513
514 fsl_pcie_hose_read_config_word(pcie, PCI_SEC_STATUS, &val_16);
515 if (val_16)
516 fsl_pcie_hose_write_config_word(pcie, PCI_SEC_STATUS, 0xffff);
517
518 return 0;
519}
520
521static int fsl_pcie_fixup_classcode(struct fsl_pcie *pcie)
522{
Hou Zhiqiangd0f3d5e2019-08-27 10:13:51 +0000523 u32 classcode_reg;
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800524 u32 val;
525
Hou Zhiqiangd0f3d5e2019-08-27 10:13:51 +0000526 if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
527 classcode_reg = PCI_CLASS_REVISION;
Hou Zhiqiangc5977b12020-10-15 14:54:34 +0800528 fsl_pcie_dbi_read_only_reg_write_enable(pcie, true);
Hou Zhiqiangd0f3d5e2019-08-27 10:13:51 +0000529 } else {
530 classcode_reg = CSR_CLASSCODE;
531 }
532
533 fsl_pcie_hose_read_config_dword(pcie, classcode_reg, &val);
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800534 val &= 0xff;
Pali Rohár25781e22022-02-18 13:18:40 +0100535 val |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
Hou Zhiqiangd0f3d5e2019-08-27 10:13:51 +0000536 fsl_pcie_hose_write_config_dword(pcie, classcode_reg, val);
537
538 if (pcie->block_rev >= PEX_IP_BLK_REV_3_0)
Hou Zhiqiangc5977b12020-10-15 14:54:34 +0800539 fsl_pcie_dbi_read_only_reg_write_enable(pcie, false);
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800540
541 return 0;
542}
543
544static int fsl_pcie_init_rc(struct fsl_pcie *pcie)
545{
546 return fsl_pcie_fixup_classcode(pcie);
547}
548
549static int fsl_pcie_init_ep(struct fsl_pcie *pcie)
550{
551 fsl_pcie_config_ready(pcie);
552
553 return 0;
554}
555
556static int fsl_pcie_probe(struct udevice *dev)
557{
558 struct fsl_pcie *pcie = dev_get_priv(dev);
559 ccsr_fsl_pci_t *regs = pcie->regs;
560 u16 val_16;
561
562 pcie->bus = dev;
563 pcie->block_rev = in_be32(&regs->block_rev1);
564
565 list_add(&pcie->list, &fsl_pcie_list);
566 pcie->enabled = is_serdes_configured(PCIE1 + pcie->idx);
567 if (!pcie->enabled) {
568 printf("PCIe%d: %s disabled\n", pcie->idx, dev->name);
569 return 0;
570 }
571
572 fsl_pcie_setup_law(pcie);
573
574 pcie->mode = fsl_pcie_is_agent(pcie);
575
576 fsl_pcie_init_port(pcie);
577
578 printf("PCIe%d: %s ", pcie->idx, dev->name);
579
580 if (pcie->mode) {
581 printf("Endpoint");
582 fsl_pcie_init_ep(pcie);
583 } else {
584 printf("Root Complex");
585 fsl_pcie_init_rc(pcie);
586 }
587
588 if (!fsl_pcie_link_up(pcie)) {
589 printf(": %s\n", pcie->mode ? "undetermined link" : "no link");
590 return 0;
591 }
592
593 fsl_pcie_hose_read_config_word(pcie, PCI_LSR, &val_16);
594 printf(": x%d gen%d\n", (val_16 & 0x3f0) >> 4, (val_16 & 0xf));
595
596 return 0;
597}
598
Simon Glassaad29ae2020-12-03 16:55:21 -0700599static int fsl_pcie_of_to_plat(struct udevice *dev)
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800600{
601 struct fsl_pcie *pcie = dev_get_priv(dev);
Hou Zhiqiangf0906c92019-08-27 10:13:54 +0000602 struct fsl_pcie_data *info;
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800603 int ret;
604
605 pcie->regs = dev_remap_addr(dev);
606 if (!pcie->regs) {
607 pr_err("\"reg\" resource not found\n");
608 return -EINVAL;
609 }
610
611 ret = dev_read_u32(dev, "law_trgt_if", &pcie->law_trgt_if);
612 if (ret < 0) {
613 pr_err("\"law_trgt_if\" not found\n");
614 return ret;
615 }
616
Hou Zhiqiangf0906c92019-08-27 10:13:54 +0000617 info = (struct fsl_pcie_data *)dev_get_driver_data(dev);
618 pcie->info = info;
619 pcie->idx = abs((u32)(dev_read_addr(dev) & info->block_offset_mask) -
620 info->block_offset) / info->stride;
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800621
622 return 0;
623}
624
625static const struct dm_pci_ops fsl_pcie_ops = {
626 .read_config = fsl_pcie_read_config,
627 .write_config = fsl_pcie_write_config,
628};
629
Hou Zhiqiangae5c6242019-08-27 11:04:01 +0000630static struct fsl_pcie_data p1_p2_data = {
631 .block_offset = 0xa000,
632 .block_offset_mask = 0xffff,
633 .stride = 0x1000,
634};
635
Hou Zhiqiangafffa7b2019-08-27 11:04:25 +0000636static struct fsl_pcie_data p2041_data = {
637 .block_offset = 0x200000,
638 .block_offset_mask = 0x3fffff,
639 .stride = 0x1000,
640};
641
Hou Zhiqiangf0906c92019-08-27 10:13:54 +0000642static struct fsl_pcie_data t2080_data = {
643 .block_offset = 0x240000,
644 .block_offset_mask = 0x3fffff,
645 .stride = 0x10000,
646};
647
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800648static const struct udevice_id fsl_pcie_ids[] = {
Pali Rohárccc205a2022-04-14 22:52:03 +0200649 { .compatible = "fsl,mpc8548-pcie", .data = (ulong)&p1_p2_data },
Hou Zhiqiangae5c6242019-08-27 11:04:01 +0000650 { .compatible = "fsl,pcie-p1_p2", .data = (ulong)&p1_p2_data },
Hou Zhiqiangafffa7b2019-08-27 11:04:25 +0000651 { .compatible = "fsl,pcie-p2041", .data = (ulong)&p2041_data },
Hou Zhiqiang4cbcf2c2019-08-27 11:04:39 +0000652 { .compatible = "fsl,pcie-p3041", .data = (ulong)&p2041_data },
Hou Zhiqiang48454072019-08-27 11:04:52 +0000653 { .compatible = "fsl,pcie-p4080", .data = (ulong)&p2041_data },
Hou Zhiqiang3ef654c2019-08-27 11:05:02 +0000654 { .compatible = "fsl,pcie-p5040", .data = (ulong)&p2041_data },
Hou Zhiqiang0e1cd0e2019-08-27 11:03:24 +0000655 { .compatible = "fsl,pcie-t102x", .data = (ulong)&t2080_data },
Hou Zhiqiang4b0b23d2019-08-27 11:03:44 +0000656 { .compatible = "fsl,pcie-t104x", .data = (ulong)&t2080_data },
Hou Zhiqiangf0906c92019-08-27 10:13:54 +0000657 { .compatible = "fsl,pcie-t2080", .data = (ulong)&t2080_data },
Hou Zhiqiangf8c8a3a2019-08-27 11:03:06 +0000658 { .compatible = "fsl,pcie-t4240", .data = (ulong)&t2080_data },
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800659 { }
660};
661
662U_BOOT_DRIVER(fsl_pcie) = {
663 .name = "fsl_pcie",
664 .id = UCLASS_PCI,
665 .of_match = fsl_pcie_ids,
666 .ops = &fsl_pcie_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700667 .of_to_plat = fsl_pcie_of_to_plat,
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800668 .probe = fsl_pcie_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700669 .priv_auto = sizeof(struct fsl_pcie),
Hou Zhiqiang25ff98c2019-04-24 22:33:02 +0800670};