drivers/pci/controller/dwc/pcie-rcar-gen4.c
Source file repositories/reference/linux-study-clean/drivers/pci/controller/dwc/pcie-rcar-gen4.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pci/controller/dwc/pcie-rcar-gen4.c- Extension
.c- Size
- 20512 bytes
- Lines
- 798
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: implementation source
- Status
- source implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/delay.hlinux/firmware.hlinux/interrupt.hlinux/io.hlinux/iopoll.hlinux/module.hlinux/of.hlinux/pci.hlinux/platform_device.hlinux/pm_runtime.hlinux/reset.h../../pci.hpcie-designware.h
Detected Declarations
struct rcar_gen4_pciestruct rcar_gen4_pcie_drvdatastruct rcar_gen4_pciefunction rcar_gen4_pcie_link_upfunction rcar_gen4_pcie_speed_changefunction rcar_gen4_pcie_start_linkfunction rcar_gen4_pcie_stop_linkfunction rcar_gen4_pcie_common_initfunction rcar_gen4_pcie_common_deinitfunction rcar_gen4_pcie_preparefunction rcar_gen4_pcie_unpreparefunction rcar_gen4_pcie_get_resourcesfunction rcar_gen4_pcie_host_initfunction rcar_gen4_pcie_host_deinitfunction rcar_gen4_add_dw_pcie_rpfunction rcar_gen4_remove_dw_pcie_rpfunction rcar_gen4_pcie_ep_pre_initfunction rcar_gen4_pcie_ep_deinitfunction rcar_gen4_pcie_ep_raise_irqfunction rcar_gen4_pcie_ep_get_featuresfunction rcar_gen4_pcie_ep_get_dbi_offsetfunction rcar_gen4_pcie_ep_get_dbi2_offsetfunction rcar_gen4_add_dw_pcie_epfunction rcar_gen4_remove_dw_pcie_epfunction rcar_gen4_add_dw_pciefunction rcar_gen4_pcie_probefunction rcar_gen4_remove_dw_pciefunction rcar_gen4_pcie_removefunction r8a779f0_pcie_ltssm_controlfunction rcar_gen4_pcie_additional_common_initfunction rcar_gen4_pcie_phy_reg_update_bitsfunction rcar_gen4_pcie_reg_test_bitfunction rcar_gen4_pcie_download_phy_firmwarefunction rcar_gen4_pcie_ltssm_control
Annotated Snippet
struct rcar_gen4_pcie_drvdata {
void (*additional_common_init)(struct rcar_gen4_pcie *rcar);
int (*ltssm_control)(struct rcar_gen4_pcie *rcar, bool enable);
enum dw_pcie_device_mode mode;
};
struct rcar_gen4_pcie {
struct dw_pcie dw;
void __iomem *base;
void __iomem *phy_base;
struct platform_device *pdev;
const struct rcar_gen4_pcie_drvdata *drvdata;
};
#define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw)
/* Common */
static bool rcar_gen4_pcie_link_up(struct dw_pcie *dw)
{
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
u32 val, mask;
val = readl(rcar->base + PCIEINTSTS0);
mask = RDLH_LINK_UP | SMLH_LINK_UP;
return (val & mask) == mask;
}
/*
* Manually initiate the speed change. Return 0 if change succeeded; otherwise
* -ETIMEDOUT.
*/
static int rcar_gen4_pcie_speed_change(struct dw_pcie *dw)
{
u32 val;
int i;
val = dw_pcie_readl_dbi(dw, PCIE_LINK_WIDTH_SPEED_CONTROL);
val &= ~PORT_LOGIC_SPEED_CHANGE;
dw_pcie_writel_dbi(dw, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
val = dw_pcie_readl_dbi(dw, PCIE_LINK_WIDTH_SPEED_CONTROL);
val |= PORT_LOGIC_SPEED_CHANGE;
dw_pcie_writel_dbi(dw, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
for (i = 0; i < RCAR_NUM_SPEED_CHANGE_RETRIES; i++) {
val = dw_pcie_readl_dbi(dw, PCIE_LINK_WIDTH_SPEED_CONTROL);
if (!(val & PORT_LOGIC_SPEED_CHANGE))
return 0;
usleep_range(10000, 11000);
}
return -ETIMEDOUT;
}
/*
* Enable LTSSM of this controller and manually initiate the speed change.
* Always return 0.
*/
static int rcar_gen4_pcie_start_link(struct dw_pcie *dw)
{
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
int i, changes, ret;
if (rcar->drvdata->ltssm_control) {
ret = rcar->drvdata->ltssm_control(rcar, true);
if (ret)
return ret;
}
/*
* Require direct speed change with retrying here if the max_link_speed
* is PCIe Gen2 or higher.
*/
changes = min_not_zero(dw->max_link_speed, RCAR_MAX_LINK_SPEED) - 1;
/*
* Since dw_pcie_setup_rc() sets it once, PCIe Gen2 will be trained.
* So, this needs remaining times for up to PCIe Gen4 if RC mode.
*/
if (changes && rcar->drvdata->mode == DW_PCIE_RC_TYPE)
changes--;
for (i = 0; i < changes; i++) {
/* It may not be connected in EP mode yet. So, break the loop */
if (rcar_gen4_pcie_speed_change(dw))
break;
}
return 0;
}
Annotation
- Immediate include surface: `linux/delay.h`, `linux/firmware.h`, `linux/interrupt.h`, `linux/io.h`, `linux/iopoll.h`, `linux/module.h`, `linux/of.h`, `linux/pci.h`.
- Detected declarations: `struct rcar_gen4_pcie`, `struct rcar_gen4_pcie_drvdata`, `struct rcar_gen4_pcie`, `function rcar_gen4_pcie_link_up`, `function rcar_gen4_pcie_speed_change`, `function rcar_gen4_pcie_start_link`, `function rcar_gen4_pcie_stop_link`, `function rcar_gen4_pcie_common_init`, `function rcar_gen4_pcie_common_deinit`, `function rcar_gen4_pcie_prepare`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.