xref: /aosp_15_r20/external/coreboot/src/soc/qualcomm/common/pcie_common.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <boot/coreboot_tables.h>
4 #include <console/console.h>
5 #include <delay.h>
6 #include <device/device.h>
7 #include <device/mmio.h>
8 #include <device/pci.h>
9 #include <device/pci_ids.h>
10 #include <gpio.h>
11 #include <soc/clock.h>
12 #include <soc/qcom_qmp_phy.h>
13 #include <soc/pcie.h>
14 #include <timer.h>
15 
16 #define ROOT_PORT_BDF		0x0
17 #define ATU_CTRL2		PCIE_ATU_UNR_REGION_CTRL2
18 
19 static struct qcom_pcie_cntlr_t qcom_pcie_cfg;
20 
dw_pcie_dbi_rd_wr(bool enable)21 static inline void dw_pcie_dbi_rd_wr(bool enable)
22 {
23 	uint32_t val;
24 	pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
25 
26 	val = read32(pcierc->dbi_base + PCIE_DBI_MISC_CONTROL_1_OFF);
27 
28 	if (enable)
29 		val |= PCIE_DBI_RO_WR_EN;
30 	else
31 		val &= ~PCIE_DBI_RO_WR_EN;
32 
33 	write32(pcierc->dbi_base + PCIE_DBI_MISC_CONTROL_1_OFF, val);
34 }
35 
dw_pcie_writel_iatu(unsigned int index,uint32_t reg,uint32_t val)36 static void dw_pcie_writel_iatu(unsigned int index, uint32_t reg, uint32_t val)
37 {
38 	pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
39 	unsigned int offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
40 
41 	write32(pcierc->atu_base + offset + reg, val);
42 }
43 
dw_pcie_readl_iatu(unsigned int index,uint32_t reg)44 static uint32_t dw_pcie_readl_iatu(unsigned int index, uint32_t reg)
45 {
46 	pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
47 	unsigned int offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
48 
49 	return read32(pcierc->atu_base + offset + reg);
50 }
51 
qcom_dw_pcie_prog_outbound_atu(unsigned int index,unsigned int type,uint64_t cpu_addr,uint64_t pcie_addr,uint32_t size)52 static void qcom_dw_pcie_prog_outbound_atu(unsigned int index,
53 					   unsigned int type, uint64_t cpu_addr,
54 					   uint64_t pcie_addr, uint32_t size)
55 {
56 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_LOWER_BASE, lower_32_bits(cpu_addr));
57 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_UPPER_BASE, upper_32_bits(cpu_addr));
58 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_LIMIT, lower_32_bits(cpu_addr + size - 1));
59 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_LOWER_TARGET, lower_32_bits(pcie_addr));
60 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_UPPER_TARGET, upper_32_bits(pcie_addr));
61 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_REGION_CTRL1, type);
62 	dw_pcie_writel_iatu(index, PCIE_ATU_UNR_REGION_CTRL2, PCIE_ATU_ENABLE);
63 
64 	/* Ensure ATU enable takes effect before any subsequent config access */
65 	if (retry(LINK_WAIT_MAX_IATU_RETRIES,
66 		  (dw_pcie_readl_iatu(index, ATU_CTRL2) & PCIE_ATU_ENABLE),
67 		  udelay(LINK_WAIT_IATU)))
68 		return;
69 
70 	printk(BIOS_ERR, "PCIe o/b iATU couldn't be enabled after 5ms\n");
71 }
72 
qcom_pcie_configure_gpios(pcie_cntlr_cfg_t * cfg)73 static void qcom_pcie_configure_gpios(pcie_cntlr_cfg_t *cfg)
74 {
75 	gpio_configure(cfg->perst, 0, GPIO_NO_PULL, GPIO_16MA, GPIO_OUTPUT);
76 }
77 
78 /**
79  * qcom_dw_pcie_configure() - Configure link capabilities and speed
80  *
81  * Configure the link capabilities and speed in the PCIe root complex.
82  */
qcom_dw_pcie_configure(uint32_t cap_speed)83 static void qcom_dw_pcie_configure(uint32_t cap_speed)
84 {
85 	pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
86 
87 	dw_pcie_dbi_rd_wr(true);
88 
89 	clrsetbits32(pcierc->dbi_base + PCIE_LINK_CAPABILITY,
90 		     TARGET_LINK_SPEED_MASK, cap_speed);
91 
92 	clrsetbits32(pcierc->dbi_base + PCIE_LINK_CTL_2,
93 		     TARGET_LINK_SPEED_MASK, cap_speed);
94 
95 	dw_pcie_dbi_rd_wr(false);
96 	printk(BIOS_INFO, "PCIe Link speed configured in Gen %d\n", cap_speed);
97 }
98 
99 /**
100  * is_pcie_link_up() - Return the link state
101  *
102  * Return: true for active link and false for no link
103  */
is_pcie_link_up(struct qcom_pcie_cntlr_t * pci)104 static bool is_pcie_link_up(struct qcom_pcie_cntlr_t *pci)
105 {
106 	/* Read link status register */
107 	return !!(read32(pci->cntlr_cfg->elbi + PCIE3X2_ELBI_SYS_STTS) & XMLH_LINK_UP);
108 }
109 
110 /**
111  * wait_link_up() - Wait for the link to come up
112  *
113  * Return: true for active line and false for no link (timeout)
114  */
wait_link_up(struct qcom_pcie_cntlr_t * pci)115 static bool wait_link_up(struct qcom_pcie_cntlr_t *pci)
116 {
117 	/* Check if the link is up or not */
118 	if (retry(LINK_WAIT_MAX_RETRIES, is_pcie_link_up(pci), mdelay(PCIE_LINK_UP_MS)))
119 		return true;
120 
121 	printk(BIOS_ERR, "PCIe link is not up even after 1sec\n");
122 	return false;
123 }
124 
qcom_pcie_dw_link_up(struct qcom_pcie_cntlr_t * pcie)125 static enum cb_err qcom_pcie_dw_link_up(struct qcom_pcie_cntlr_t *pcie)
126 {
127 	if (is_pcie_link_up(pcie)) {
128 		printk(BIOS_INFO, "PCIe Link is already up\n");
129 		return CB_SUCCESS;
130 	}
131 
132 	/* DW pre link configurations */
133 	qcom_dw_pcie_configure(LINK_SPEED_GEN_2);
134 
135 	/* enable link training */
136 	setbits32(pcie->cntlr_cfg->parf + PCIE_PARF_LTSSM, LTSSM_EN);
137 
138 	/* Check that link was established */
139 	if (wait_link_up(pcie)) {
140 		printk(BIOS_INFO, "PCIe link is up\n");
141 		return CB_SUCCESS;
142 	}
143 
144 	/*
145 	 * Link can be established in Gen 1 as it failed to establish in Gen2.
146 	 * So allow some time to do it.
147 	 */
148 	udelay(100);
149 
150 	return CB_ERR;
151 }
152 
153 /**
154  * Returns root port config space address or endpoint config space address.
155  * For endpoint config address, mapping would be done with ATU.
156  */
qcom_dw_pcie_get_config_addr(struct qcom_pcie_cntlr_t * pcierc,pci_devfn_t dev)157 static void *qcom_dw_pcie_get_config_addr(struct qcom_pcie_cntlr_t *pcierc,
158 					  pci_devfn_t dev)
159 {
160 	unsigned int atu_type, cfg_size;
161 	void *cfg_address;
162 	uint32_t bus, busdev, devfn;
163 	pcie_cntlr_cfg_t *cntlr = pcierc->cntlr_cfg;
164 	bus = PCI_DEV2SEGBUS(dev);
165 	devfn = PCI_DEV2DEVFN(dev);
166 
167 	busdev = PCIE_ATU_BUS(bus) |
168 		 PCIE_ATU_DEV(PCI_SLOT(devfn)) |
169 		 PCIE_ATU_FUNC(PCI_FUNC(devfn));
170 
171 	/* Accessing root port configuration space */
172 	if (!bus && !devfn) {
173 		cfg_address = pcierc->cntlr_cfg->dbi_base;
174 		return cfg_address;
175 	}
176 
177 	/* For local bus use CFG0 type */
178 	atu_type = (bus == 1) ? PCIE_ATU_TYPE_CFG0 : PCIE_ATU_TYPE_CFG1;
179 
180 	cfg_address = cntlr->cfg_base + (cntlr->cfg_size * devfn);
181 	cfg_size = cntlr->cfg_size;
182 
183 	qcom_dw_pcie_prog_outbound_atu(PCIE_ATU_REGION_INDEX1, atu_type,
184 				       (uint64_t)cfg_address, busdev, cfg_size);
185 	return cfg_address;
186 }
187 
qcom_dw_pcie_setup_rc(struct qcom_pcie_cntlr_t * pcie)188 static void qcom_dw_pcie_setup_rc(struct qcom_pcie_cntlr_t *pcie)
189 {
190 	uint32_t val;
191 	pcie_cntlr_cfg_t *pcierc = pcie->cntlr_cfg;
192 	/*
193 	 * Enable DBI read-only registers for writing/updating configuration.
194 	 * Write permission gets disabled towards the end of this function.
195 	 */
196 	dw_pcie_dbi_rd_wr(true);
197 
198 	val = read32(pcierc->dbi_base + PCIE_PORT_LINK_CONTROL);
199 	/* Set the number of lanes */
200 	val &= ~PORT_LINK_MODE_MASK;
201 
202 	switch (pcierc->lanes) {
203 	case 1:
204 		val |= PORT_LINK_MODE_1_LANES;
205 		break;
206 	case 2:
207 		val |= PORT_LINK_MODE_2_LANES;
208 		break;
209 	case 4:
210 		val |= PORT_LINK_MODE_4_LANES;
211 		break;
212 	case 8:
213 		val |= PORT_LINK_MODE_8_LANES;
214 		break;
215 	default:
216 		printk(BIOS_INFO, "PCIe num-lanes %u: invalid value\n",
217 		       pcierc->lanes);
218 		return;
219 	}
220 
221 	write32(pcierc->dbi_base + PCIE_PORT_LINK_CONTROL, val);
222 
223 	/* Set link width speed control register */
224 	val = read32(pcierc->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
225 	val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
226 
227 	switch (pcierc->lanes) {
228 	case 1:
229 		val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
230 		break;
231 	case 2:
232 		val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
233 		break;
234 	case 4:
235 		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
236 		break;
237 	case 8:
238 		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
239 		break;
240 	default:
241 		printk(BIOS_INFO, "PCIe invalid lanes option\n");
242 		return;
243 	}
244 
245 	write32(pcierc->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL, val);
246 
247 	/* Setup bus numbers */
248 	clrsetbits32(pcierc->dbi_base + PCI_PRIMARY_BUS, TYPE1_HDR_BUS_NUM_MASK,
249 		     ROOT_PORT_BUS_NUM);
250 
251 	/* Disable SMMU */
252 	write32(pcierc->parf + PCIE_PARF_BDF_TO_SID_CFG, BDF_TO_SID_BYPASS);
253 
254 	/* Configure ATU for outbound accesses */
255 	qcom_dw_pcie_prog_outbound_atu(PCIE_ATU_REGION_INDEX0,
256 				       PCIE_ATU_TYPE_MEM,
257 				       pcierc->mem.phys_start,
258 				       ROOT_PORT_BDF, pcierc->mem.size);
259 
260 	/* Program correct class for RC */
261 	write16(pcierc->dbi_base + PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
262 
263 	/* Disable write permission right after the update */
264 	dw_pcie_dbi_rd_wr(false);
265 }
266 
qcom_qmp_phy_config_lane(void * base,const struct qcom_qmp_phy_init_tbl tbl[],unsigned int num,uint8_t ln_mask)267 static void qcom_qmp_phy_config_lane(void *base, const struct qcom_qmp_phy_init_tbl tbl[],
268 				     unsigned int num, uint8_t ln_mask)
269 {
270 	unsigned int i;
271 	const struct qcom_qmp_phy_init_tbl *t = tbl;
272 
273 	for (i = 0; i < num; i++, t++) {
274 		if (!(t->lane_mask & ln_mask))
275 			continue;
276 		write32(base + t->offset, t->val);
277 	}
278 }
279 
qcom_qmp_phy_configure(void * base,const struct qcom_qmp_phy_init_tbl tbl[],unsigned int num)280 static void qcom_qmp_phy_configure(void *base, const struct qcom_qmp_phy_init_tbl tbl[],
281 				   unsigned int num)
282 {
283 	qcom_qmp_phy_config_lane(base, tbl, num, 0xff);
284 }
285 
qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t * qphy)286 static enum cb_err qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t *qphy)
287 {
288 	uint64_t lock_us;
289 
290 	/* Release powerdown mode and allow endpoint refclk drive */
291 	write32(qphy->pcs + QPHY_PCS_PWR_DWN_CNTRL, SW_PWRDN | REFCLK_DRV_DSBL);
292 
293 	/* Serdes configuration */
294 	qcom_qmp_phy_configure(qphy->serdes, qphy->serdes_tbl, qphy->serdes_tbl_num);
295 
296 	/* Tx, Rx, and PCS configurations */
297 	qcom_qmp_phy_config_lane(qphy->tx0, qphy->tx_tbl, qphy->tx_tbl_num, 1);
298 	qcom_qmp_phy_config_lane(qphy->tx0, qphy->tx_tbl_sec, qphy->tx_tbl_num_sec, 1);
299 	qcom_qmp_phy_config_lane(qphy->tx1, qphy->tx_tbl, qphy->tx_tbl_num, 2);
300 	qcom_qmp_phy_config_lane(qphy->tx1, qphy->tx_tbl_sec, qphy->tx_tbl_num_sec, 2);
301 	qcom_qmp_phy_config_lane(qphy->rx0, qphy->rx_tbl, qphy->rx_tbl_num, 1);
302 	qcom_qmp_phy_config_lane(qphy->rx0, qphy->rx_tbl_sec, qphy->rx_tbl_num_sec, 1);
303 	qcom_qmp_phy_config_lane(qphy->rx1, qphy->rx_tbl, qphy->rx_tbl_num, 2);
304 	qcom_qmp_phy_config_lane(qphy->rx1, qphy->rx_tbl_sec, qphy->rx_tbl_num_sec, 2);
305 	qcom_qmp_phy_configure(qphy->pcs, qphy->pcs_tbl, qphy->pcs_tbl_num);
306 	qcom_qmp_phy_configure(qphy->pcs, qphy->pcs_tbl_sec, qphy->pcs_tbl_num_sec);
307 	qcom_qmp_phy_configure(qphy->pcs_misc, qphy->pcs_misc_tbl, qphy->pcs_misc_tbl_num);
308 	qcom_qmp_phy_configure(qphy->pcs_misc, qphy->pcs_misc_tbl_sec, qphy->pcs_tbl_num_sec);
309 
310 	/* Release software reset of PCS/Serdes */
311 	clrbits32(qphy->pcs + QPHY_SW_RESET, SW_RESET);
312 
313 	/* start PCS/Serdes to operation mode */
314 	write32(qphy->pcs  + QPHY_START_CTRL, PCS_START | SERDES_START);
315 
316 	/*
317 	 * Wait for PHY initialization to be done
318 	 * PCS_STATUS: wait for 1ms for PHY STATUS bit to be set
319 	 */
320 	lock_us = wait_us(1000, !(read32(qphy->qmp_phy_base + QPHY_PCS_STATUS) & PHY_STATUS));
321 	if (!lock_us) {
322 		printk(BIOS_ERR, "PCIe QMP PHY PLL failed to lock in 1ms\n");
323 		return CB_ERR;
324 	}
325 
326 	printk(BIOS_DEBUG, "PCIe QPHY Initialized took %lldus\n", lock_us);
327 
328 	qcom_dw_pcie_enable_pipe_clock();
329 
330 	return CB_SUCCESS;
331 }
332 
333 /*
334  * Reset the PCIe PHY core.
335  * Allow 100us delay to ensure reset is asserted.
336  */
qcom_qmp_reset_phy(struct qcom_pcie_cntlr_t * pcie)337 static void qcom_qmp_reset_phy(struct qcom_pcie_cntlr_t *pcie)
338 {
339 	clock_reset_bcr(pcie->cntlr_cfg->qmp_phy_bcr, 1);
340 	udelay(100);
341 	clock_reset_bcr(pcie->cntlr_cfg->qmp_phy_bcr, 0);
342 }
343 
344 /*
345  * Reset the PCIe controller core.
346  * Allow 100us delay to ensure reset is asserted.
347  */
qcom_dw_pcie_reset_core(struct qcom_pcie_cntlr_t * pcie)348 static void qcom_dw_pcie_reset_core(struct qcom_pcie_cntlr_t *pcie)
349 {
350 	clock_reset_bcr(pcie->cntlr_cfg->pcie_bcr, 1);
351 	udelay(100);
352 	clock_reset_bcr(pcie->cntlr_cfg->pcie_bcr, 0);
353 }
354 
qcom_dw_pcie_enable(struct qcom_pcie_cntlr_t * pcie)355 static enum cb_err qcom_dw_pcie_enable(struct qcom_pcie_cntlr_t *pcie)
356 {
357 	int ret;
358 
359 	pcie_cntlr_cfg_t *pcierc = pcie->cntlr_cfg;
360 	pcie_qmp_phy_cfg_t *qmp_phy = pcie->qmp_phy_cfg;
361 
362 	/* assert PCIe reset link to keep EP in reset */
363 	gpio_set(pcierc->perst, 0);
364 
365 	/* Enable PCIe controller and SoC specific clocks */
366 	ret = qcom_dw_pcie_enable_clock();
367 	if (ret) {
368 		printk(BIOS_ERR, "Enable PCIe clocks failed\n");
369 		return ret;
370 	}
371 
372 	/* Reset the controller */
373 	qcom_dw_pcie_reset_core(pcie);
374 
375 	/* configure PCIe to RC mode */
376 	write32(pcierc->parf + PCIE_PARF_DEVICE_TYPE, DEVICE_TYPE_RC);
377 
378 	/* Power on the PHY */
379 	clrbits32(pcierc->parf + PCIE_PARF_PHY_CTRL, PHY_PWR_DOWN);
380 
381 	/* MAC PHY_POWERDOWN MUX DISABLE */
382 	clrbits32(pcierc->parf + PCIE_PARF_SYS_CTRL, MAC_PHY_PWRDOWN_MUX_EN);
383 
384 	/* Bypass MHI as its not needed */
385 	setbits32(pcierc->parf + PCIE_PARF_MHI_CLOCK_RESET_CTRL, MHI_BYPASS);
386 
387 	qcom_qmp_reset_phy(pcie);
388 
389 	/* Initialize QMP PHY */
390 	ret = qcom_qmp_phy_power_on(qmp_phy);
391 	if (ret) {
392 		printk(BIOS_ERR, "PCIe PHY init failed\n");
393 		return ret;
394 	}
395 
396 	qcom_dw_pcie_setup_rc(pcie);
397 
398 	/* de-assert PCIe reset link to bring EP out of reset */
399 	gpio_set(pcierc->perst, 1);
400 
401 	/* establisth the link */
402 	ret = qcom_pcie_dw_link_up(pcie);
403 	if (ret) {
404 		printk(BIOS_ERR, "PCIe Link init failed\n");
405 		return ret;
406 	}
407 
408 	return CB_SUCCESS;
409 }
410 
411 /**
412  * Fill coreboot table with PCIe info.
413  * It allows exporting this info to payloads.
414  */
fill_lb_pcie(struct lb_pcie * pcie)415 enum cb_err fill_lb_pcie(struct lb_pcie *pcie)
416 {
417 	if (!mainboard_needs_pcie_init())
418 		return CB_ERR_NOT_IMPLEMENTED;
419 
420 	pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
421 	pcie->ctrl_base = (uintptr_t)pcierc->dbi_base;
422 	return CB_SUCCESS;
423 }
424 
425 /* map_bus function for mapping pcie_s_{read/write}_configXX() functions */
pci_map_bus(pci_devfn_t dev)426 volatile union pci_bank *pci_map_bus(pci_devfn_t dev)
427 {
428 	void *config_addr = NULL;
429 
430 	config_addr = qcom_dw_pcie_get_config_addr(&qcom_pcie_cfg, dev);
431 	return (void *)config_addr;
432 }
433 
434 /* PCI domain ops read_resources callback */
qcom_pci_domain_read_resources(struct device * dev)435 void qcom_pci_domain_read_resources(struct device *dev)
436 {
437 	struct resource *res;
438 	pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
439 
440 	/* Initialize the system-wide I/O space constraints. */
441 	res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
442 	res->base = pcierc->io.phys_start;
443 	res->limit = pcierc->io.size - 1;
444 	res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
445 
446 	/* Initialize the system-wide memory resources constraints. */
447 	res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
448 	res->base = pcierc->mem.phys_start;
449 	res->limit = pcierc->mem.size - 1;
450 	res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
451 }
452 
453 /* PCI domain ops enable callback */
qcom_setup_pcie_host(struct device * dev)454 void qcom_setup_pcie_host(struct device *dev)
455 {
456 	gcom_pcie_get_config(&qcom_pcie_cfg);
457 
458 	/* Ensure PCIe endpoints are powered-on before initiating PCIe link training */
459 	gcom_pcie_power_on_ep();
460 
461 	printk(BIOS_INFO, "Setup PCIe in RC mode\n");
462 
463 	/* Configure PERST gpio */
464 	qcom_pcie_configure_gpios(qcom_pcie_cfg.cntlr_cfg);
465 
466 	if (!qcom_dw_pcie_enable(&qcom_pcie_cfg))
467 		printk(BIOS_NOTICE, "PCIe enumerated succussfully..\n");
468 	else
469 		printk(BIOS_EMERG, "Failed to enable PCIe\n");
470 }
471