Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / pci / pcie_layerscape_rc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2020,2021 NXP
4  * Layerscape PCIe driver
5  */
6
7 #include <common.h>
8 #include <asm/arch/fsl_serdes.h>
9 #include <pci.h>
10 #include <asm/global_data.h>
11 #include <asm/io.h>
12 #include <errno.h>
13 #include <malloc.h>
14 #include <dm.h>
15 #include <dm/devres.h>
16 #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
17         defined(CONFIG_ARM)
18 #include <asm/arch/clock.h>
19 #endif
20 #include "pcie_layerscape.h"
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 struct ls_pcie_drvdata {
25         u32 lut_offset;
26         u32 ctrl_offset;
27         bool big_endian;
28 };
29
30 static void ls_pcie_cfg0_set_busdev(struct ls_pcie_rc *pcie_rc, u32 busdev)
31 {
32         struct ls_pcie *pcie = pcie_rc->pcie;
33
34         dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
35                    PCIE_ATU_VIEWPORT);
36         dbi_writel(pcie, busdev, PCIE_ATU_LOWER_TARGET);
37 }
38
39 static void ls_pcie_cfg1_set_busdev(struct ls_pcie_rc *pcie_rc, u32 busdev)
40 {
41         struct ls_pcie *pcie = pcie_rc->pcie;
42
43         dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
44                    PCIE_ATU_VIEWPORT);
45         dbi_writel(pcie, busdev, PCIE_ATU_LOWER_TARGET);
46 }
47
48 static void ls_pcie_setup_atu(struct ls_pcie_rc *pcie_rc)
49 {
50         struct pci_region *io, *mem, *pref;
51         unsigned long long offset = 0;
52         struct ls_pcie *pcie = pcie_rc->pcie;
53         int idx = 0;
54         uint svr;
55
56         svr = get_svr();
57         if (((svr >> SVR_VAR_PER_SHIFT) & SVR_LS102XA_MASK) == SVR_LS102XA) {
58                 offset = LS1021_PCIE_SPACE_OFFSET +
59                          LS1021_PCIE_SPACE_SIZE * pcie->idx;
60         }
61
62         /* ATU 0 : OUTBOUND : CFG0 */
63         ls_pcie_atu_outbound_set(pcie, PCIE_ATU_REGION_INDEX0,
64                                  PCIE_ATU_TYPE_CFG0,
65                                  pcie_rc->cfg_res.start + offset,
66                                  0,
67                                  fdt_resource_size(&pcie_rc->cfg_res) / 2);
68         /* ATU 1 : OUTBOUND : CFG1 */
69         ls_pcie_atu_outbound_set(pcie, PCIE_ATU_REGION_INDEX1,
70                                  PCIE_ATU_TYPE_CFG1,
71                                  pcie_rc->cfg_res.start + offset +
72                                  fdt_resource_size(&pcie_rc->cfg_res) / 2,
73                                  0,
74                                  fdt_resource_size(&pcie_rc->cfg_res) / 2);
75
76         pci_get_regions(pcie_rc->bus, &io, &mem, &pref);
77         idx = PCIE_ATU_REGION_INDEX1 + 1;
78
79         /* Fix the pcie memory map for LS2088A series SoCs */
80         svr = (svr >> SVR_VAR_PER_SHIFT) & 0xFFFFFE;
81         if (svr == SVR_LS2088A || svr == SVR_LS2084A ||
82             svr == SVR_LS2048A || svr == SVR_LS2044A ||
83             svr == SVR_LS2081A || svr == SVR_LS2041A) {
84                 if (io)
85                         io->phys_start = (io->phys_start &
86                                          (PCIE_PHYS_SIZE - 1)) +
87                                          LS2088A_PCIE1_PHYS_ADDR +
88                                          LS2088A_PCIE_PHYS_SIZE * pcie->idx;
89                 if (mem)
90                         mem->phys_start = (mem->phys_start &
91                                          (PCIE_PHYS_SIZE - 1)) +
92                                          LS2088A_PCIE1_PHYS_ADDR +
93                                          LS2088A_PCIE_PHYS_SIZE * pcie->idx;
94                 if (pref)
95                         pref->phys_start = (pref->phys_start &
96                                          (PCIE_PHYS_SIZE - 1)) +
97                                          LS2088A_PCIE1_PHYS_ADDR +
98                                          LS2088A_PCIE_PHYS_SIZE * pcie->idx;
99         }
100
101         if (io)
102                 /* ATU : OUTBOUND : IO */
103                 ls_pcie_atu_outbound_set(pcie, idx++,
104                                          PCIE_ATU_TYPE_IO,
105                                          io->phys_start + offset,
106                                          io->bus_start,
107                                          io->size);
108
109         if (mem)
110                 /* ATU : OUTBOUND : MEM */
111                 ls_pcie_atu_outbound_set(pcie, idx++,
112                                          PCIE_ATU_TYPE_MEM,
113                                          mem->phys_start + offset,
114                                          mem->bus_start,
115                                          mem->size);
116
117         if (pref)
118                 /* ATU : OUTBOUND : pref */
119                 ls_pcie_atu_outbound_set(pcie, idx++,
120                                          PCIE_ATU_TYPE_MEM,
121                                          pref->phys_start + offset,
122                                          pref->bus_start,
123                                          pref->size);
124
125         ls_pcie_dump_atu(pcie, PCIE_ATU_REGION_NUM, PCIE_ATU_REGION_OUTBOUND);
126 }
127
128 /* Return 0 if the address is valid, -errno if not valid */
129 static int ls_pcie_addr_valid(struct ls_pcie_rc *pcie_rc, pci_dev_t bdf)
130 {
131         struct udevice *bus = pcie_rc->bus;
132         struct ls_pcie *pcie = pcie_rc->pcie;
133
134         if (pcie->mode == PCI_HEADER_TYPE_NORMAL)
135                 return -ENODEV;
136
137         if (!pcie_rc->enabled)
138                 return -ENXIO;
139
140         if (PCI_BUS(bdf) < dev_seq(bus))
141                 return -EINVAL;
142
143         if ((PCI_BUS(bdf) > dev_seq(bus)) && (!ls_pcie_link_up(pcie)))
144                 return -EINVAL;
145
146         if (PCI_BUS(bdf) <= (dev_seq(bus) + 1) && (PCI_DEV(bdf) > 0))
147                 return -EINVAL;
148
149         return 0;
150 }
151
152 static int ls_pcie_conf_address(const struct udevice *bus, pci_dev_t bdf,
153                                 uint offset, void **paddress)
154 {
155         struct ls_pcie_rc *pcie_rc = dev_get_priv(bus);
156         struct ls_pcie *pcie = pcie_rc->pcie;
157         u32 busdev;
158
159         if (ls_pcie_addr_valid(pcie_rc, bdf))
160                 return -EINVAL;
161
162         if (PCI_BUS(bdf) == dev_seq(bus)) {
163                 *paddress = pcie->dbi + offset;
164                 return 0;
165         }
166
167         busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - dev_seq(bus)) |
168                  PCIE_ATU_DEV(PCI_DEV(bdf)) |
169                  PCIE_ATU_FUNC(PCI_FUNC(bdf));
170
171         if (PCI_BUS(bdf) == dev_seq(bus) + 1) {
172                 ls_pcie_cfg0_set_busdev(pcie_rc, busdev);
173                 *paddress = pcie_rc->cfg0 + offset;
174         } else {
175                 ls_pcie_cfg1_set_busdev(pcie_rc, busdev);
176                 *paddress = pcie_rc->cfg1 + offset;
177         }
178         return 0;
179 }
180
181 static int ls_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
182                                uint offset, ulong *valuep,
183                                enum pci_size_t size)
184 {
185         return pci_generic_mmap_read_config(bus, ls_pcie_conf_address,
186                                             bdf, offset, valuep, size);
187 }
188
189 static int ls_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
190                                 uint offset, ulong value,
191                                 enum pci_size_t size)
192 {
193         return pci_generic_mmap_write_config(bus, ls_pcie_conf_address,
194                                              bdf, offset, value, size);
195 }
196
197 /* Clear multi-function bit */
198 static void ls_pcie_clear_multifunction(struct ls_pcie_rc *pcie_rc)
199 {
200         struct ls_pcie *pcie = pcie_rc->pcie;
201
202         writeb(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE);
203 }
204
205 /* Fix class value */
206 static void ls_pcie_fix_class(struct ls_pcie_rc *pcie_rc)
207 {
208         struct ls_pcie *pcie = pcie_rc->pcie;
209
210         writew(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
211 }
212
213 /* Drop MSG TLP except for Vendor MSG */
214 static void ls_pcie_drop_msg_tlp(struct ls_pcie_rc *pcie_rc)
215 {
216         struct ls_pcie *pcie = pcie_rc->pcie;
217         u32 val;
218
219         val = dbi_readl(pcie, PCIE_STRFMR1);
220         val &= 0xDFFFFFFF;
221         dbi_writel(pcie, val, PCIE_STRFMR1);
222 }
223
224 /* Disable all bars in RC mode */
225 static void ls_pcie_disable_bars(struct ls_pcie_rc *pcie_rc)
226 {
227         struct ls_pcie *pcie = pcie_rc->pcie;
228
229         dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_0);
230         dbi_writel(pcie, 0, PCIE_CS2_OFFSET + PCI_BASE_ADDRESS_1);
231         dbi_writel(pcie, 0xfffffffe, PCIE_CS2_OFFSET + PCI_ROM_ADDRESS1);
232 }
233
234 static void ls_pcie_setup_ctrl(struct ls_pcie_rc *pcie_rc)
235 {
236         struct ls_pcie *pcie = pcie_rc->pcie;
237
238         ls_pcie_setup_atu(pcie_rc);
239
240         ls_pcie_dbi_ro_wr_en(pcie);
241         ls_pcie_fix_class(pcie_rc);
242         ls_pcie_clear_multifunction(pcie_rc);
243         ls_pcie_drop_msg_tlp(pcie_rc);
244         ls_pcie_dbi_ro_wr_dis(pcie);
245
246         ls_pcie_disable_bars(pcie_rc);
247 }
248
249 static int ls_pcie_probe(struct udevice *dev)
250 {
251         const struct ls_pcie_drvdata *drvdata = (void *)dev_get_driver_data(dev);
252         struct ls_pcie_rc *pcie_rc = dev_get_priv(dev);
253         const void *fdt = gd->fdt_blob;
254         int node = dev_of_offset(dev);
255         struct ls_pcie *pcie;
256         u16 link_sta;
257         uint svr;
258         int ret;
259         fdt_size_t cfg_size;
260
261         pcie_rc->bus = dev;
262
263         pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
264         if (!pcie)
265                 return -ENOMEM;
266
267         pcie_rc->pcie = pcie;
268
269         /* try resource name of the official binding first */
270         ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
271                                      "regs", &pcie_rc->dbi_res);
272         if (ret)
273                 ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
274                                              "dbi", &pcie_rc->dbi_res);
275         if (ret) {
276                 printf("ls-pcie: resource \"dbi\" not found\n");
277                 return ret;
278         }
279
280         pcie->idx = (pcie_rc->dbi_res.start - PCIE_SYS_BASE_ADDR) /
281                     PCIE_CCSR_SIZE;
282
283         list_add(&pcie_rc->list, &ls_pcie_list);
284
285         pcie_rc->enabled = is_serdes_configured(PCIE_SRDS_PRTCL(pcie->idx));
286         if (!pcie_rc->enabled) {
287                 printf("PCIe%d: %s disabled\n", PCIE_SRDS_PRTCL(pcie->idx),
288                        dev->name);
289                 return 0;
290         }
291
292         pcie->dbi = map_physmem(pcie_rc->dbi_res.start,
293                                 fdt_resource_size(&pcie_rc->dbi_res),
294                                 MAP_NOCACHE);
295
296         pcie->mode = readb(pcie->dbi + PCI_HEADER_TYPE) & 0x7f;
297         if (pcie->mode == PCI_HEADER_TYPE_NORMAL)
298                 return 0;
299
300         if (drvdata) {
301                 pcie->lut = pcie->dbi + drvdata->lut_offset;
302         } else {
303                 ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
304                                              "lut", &pcie_rc->lut_res);
305                 if (!ret)
306                         pcie->lut = map_physmem(pcie_rc->lut_res.start,
307                                                 fdt_resource_size(&pcie_rc->lut_res),
308                                                 MAP_NOCACHE);
309         }
310
311         if (drvdata) {
312                 pcie->ctrl = pcie->lut + drvdata->ctrl_offset;
313         } else {
314                 ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
315                                              "ctrl", &pcie_rc->ctrl_res);
316                 if (!ret)
317                         pcie->ctrl = map_physmem(pcie_rc->ctrl_res.start,
318                                                  fdt_resource_size(&pcie_rc->ctrl_res),
319                                                  MAP_NOCACHE);
320                 if (!pcie->ctrl)
321                         pcie->ctrl = pcie->lut;
322         }
323
324         if (!pcie->ctrl) {
325                 printf("%s: NOT find CTRL\n", dev->name);
326                 return -1;
327         }
328
329         ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
330                                      "config", &pcie_rc->cfg_res);
331         if (ret) {
332                 printf("%s: resource \"config\" not found\n", dev->name);
333                 return ret;
334         }
335
336         cfg_size = fdt_resource_size(&pcie_rc->cfg_res);
337         if (cfg_size < SZ_8K) {
338                 printf("PCIe%d: %s Invalid size(0x%llx) for resource \"config\",expected minimum 0x%x\n",
339                        PCIE_SRDS_PRTCL(pcie->idx), dev->name, (u64)cfg_size, SZ_8K);
340                 return 0;
341         }
342
343         /*
344          * Fix the pcie memory map address and PF control registers address
345          * for LS2088A series SoCs
346          */
347         svr = get_svr();
348         svr = (svr >> SVR_VAR_PER_SHIFT) & 0xFFFFFE;
349         if (svr == SVR_LS2088A || svr == SVR_LS2084A ||
350             svr == SVR_LS2048A || svr == SVR_LS2044A ||
351             svr == SVR_LS2081A || svr == SVR_LS2041A) {
352                 pcie_rc->cfg_res.start = LS2088A_PCIE1_PHYS_ADDR +
353                                          LS2088A_PCIE_PHYS_SIZE * pcie->idx;
354                 pcie_rc->cfg_res.end = pcie_rc->cfg_res.start + cfg_size;
355                 pcie->ctrl = pcie->lut + 0x40000;
356         }
357
358         pcie_rc->cfg0 = map_physmem(pcie_rc->cfg_res.start,
359                                     fdt_resource_size(&pcie_rc->cfg_res),
360                                     MAP_NOCACHE);
361         pcie_rc->cfg1 = pcie_rc->cfg0 +
362                         fdt_resource_size(&pcie_rc->cfg_res) / 2;
363
364         if (drvdata)
365                 pcie->big_endian = drvdata->big_endian;
366         else
367                 pcie->big_endian = fdtdec_get_bool(fdt, node, "big-endian");
368
369         debug("%s dbi:%lx lut:%lx ctrl:0x%lx cfg0:0x%lx, big-endian:%d\n",
370               dev->name, (unsigned long)pcie->dbi, (unsigned long)pcie->lut,
371               (unsigned long)pcie->ctrl, (unsigned long)pcie_rc->cfg0,
372               pcie->big_endian);
373
374         printf("PCIe%u: %s %s", PCIE_SRDS_PRTCL(pcie->idx), dev->name,
375                "Root Complex");
376         ls_pcie_setup_ctrl(pcie_rc);
377
378         if (!ls_pcie_link_up(pcie)) {
379                 /* Let the user know there's no PCIe link */
380                 printf(": no link\n");
381                 return 0;
382         }
383
384         /* Print the negotiated PCIe link width */
385         link_sta = readw(pcie->dbi + PCIE_LINK_STA);
386         printf(": x%d gen%d\n", (link_sta & PCIE_LINK_WIDTH_MASK) >> 4,
387                link_sta & PCIE_LINK_SPEED_MASK);
388
389         return 0;
390 }
391
392 static const struct dm_pci_ops ls_pcie_ops = {
393         .read_config    = ls_pcie_read_config,
394         .write_config   = ls_pcie_write_config,
395 };
396
397 static const struct ls_pcie_drvdata ls1028a_drvdata = {
398         .lut_offset = 0x80000,
399         .ctrl_offset = 0x40000,
400         .big_endian = false,
401 };
402
403 static const struct udevice_id ls_pcie_ids[] = {
404         { .compatible = "fsl,ls-pcie" },
405         { .compatible = "fsl,ls1028a-pcie", .data = (ulong)&ls1028a_drvdata },
406         { .compatible = "fsl,ls1088a-pcie", .data = (ulong)&ls1028a_drvdata },
407         { }
408 };
409
410 U_BOOT_DRIVER(pci_layerscape) = {
411         .name = "pci_layerscape",
412         .id = UCLASS_PCI,
413         .of_match = ls_pcie_ids,
414         .ops = &ls_pcie_ops,
415         .probe  = ls_pcie_probe,
416         .priv_auto      = sizeof(struct ls_pcie_rc),
417 };