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