Lines Matching +full:pcie +full:- +full:2
1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe driver for Marvell MVEBU SoCs
5 * Based on Barebox drivers/pci/pci-mvebu.c
7 * Ported to U-Boot by:
14 #include <dm/device-internal.h>
27 /* PCIe unit register offsets */
38 #define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4))
84 * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
91 static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie) in mvebu_pcie_link_up() argument
94 val = readl(pcie->base + PCIE_STAT_OFF); in mvebu_pcie_link_up()
98 static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie *pcie, int busno) in mvebu_pcie_set_local_bus_nr() argument
102 stat = readl(pcie->base + PCIE_STAT_OFF); in mvebu_pcie_set_local_bus_nr()
105 writel(stat, pcie->base + PCIE_STAT_OFF); in mvebu_pcie_set_local_bus_nr()
108 static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int devno) in mvebu_pcie_set_local_dev_nr() argument
112 stat = readl(pcie->base + PCIE_STAT_OFF); in mvebu_pcie_set_local_dev_nr()
115 writel(stat, pcie->base + PCIE_STAT_OFF); in mvebu_pcie_set_local_dev_nr()
118 static int mvebu_pcie_get_local_bus_nr(struct mvebu_pcie *pcie) in mvebu_pcie_get_local_bus_nr() argument
122 stat = readl(pcie->base + PCIE_STAT_OFF); in mvebu_pcie_get_local_bus_nr()
126 static int mvebu_pcie_get_local_dev_nr(struct mvebu_pcie *pcie) in mvebu_pcie_get_local_dev_nr() argument
130 stat = readl(pcie->base + PCIE_STAT_OFF); in mvebu_pcie_get_local_dev_nr()
143 struct mvebu_pcie *pcie = dev_get_platdata(bus); in mvebu_pcie_read_config() local
144 int local_bus = PCI_BUS(pcie->dev); in mvebu_pcie_read_config()
145 int local_dev = PCI_DEV(pcie->dev); in mvebu_pcie_read_config()
149 debug("PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) ", in mvebu_pcie_read_config()
155 debug("- out of range\n"); in mvebu_pcie_read_config()
163 debug("- out of range\n"); in mvebu_pcie_read_config()
175 writel(reg, pcie->base + PCIE_CONF_ADDR_OFF); in mvebu_pcie_read_config()
176 data = readl(pcie->base + PCIE_CONF_DATA_OFF); in mvebu_pcie_read_config()
187 struct mvebu_pcie *pcie = dev_get_platdata(bus); in mvebu_pcie_write_config() local
188 int local_bus = PCI_BUS(pcie->dev); in mvebu_pcie_write_config()
189 int local_dev = PCI_DEV(pcie->dev); in mvebu_pcie_write_config()
192 debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", in mvebu_pcie_write_config()
213 writel(PCIE_CONF_ADDR(bdf, offset), pcie->base + PCIE_CONF_ADDR_OFF); in mvebu_pcie_write_config()
215 writel(data, pcie->base + PCIE_CONF_DATA_OFF); in mvebu_pcie_write_config()
221 * Setup PCIE BARs and Address Decode Wins:
222 * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
223 * WIN[0-3] -> DRAM bank[0-3]
225 static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie) in mvebu_pcie_setup_wins() argument
233 writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i)); in mvebu_pcie_setup_wins()
234 writel(0, pcie->base + PCIE_BAR_LO_OFF(i)); in mvebu_pcie_setup_wins()
235 writel(0, pcie->base + PCIE_BAR_HI_OFF(i)); in mvebu_pcie_setup_wins()
239 writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i)); in mvebu_pcie_setup_wins()
240 writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i)); in mvebu_pcie_setup_wins()
241 writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i)); in mvebu_pcie_setup_wins()
244 writel(0, pcie->base + PCIE_WIN5_CTRL_OFF); in mvebu_pcie_setup_wins()
245 writel(0, pcie->base + PCIE_WIN5_BASE_OFF); in mvebu_pcie_setup_wins()
246 writel(0, pcie->base + PCIE_WIN5_REMAP_OFF); in mvebu_pcie_setup_wins()
250 for (i = 0; i < dram->num_cs; i++) { in mvebu_pcie_setup_wins()
251 const struct mbus_dram_window *cs = dram->cs + i; in mvebu_pcie_setup_wins()
253 writel(cs->base & 0xffff0000, in mvebu_pcie_setup_wins()
254 pcie->base + PCIE_WIN04_BASE_OFF(i)); in mvebu_pcie_setup_wins()
255 writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i)); in mvebu_pcie_setup_wins()
256 writel(((cs->size - 1) & 0xffff0000) | in mvebu_pcie_setup_wins()
257 (cs->mbus_attr << 8) | in mvebu_pcie_setup_wins()
258 (dram->mbus_dram_target_id << 4) | 1, in mvebu_pcie_setup_wins()
259 pcie->base + PCIE_WIN04_CTRL_OFF(i)); in mvebu_pcie_setup_wins()
261 size += cs->size; in mvebu_pcie_setup_wins()
265 if ((size & (size - 1)) != 0) in mvebu_pcie_setup_wins()
269 writel(dram->cs[0].base | 0xc, pcie->base + PCIE_BAR_LO_OFF(1)); in mvebu_pcie_setup_wins()
270 writel(0, pcie->base + PCIE_BAR_HI_OFF(1)); in mvebu_pcie_setup_wins()
271 writel(((size - 1) & 0xffff0000) | 0x1, in mvebu_pcie_setup_wins()
272 pcie->base + PCIE_BAR_CTRL_OFF(1)); in mvebu_pcie_setup_wins()
277 struct mvebu_pcie *pcie = dev_get_platdata(dev); in mvebu_pcie_probe() local
283 debug("%s: PCIe %d.%d - up, base %08x\n", __func__, in mvebu_pcie_probe()
284 pcie->port, pcie->lane, (u32)pcie->base); in mvebu_pcie_probe()
288 readl(pcie->base), mvebu_pcie_get_local_bus_nr(pcie), in mvebu_pcie_probe()
289 mvebu_pcie_get_local_dev_nr(pcie)); in mvebu_pcie_probe()
291 mvebu_pcie_set_local_bus_nr(pcie, bus); in mvebu_pcie_probe()
292 mvebu_pcie_set_local_dev_nr(pcie, 0); in mvebu_pcie_probe()
293 pcie->dev = PCI_BDF(bus, 0, 0); in mvebu_pcie_probe()
295 pcie->mem.start = (u32)mvebu_pcie_membase; in mvebu_pcie_probe()
296 pcie->mem.end = pcie->mem.start + PCIE_MEM_SIZE - 1; in mvebu_pcie_probe()
299 if (mvebu_mbus_add_window_by_id(pcie->mem_target, pcie->mem_attr, in mvebu_pcie_probe()
300 (phys_addr_t)pcie->mem.start, in mvebu_pcie_probe()
302 printf("PCIe unable to add mbus window for mem at %08x+%08x\n", in mvebu_pcie_probe()
303 (u32)pcie->mem.start, PCIE_MEM_SIZE); in mvebu_pcie_probe()
307 mvebu_pcie_setup_wins(pcie); in mvebu_pcie_probe()
310 reg = readl(pcie->base + PCIE_CMD_OFF); in mvebu_pcie_probe()
314 writel(reg, pcie->base + PCIE_CMD_OFF); in mvebu_pcie_probe()
317 writel(SOC_REGS_PHY_BASE, pcie->base + PCIE_BAR_LO_OFF(0)); in mvebu_pcie_probe()
318 writel(0, pcie->base + PCIE_BAR_HI_OFF(0)); in mvebu_pcie_probe()
321 pci_set_region(hose->regions + 0, pcie->mem.start, in mvebu_pcie_probe()
322 pcie->mem.start, PCIE_MEM_SIZE, PCI_REGION_MEM); in mvebu_pcie_probe()
323 pci_set_region(hose->regions + 1, in mvebu_pcie_probe()
325 gd->ram_size, in mvebu_pcie_probe()
327 hose->region_count = 2; in mvebu_pcie_probe()
334 static int mvebu_pcie_port_parse_dt(ofnode node, struct mvebu_pcie *pcie) in mvebu_pcie_port_parse_dt() argument
339 addr = ofnode_get_property(node, "assigned-addresses", &len); in mvebu_pcie_port_parse_dt()
341 pr_err("property \"assigned-addresses\" not found"); in mvebu_pcie_port_parse_dt()
342 return -FDT_ERR_NOTFOUND; in mvebu_pcie_port_parse_dt()
345 pcie->base = (void *)(fdt32_to_cpu(addr[2]) + SOC_REGS_PHY_BASE); in mvebu_pcie_port_parse_dt()
361 const int na = 3, ns = 2; in mvebu_get_tgt_attr()
365 *tgt = -1; in mvebu_get_tgt_attr()
366 *attr = -1; in mvebu_get_tgt_attr()
370 return -EINVAL; in mvebu_get_tgt_attr()
374 * here. Currently this function is only available in U-Boot when in mvebu_get_tgt_attr()
376 * general, lets't hardcode the "pna" value in the U-Boot code. in mvebu_get_tgt_attr()
378 pna = 2; /* hardcoded for now because of lack of of_n_addr_cells() */ in mvebu_get_tgt_attr()
397 * in bits 7..0. PCI_DEV() in U-Boot is similar to PCI_SLOT(), in mvebu_get_tgt_attr()
407 return -ENOENT; in mvebu_get_tgt_attr()
412 struct mvebu_pcie *pcie = dev_get_platdata(dev); in mvebu_pcie_ofdata_to_platdata() local
416 if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-port", in mvebu_pcie_ofdata_to_platdata()
417 &pcie->port)) { in mvebu_pcie_ofdata_to_platdata()
418 ret = -ENODEV; in mvebu_pcie_ofdata_to_platdata()
422 if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-lane", &pcie->lane)) in mvebu_pcie_ofdata_to_platdata()
423 pcie->lane = 0; in mvebu_pcie_ofdata_to_platdata()
425 sprintf(pcie->name, "pcie%d.%d", pcie->port, pcie->lane); in mvebu_pcie_ofdata_to_platdata()
428 pcie->devfn = pci_get_devfn(dev); in mvebu_pcie_ofdata_to_platdata()
429 if (pcie->devfn < 0) { in mvebu_pcie_ofdata_to_platdata()
430 ret = -ENODEV; in mvebu_pcie_ofdata_to_platdata()
434 ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn, in mvebu_pcie_ofdata_to_platdata()
436 &pcie->mem_target, &pcie->mem_attr); in mvebu_pcie_ofdata_to_platdata()
438 printf("%s: cannot get tgt/attr for mem window\n", pcie->name); in mvebu_pcie_ofdata_to_platdata()
442 /* Parse PCIe controller register base from DT */ in mvebu_pcie_ofdata_to_platdata()
443 ret = mvebu_pcie_port_parse_dt(dev_ofnode(dev), pcie); in mvebu_pcie_ofdata_to_platdata()
448 if (!mvebu_pcie_link_up(pcie)) { in mvebu_pcie_ofdata_to_platdata()
449 debug("%s: %s - down\n", __func__, pcie->name); in mvebu_pcie_ofdata_to_platdata()
450 ret = -ENODEV; in mvebu_pcie_ofdata_to_platdata()
476 * PCIe base controller in UCLASS_PCI.
480 struct mvebu_pcie *pcie; in mvebu_pcie_bind() local
489 return -ENOENT; in mvebu_pcie_bind()
496 pcie = calloc(1, sizeof(*pcie)); in mvebu_pcie_bind()
497 if (!pcie) in mvebu_pcie_bind()
498 return -ENOMEM; in mvebu_pcie_bind()
501 device_bind_ofnode(parent, &pcie_mvebu_drv, pcie->name, pcie, in mvebu_pcie_bind()
509 { .compatible = "marvell,armada-xp-pcie" },
510 { .compatible = "marvell,armada-370-pcie" },