drivers/pci/controller/plda/pcie-starfive.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/plda/pcie-starfive.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/plda/pcie-starfive.c
Extension
.c
Size
13520 bytes
Lines
498
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct starfive_jh7110_pcie {
	struct plda_pcie_rp plda;
	struct reset_control *resets;
	struct clk_bulk_data *clks;
	struct regmap *reg_syscon;
	struct regulator *vpcie3v3;
	struct gpio_desc *reset_gpio;
	struct phy *phy;

	unsigned int stg_pcie_base;
	int num_clks;
};

/*
 * JH7110 PCIe port BAR0/1 can be configured as 64-bit prefetchable memory
 * space. PCIe read and write requests targeting BAR0/1 are routed to so called
 * 'Bridge Configuration space' in PLDA IP datasheet, which contains the bridge
 * internal registers, such as interrupt, DMA and ATU registers...
 * JH7110 can access the Bridge Configuration space by local bus, and don`t
 * want the bridge internal registers accessed by the DMA from EP devices.
 * Thus, they are unimplemented and should be hidden here.
 */
static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,
				      int offset)
{
	if (pci_is_root_bus(bus) && !devfn &&
	    (offset == PCI_BASE_ADDRESS_0 || offset == PCI_BASE_ADDRESS_1))
		return true;

	return false;
}

static int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
				      int where, int size, u32 value)
{
	if (starfive_pcie_hide_rc_bar(bus, devfn, where))
		return PCIBIOS_SUCCESSFUL;

	return pci_generic_config_write(bus, devfn, where, size, value);
}

static int starfive_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
				     int where, int size, u32 *value)
{
	if (starfive_pcie_hide_rc_bar(bus, devfn, where)) {
		*value = 0;
		return PCIBIOS_SUCCESSFUL;
	}

	return pci_generic_config_read(bus, devfn, where, size, value);
}

static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie,
				  struct device *dev)
{
	int domain_nr;

	pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
	if (pcie->num_clks < 0)
		return dev_err_probe(dev, pcie->num_clks,
				     "failed to get pcie clocks\n");

	pcie->resets = devm_reset_control_array_get_exclusive(dev);
	if (IS_ERR(pcie->resets))
		return dev_err_probe(dev, PTR_ERR(pcie->resets),
				     "failed to get pcie resets");

	pcie->reg_syscon =
		syscon_regmap_lookup_by_phandle(dev->of_node,
						"starfive,stg-syscon");

	if (IS_ERR(pcie->reg_syscon))
		return dev_err_probe(dev, PTR_ERR(pcie->reg_syscon),
				     "failed to parse starfive,stg-syscon\n");

	pcie->phy = devm_phy_optional_get(dev, NULL);
	if (IS_ERR(pcie->phy))
		return dev_err_probe(dev, PTR_ERR(pcie->phy),
				     "failed to get pcie phy\n");

	/*
	 * The PCIe domain numbers are set to be static in JH7110 DTS.
	 * As the STG system controller defines different bases in PCIe RP0 &
	 * RP1, we use them to identify which controller is doing the hardware
	 * initialization.
	 */
	domain_nr = of_get_pci_domain_nr(dev->of_node);

	if (domain_nr < 0 || domain_nr > 1)
		return dev_err_probe(dev, -ENODEV,

Annotation

Implementation Notes