1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2021 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
6 * Copyright (c) 2021 Rockchip, Inc.
8 * Copyright (C) 2018 Texas Instruments, Inc
15 #include <dm/device_compat.h>
17 #include <linux/delay.h>
18 #include "pcie_dw_common.h"
20 int pcie_dw_get_link_speed(struct pcie_dw *pci)
22 return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) &
23 PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF;
26 int pcie_dw_get_link_width(struct pcie_dw *pci)
28 return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) &
29 PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
32 static void dw_pcie_writel_ob_unroll(struct pcie_dw *pci, u32 index, u32 reg,
35 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
36 void __iomem *base = pci->atu_base;
38 writel(val, base + offset + reg);
41 static u32 dw_pcie_readl_ob_unroll(struct pcie_dw *pci, u32 index, u32 reg)
43 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
44 void __iomem *base = pci->atu_base;
46 return readl(base + offset + reg);
50 * pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses
52 * @pcie: Pointer to the PCI controller state
53 * @index: ATU region index
54 * @type: ATU accsess type
55 * @cpu_addr: the physical address for the translation entry
56 * @pci_addr: the pcie bus address for the translation entry
57 * @size: the size of the translation entry
59 * Return: 0 is successful and -1 is failure
61 int pcie_dw_prog_outbound_atu_unroll(struct pcie_dw *pci, int index,
62 int type, u64 cpu_addr,
63 u64 pci_addr, u32 size)
67 dev_dbg(pci->dev, "ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n",
68 index, type, cpu_addr, pci_addr, size);
70 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
71 lower_32_bits(cpu_addr));
72 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
73 upper_32_bits(cpu_addr));
74 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
75 lower_32_bits(cpu_addr + size - 1));
76 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
77 lower_32_bits(pci_addr));
78 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
79 upper_32_bits(pci_addr));
80 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
82 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
86 * Make sure ATU enable takes effect before any subsequent config
89 for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
90 val = dw_pcie_readl_ob_unroll(pci, index,
91 PCIE_ATU_UNR_REGION_CTRL2);
92 if (val & PCIE_ATU_ENABLE)
95 udelay(LINK_WAIT_IATU);
97 dev_err(pci->dev, "outbound iATU is not being enabled\n");
103 * set_cfg_address() - Configure the PCIe controller config space access
105 * @pcie: Pointer to the PCI controller state
106 * @d: PCI device to access
107 * @where: Offset in the configuration space
109 * Configures the PCIe controller to access the configuration space of
110 * a specific PCIe device and returns the address to use for this
113 * Return: Address that can be used to access the configation space
114 * of the requested device / offset
116 static uintptr_t set_cfg_address(struct pcie_dw *pcie,
117 pci_dev_t d, uint where)
119 int bus = PCI_BUS(d) - pcie->first_busno;
120 uintptr_t va_address;
124 /* Use dbi_base for own configuration read and write */
126 va_address = (uintptr_t)pcie->dbi_base;
132 * For local bus whose primary bus number is root bridge,
133 * change TLP Type field to 4.
135 atu_type = PCIE_ATU_TYPE_CFG0;
137 /* Otherwise, change TLP Type field to 5. */
138 atu_type = PCIE_ATU_TYPE_CFG1;
141 * Not accessing root port configuration space?
142 * Region #0 is used for Outbound CFG space access.
143 * Direction = Outbound
147 d = PCI_ADD_BUS(bus, d);
148 ret = pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
149 atu_type, (u64)pcie->cfg_base,
150 d << 8, pcie->cfg_size);
152 return (uintptr_t)ret;
154 va_address = (uintptr_t)pcie->cfg_base;
157 va_address += where & ~0x3;
163 * pcie_dw_addr_valid() - Check for valid bus address
165 * @d: The PCI device to access
166 * @first_busno: Bus number of the PCIe controller root complex
168 * Return 1 (true) if the PCI device can be accessed by this controller.
170 * Return: 1 on valid, 0 on invalid
172 static int pcie_dw_addr_valid(pci_dev_t d, int first_busno)
174 if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0))
176 if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0))
183 * pcie_dw_read_config() - Read from configuration space
185 * @bus: Pointer to the PCI bus
186 * @bdf: Identifies the PCIe device to access
187 * @offset: The offset into the device's configuration space
188 * @valuep: A pointer at which to store the read value
189 * @size: Indicates the size of access to perform
191 * Read a value of size @size from offset @offset within the configuration
192 * space of the device identified by the bus, device & function numbers in @bdf
193 * on the PCI bus @bus.
195 * Return: 0 on success
197 int pcie_dw_read_config(const struct udevice *bus, pci_dev_t bdf,
198 uint offset, ulong *valuep,
199 enum pci_size_t size)
201 struct pcie_dw *pcie = dev_get_priv(bus);
202 uintptr_t va_address;
205 dev_dbg(pcie->dev, "PCIE CFG read: bdf=%2x:%2x:%2x ",
206 PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
208 if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) {
209 debug("- out of range\n");
210 *valuep = pci_get_ff(size);
214 va_address = set_cfg_address(pcie, bdf, offset);
216 value = readl((void __iomem *)va_address);
218 debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
219 *valuep = pci_conv_32_to_size(value, offset, size);
221 return pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
222 PCIE_ATU_TYPE_IO, pcie->io.phys_start,
223 pcie->io.bus_start, pcie->io.size);
227 * pcie_dw_write_config() - Write to configuration space
229 * @bus: Pointer to the PCI bus
230 * @bdf: Identifies the PCIe device to access
231 * @offset: The offset into the device's configuration space
232 * @value: The value to write
233 * @size: Indicates the size of access to perform
235 * Write the value @value of size @size from offset @offset within the
236 * configuration space of the device identified by the bus, device & function
237 * numbers in @bdf on the PCI bus @bus.
239 * Return: 0 on success
241 int pcie_dw_write_config(struct udevice *bus, pci_dev_t bdf,
242 uint offset, ulong value,
243 enum pci_size_t size)
245 struct pcie_dw *pcie = dev_get_priv(bus);
246 uintptr_t va_address;
249 dev_dbg(pcie->dev, "PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
250 PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
251 dev_dbg(pcie->dev, "(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
253 if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) {
254 debug("- out of range\n");
258 va_address = set_cfg_address(pcie, bdf, offset);
260 old = readl((void __iomem *)va_address);
261 value = pci_conv_size_to_32(old, value, offset, size);
262 writel(value, (void __iomem *)va_address);
264 return pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
265 PCIE_ATU_TYPE_IO, pcie->io.phys_start,
266 pcie->io.bus_start, pcie->io.size);
270 * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion
272 * @pcie: Pointer to the PCI controller state
274 * Configure the host BARs of the PCIe controller root port so that
275 * PCI(e) devices may access the system memory.
277 void pcie_dw_setup_host(struct pcie_dw *pci)
279 struct udevice *ctlr = pci_get_controller(pci->dev);
280 struct pci_controller *hose = dev_get_uclass_priv(ctlr);
284 pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
287 writel(PCI_BASE_ADDRESS_MEM_TYPE_64,
288 pci->dbi_base + PCI_BASE_ADDRESS_0);
289 writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_1);
291 /* setup interrupt pins */
292 clrsetbits_le32(pci->dbi_base + PCI_INTERRUPT_LINE,
295 /* setup bus numbers */
296 clrsetbits_le32(pci->dbi_base + PCI_PRIMARY_BUS,
297 0xffffff, 0x00ff0100);
299 /* setup command register */
300 clrsetbits_le32(pci->dbi_base + PCI_PRIMARY_BUS,
302 PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
303 PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
305 /* Enable write permission for the DBI read-only register */
306 dw_pcie_dbi_write_enable(pci, true);
307 /* program correct class for RC */
308 writew(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE);
309 /* Better disable write permission right after the update */
310 dw_pcie_dbi_write_enable(pci, false);
312 setbits_le32(pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL,
313 PORT_LOGIC_SPEED_CHANGE);
315 for (ret = 0; ret < hose->region_count; ret++) {
316 if (hose->regions[ret].flags == PCI_REGION_IO) {
317 pci->io.phys_start = hose->regions[ret].phys_start; /* IO base */
318 pci->io.bus_start = hose->regions[ret].bus_start; /* IO_bus_addr */
319 pci->io.size = hose->regions[ret].size; /* IO size */
320 } else if (hose->regions[ret].flags == PCI_REGION_MEM) {
321 pci->mem.phys_start = hose->regions[ret].phys_start; /* MEM base */
322 pci->mem.bus_start = hose->regions[ret].bus_start; /* MEM_bus_addr */
323 pci->mem.size = hose->regions[ret].size; /* MEM size */
324 } else if (hose->regions[ret].flags == PCI_REGION_PREFETCH) {
325 pci->prefetch.phys_start = hose->regions[ret].phys_start; /* PREFETCH base */
326 pci->prefetch.bus_start = hose->regions[ret].bus_start; /* PREFETCH_bus_addr */
327 pci->prefetch.size = hose->regions[ret].size; /* PREFETCH size */
328 } else if (hose->regions[ret].flags == PCI_REGION_SYS_MEMORY) {
329 pci->cfg_base = (void *)(pci->io.phys_start - pci->io.size);
330 pci->cfg_size = pci->io.size;
332 dev_err(pci->dev, "invalid flags type!\n");
336 dev_dbg(pci->dev, "Config space: [0x%llx - 0x%llx, size 0x%llx]\n",
337 (u64)pci->cfg_base, (u64)pci->cfg_base + pci->cfg_size,
340 dev_dbg(pci->dev, "IO space: [0x%llx - 0x%llx, size 0x%llx]\n",
341 (u64)pci->io.phys_start, (u64)pci->io.phys_start + pci->io.size,
344 dev_dbg(pci->dev, "IO bus: [0x%llx - 0x%llx, size 0x%llx]\n",
345 (u64)pci->io.bus_start, (u64)pci->io.bus_start + pci->io.size,
348 dev_dbg(pci->dev, "MEM space: [0x%llx - 0x%llx, size 0x%llx]\n",
349 (u64)pci->mem.phys_start,
350 (u64)pci->mem.phys_start + pci->mem.size,
353 dev_dbg(pci->dev, "MEM bus: [0x%llx - 0x%llx, size 0x%llx]\n",
354 (u64)pci->mem.bus_start,
355 (u64)pci->mem.bus_start + pci->mem.size,
358 if (pci->prefetch.size) {
359 dev_dbg(pci->dev, "PREFETCH space: [0x%llx - 0x%llx, size 0x%llx]\n",
360 (u64)pci->prefetch.phys_start,
361 (u64)pci->prefetch.phys_start + pci->prefetch.size,
362 (u64)pci->prefetch.size);
364 dev_dbg(pci->dev, "PREFETCH bus: [0x%llx - 0x%llx, size 0x%llx]\n",
365 (u64)pci->prefetch.bus_start,
366 (u64)pci->prefetch.bus_start + pci->prefetch.size,
367 (u64)pci->prefetch.size);