123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-09-23 GuEe-GUI first version
- */
- #define DBG_TAG "pcie.dw"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include "pcie-dw.h"
- static rt_uint8_t __dw_pcie_find_next_cap(struct dw_pcie *pci,
- rt_uint8_t cap_ptr, rt_uint8_t cap)
- {
- rt_uint16_t reg;
- rt_uint8_t cap_id, next_cap_ptr;
- if (!cap_ptr)
- {
- return 0;
- }
- reg = dw_pcie_readw_dbi(pci, cap_ptr);
- cap_id = (reg & 0x00ff);
- if (cap_id > PCIY_MAX)
- {
- return 0;
- }
- if (cap_id == cap)
- {
- return cap_ptr;
- }
- next_cap_ptr = (reg & 0xff00) >> 8;
- return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
- }
- rt_uint8_t dw_pcie_find_capability(struct dw_pcie *pci, rt_uint8_t cap)
- {
- rt_uint16_t reg;
- rt_uint8_t next_cap_ptr;
- reg = dw_pcie_readw_dbi(pci, PCIR_CAP_PTR);
- next_cap_ptr = (reg & 0x00ff);
- return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
- }
- static rt_uint16_t dw_pcie_find_next_ext_capability(struct dw_pcie *pci,
- rt_uint16_t start, rt_uint8_t cap)
- {
- rt_uint32_t header;
- int ttl, pos = PCI_REGMAX + 1;
- /* minimum 8 bytes per capability */
- ttl = ((PCIE_REGMAX + 1) - (PCI_REGMAX + 1)) / 8;
- if (start)
- {
- pos = start;
- }
- header = dw_pcie_readl_dbi(pci, pos);
- /*
- * If we have no capabilities, this is indicated by cap ID,
- * cap version and next pointer all being 0.
- */
- if (header == 0)
- {
- return 0;
- }
- while (ttl-- > 0)
- {
- if (PCI_EXTCAP_ID(header) == cap && pos != start)
- {
- return pos;
- }
- pos = PCI_EXTCAP_NEXTPTR(header);
- if (pos < PCI_REGMAX + 1)
- {
- break;
- }
- header = dw_pcie_readl_dbi(pci, pos);
- }
- return 0;
- }
- rt_uint16_t dw_pcie_find_ext_capability(struct dw_pcie *pci, rt_uint8_t cap)
- {
- return dw_pcie_find_next_ext_capability(pci, 0, cap);
- }
- rt_err_t dw_pcie_read(void *addr, rt_size_t size, rt_uint32_t *out_val)
- {
- /* Check aligned */
- if ((rt_ubase_t)addr & ((rt_ubase_t)size - 1))
- {
- *out_val = 0;
- return -RT_EINVAL;
- }
- if (size == 4)
- {
- *out_val = HWREG32(addr);
- }
- else if (size == 2)
- {
- *out_val = HWREG16(addr);
- }
- else if (size == 1)
- {
- *out_val = HWREG8(addr);
- }
- else
- {
- *out_val = 0;
- return -RT_EINVAL;
- }
- return RT_EOK;
- }
- rt_err_t dw_pcie_write(void *addr, rt_size_t size, rt_uint32_t val)
- {
- /* Check aligned */
- if ((rt_ubase_t)addr & ((rt_ubase_t)size - 1))
- {
- return -RT_EINVAL;
- }
- if (size == 4)
- {
- HWREG32(addr) = val;
- }
- else if (size == 2)
- {
- HWREG16(addr) = val;
- }
- else if (size == 1)
- {
- HWREG8(addr) = val;
- }
- else
- {
- return -RT_EINVAL;
- }
- return RT_EOK;
- }
- rt_uint32_t dw_pcie_read_dbi(struct dw_pcie *pci, rt_uint32_t reg, rt_size_t size)
- {
- rt_err_t err;
- rt_uint32_t val = 0;
- if (pci->ops->read_dbi)
- {
- return pci->ops->read_dbi(pci, pci->dbi_base, reg, size);
- }
- if ((err = dw_pcie_read(pci->dbi_base + reg, size, &val)))
- {
- LOG_E("Read DBI address error = %s", rt_strerror(err));
- }
- return val;
- }
- void dw_pcie_write_dbi(struct dw_pcie *pci, rt_uint32_t reg, rt_size_t size, rt_uint32_t val)
- {
- rt_err_t err;
- if (pci->ops->write_dbi)
- {
- pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val);
- return;
- }
- if ((err = dw_pcie_write(pci->dbi_base + reg, size, val)))
- {
- LOG_E("Write DBI address error = %s", rt_strerror(err));
- }
- }
- void dw_pcie_write_dbi2(struct dw_pcie *pci, rt_uint32_t reg, rt_size_t size, rt_uint32_t val)
- {
- rt_err_t err;
- if (pci->ops && pci->ops->write_dbi2)
- {
- pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
- return;
- }
- if ((err = dw_pcie_write(pci->dbi_base2 + reg, size, val)))
- {
- LOG_E("Write DBI2 address error = %s", rt_strerror(err));
- }
- }
- rt_uint32_t dw_pcie_readl_atu(struct dw_pcie *pci, rt_uint32_t reg)
- {
- rt_err_t err;
- rt_uint32_t val = 0;
- if (pci->ops->read_dbi)
- {
- return pci->ops->read_dbi(pci, pci->atu_base, reg, 4);
- }
- if ((err = dw_pcie_read(pci->atu_base + reg, 4, &val)))
- {
- LOG_E("Read ATU address error = %s", rt_strerror(err));
- }
- return val;
- }
- void dw_pcie_writel_atu(struct dw_pcie *pci, rt_uint32_t reg, rt_uint32_t val)
- {
- rt_err_t err;
- if (pci->ops->write_dbi)
- {
- pci->ops->write_dbi(pci, pci->atu_base, reg, 4, val);
- return;
- }
- if ((err = dw_pcie_write(pci->atu_base + reg, 4, val)))
- {
- LOG_E("Write ATU address error = %s", rt_strerror(err));
- }
- }
- static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, rt_uint8_t func_no,
- int index, int type, rt_uint64_t cpu_addr, rt_uint64_t pci_addr, rt_size_t size)
- {
- rt_uint64_t limit_addr = cpu_addr + size - 1;
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
- rt_lower_32_bits(cpu_addr));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
- rt_upper_32_bits(cpu_addr));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_LIMIT,
- rt_lower_32_bits(limit_addr));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_LIMIT,
- rt_upper_32_bits(limit_addr));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
- rt_lower_32_bits(pci_addr));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
- rt_upper_32_bits(pci_addr));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
- type | PCIE_ATU_FUNC_NUM(func_no));
- dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
- PCIE_ATU_ENABLE);
- /*
- * Make sure ATU enable takes effect before any subsequent config
- * and I/O accesses.
- */
- for (int retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; ++retries)
- {
- if (dw_pcie_readl_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2) & PCIE_ATU_ENABLE)
- {
- return;
- }
- rt_thread_mdelay(LINK_WAIT_IATU);
- }
- LOG_E("Outbound iATU is not being enabled");
- }
- static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, rt_uint8_t func_no,
- int index, int type, rt_uint64_t cpu_addr, rt_uint64_t pci_addr, rt_size_t size)
- {
- if (pci->ops->cpu_addr_fixup)
- {
- cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
- }
- if (pci->iatu_unroll_enabled & DWC_IATU_UNROLL_EN)
- {
- dw_pcie_prog_outbound_atu_unroll(pci, func_no,
- index, type, cpu_addr, pci_addr, size);
- return;
- }
- dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_OUTBOUND | index);
- dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE, rt_lower_32_bits(cpu_addr));
- dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE, rt_upper_32_bits(cpu_addr));
- dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT, rt_lower_32_bits(cpu_addr + size - 1));
- dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, rt_lower_32_bits(pci_addr));
- dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, rt_upper_32_bits(pci_addr));
- dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type | PCIE_ATU_FUNC_NUM(func_no));
- dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
- /*
- * Make sure ATU enable takes effect before any subsequent config
- * and I/O accesses.
- */
- for (int retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; ++retries)
- {
- if (dw_pcie_readl_dbi(pci, PCIE_ATU_CR2) & PCIE_ATU_ENABLE)
- {
- return;
- }
- rt_thread_mdelay(LINK_WAIT_IATU);
- }
- LOG_E("Outbound iATU is not being enabled");
- }
- void dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
- int index, int type, rt_uint64_t cpu_addr, rt_uint64_t pci_addr, rt_size_t size)
- {
- __dw_pcie_prog_outbound_atu(pci, 0, index, type, cpu_addr, pci_addr, size);
- }
- void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, rt_uint8_t func_no,
- int index, int type, rt_uint64_t cpu_addr, rt_uint64_t pci_addr, rt_size_t size)
- {
- __dw_pcie_prog_outbound_atu(pci, func_no, index, type, cpu_addr, pci_addr, size);
- }
- static rt_err_t dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci,
- rt_uint8_t func_no, int index, int bar, rt_uint64_t cpu_addr,
- enum dw_pcie_aspace_type aspace_type)
- {
- int type;
- dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
- rt_lower_32_bits(cpu_addr));
- dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
- rt_upper_32_bits(cpu_addr));
- switch (aspace_type)
- {
- case DW_PCIE_ASPACE_MEM:
- type = PCIE_ATU_TYPE_MEM;
- break;
- case DW_PCIE_ASPACE_IO:
- type = PCIE_ATU_TYPE_IO;
- break;
- default:
- return -RT_EINVAL;
- }
- dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
- type | PCIE_ATU_FUNC_NUM(func_no));
- dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
- PCIE_ATU_FUNC_NUM_MATCH_EN | PCIE_ATU_ENABLE |
- PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
- /*
- * Make sure ATU enable takes effect before any subsequent config
- * and I/O accesses.
- */
- for (int retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; ++retries)
- {
- if (dw_pcie_readl_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2) & PCIE_ATU_ENABLE)
- {
- return RT_EOK;
- }
- rt_thread_mdelay(LINK_WAIT_IATU);
- }
- LOG_E("Inbound iATU is not being enabled");
- return -RT_EBUSY;
- }
- rt_err_t dw_pcie_prog_inbound_atu(struct dw_pcie *pci,
- rt_uint8_t func_no, int index, int bar, rt_uint64_t cpu_addr,
- enum dw_pcie_aspace_type aspace_type)
- {
- int type;
- if (pci->iatu_unroll_enabled & DWC_IATU_UNROLL_EN)
- {
- return dw_pcie_prog_inbound_atu_unroll(pci, func_no,
- index, bar, cpu_addr, aspace_type);
- }
- dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND | index);
- dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, rt_lower_32_bits(cpu_addr));
- dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, rt_upper_32_bits(cpu_addr));
- switch (aspace_type)
- {
- case DW_PCIE_ASPACE_MEM:
- type = PCIE_ATU_TYPE_MEM;
- break;
- case DW_PCIE_ASPACE_IO:
- type = PCIE_ATU_TYPE_IO;
- break;
- default:
- return -RT_EINVAL;
- }
- dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type | PCIE_ATU_FUNC_NUM(func_no));
- dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE |
- PCIE_ATU_FUNC_NUM_MATCH_EN | PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
- /*
- * Make sure ATU enable takes effect before any subsequent config
- * and I/O accesses.
- */
- for (int retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; ++retries)
- {
- if (dw_pcie_readl_dbi(pci, PCIE_ATU_CR2) & PCIE_ATU_ENABLE)
- {
- return RT_EOK;
- }
- rt_thread_mdelay(LINK_WAIT_IATU);
- }
- LOG_E("Inbound iATU is not being enabled");
- return -RT_EBUSY;
- }
- void dw_pcie_disable_atu(struct dw_pcie *pci, int index, enum dw_pcie_region_type type)
- {
- rt_uint32_t region;
- switch (type)
- {
- case DW_PCIE_REGION_INBOUND:
- region = PCIE_ATU_REGION_INBOUND;
- break;
- case DW_PCIE_REGION_OUTBOUND:
- region = PCIE_ATU_REGION_OUTBOUND;
- break;
- default:
- return;
- }
- if (pci->iatu_unroll_enabled)
- {
- if (region == PCIE_ATU_REGION_INBOUND)
- {
- dw_pcie_writel_ib_unroll(pci, index,
- PCIE_ATU_UNR_REGION_CTRL2, ~(rt_uint32_t)PCIE_ATU_ENABLE);
- }
- else
- {
- dw_pcie_writel_ob_unroll(pci, index,
- PCIE_ATU_UNR_REGION_CTRL2, ~(rt_uint32_t)PCIE_ATU_ENABLE);
- }
- }
- else
- {
- dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index);
- dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~(rt_uint32_t)PCIE_ATU_ENABLE);
- }
- }
- rt_err_t dw_pcie_wait_for_link(struct dw_pcie *pci)
- {
- /* Check if the link is up or not */
- for (int retries = 0; retries < LINK_WAIT_MAX_RETRIES; ++retries)
- {
- if (dw_pcie_link_up(pci))
- {
- LOG_I("%s: Link up", rt_dm_dev_get_name(pci->dev));
- return RT_EOK;
- }
- rt_hw_us_delay((LINK_WAIT_USLEEP_MIN + LINK_WAIT_USLEEP_MAX) >> 1);
- }
- LOG_I("PHY link never came up");
- return -RT_ETIMEOUT;
- }
- rt_bool_t dw_pcie_link_up(struct dw_pcie *pci)
- {
- rt_uint32_t val;
- if (pci->ops->link_up)
- {
- return pci->ops->link_up(pci);
- }
- val = HWREG32(pci->dbi_base + PCIE_PORT_DEBUG1);
- return (val & PCIE_PORT_DEBUG1_LINK_UP) && (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING));
- }
- void dw_pcie_upconfig_setup(struct dw_pcie *pci)
- {
- rt_uint32_t val;
- val = dw_pcie_readl_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL);
- val |= PORT_MLTI_UPCFG_SUPPORT;
- dw_pcie_writel_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL, val);
- }
- static void dw_pcie_link_set_max_speed(struct dw_pcie *pci, rt_uint32_t link_gen)
- {
- rt_uint32_t cap, ctrl2, link_speed;
- rt_uint8_t offset = dw_pcie_find_capability(pci, PCIY_EXPRESS);
- cap = dw_pcie_readl_dbi(pci, offset + PCIER_LINK_CAP);
- ctrl2 = dw_pcie_readl_dbi(pci, offset + PCIER_LINK_CTL2);
- ctrl2 &= ~PCIEM_LNKCTL2_TLS;
- switch (link_gen)
- {
- case 1: link_speed = PCIEM_LNKCTL2_TLS_2_5GT; break;
- case 2: link_speed = PCIEM_LNKCTL2_TLS_5_0GT; break;
- case 3: link_speed = PCIEM_LNKCTL2_TLS_8_0GT; break;
- case 4: link_speed = PCIEM_LNKCTL2_TLS_16_0GT; break;
- default:
- /* Use hardware capability */
- link_speed = RT_FIELD_GET(PCIEM_LINK_CAP_MAX_SPEED, cap);
- ctrl2 &= ~PCIEM_LNKCTL2_HASD;
- break;
- }
- dw_pcie_writel_dbi(pci, offset + PCIER_LINK_CTL2, ctrl2 | link_speed);
- cap &= ~((rt_uint32_t)PCIEM_LINK_CAP_MAX_SPEED);
- dw_pcie_writel_dbi(pci, offset + PCIER_LINK_CAP, cap | link_speed);
- }
- void dw_pcie_setup(struct dw_pcie *pci)
- {
- rt_uint32_t val;
- struct rt_device *dev = pci->dev;
- if (pci->version >= 0x480a || (!pci->version && dw_pcie_iatu_unroll_enabled(pci)))
- {
- pci->iatu_unroll_enabled |= DWC_IATU_UNROLL_EN;
- if (!pci->atu_base)
- {
- pci->atu_base = rt_dm_dev_iomap_by_name(dev, "atu");
- }
- if (!pci->atu_base)
- {
- pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
- }
- }
- LOG_D("iATU unroll is %sabled", pci->iatu_unroll_enabled & DWC_IATU_UNROLL_EN ? "en" : "dis");
- if (pci->link_gen > 0)
- {
- dw_pcie_link_set_max_speed(pci, pci->link_gen);
- }
- /* Configure Gen1 N_FTS */
- if (pci->fts_number[0])
- {
- val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
- val &= ~(PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK);
- val |= PORT_AFR_N_FTS(pci->fts_number[0]);
- val |= PORT_AFR_CC_N_FTS(pci->fts_number[0]);
- dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val);
- }
- /* Configure Gen2+ N_FTS */
- if (pci->fts_number[1])
- {
- val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
- val &= ~PORT_LOGIC_N_FTS_MASK;
- val |= pci->fts_number[1];
- dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
- }
- val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
- val &= ~PORT_LINK_FAST_LINK_MODE;
- val |= PORT_LINK_DLL_LINK_EN;
- dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
- if (rt_dm_dev_prop_read_bool(dev, "snps,enable-cdm-check"))
- {
- val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
- val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS | PCIE_PL_CHK_REG_CHK_REG_START;
- dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
- }
- rt_dm_dev_prop_read_u32(dev, "num-lanes", &pci->num_lanes);
- if (!pci->num_lanes)
- {
- LOG_D("Using h/w default number of lanes");
- return;
- }
- /* Set the number of lanes */
- val &= ~PORT_LINK_FAST_LINK_MODE;
- val &= ~PORT_LINK_MODE_MASK;
- switch (pci->num_lanes)
- {
- case 1: val |= PORT_LINK_MODE_1_LANES; break;
- case 2: val |= PORT_LINK_MODE_2_LANES; break;
- case 4: val |= PORT_LINK_MODE_4_LANES; break;
- case 8: val |= PORT_LINK_MODE_8_LANES; break;
- default:
- LOG_E("Invail num-lanes = %d", pci->num_lanes);
- return;
- }
- dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
- /* Set link width speed control register */
- val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
- val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
- switch (pci->num_lanes)
- {
- case 1: val |= PORT_LOGIC_LINK_WIDTH_1_LANES; break;
- case 2: val |= PORT_LOGIC_LINK_WIDTH_2_LANES; break;
- case 4: val |= PORT_LOGIC_LINK_WIDTH_4_LANES; break;
- case 8: val |= PORT_LOGIC_LINK_WIDTH_8_LANES; break;
- }
- val |= pci->user_speed;
- dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
- }
|