drivers/pci/controller/dwc/pcie-stm32.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/dwc/pcie-stm32.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/dwc/pcie-stm32.c
Extension
.c
Size
8802 bytes
Lines
371
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 stm32_pcie {
	struct dw_pcie pci;
	struct regmap *regmap;
	struct reset_control *rst;
	struct phy *phy;
	struct clk *clk;
	struct gpio_desc *perst_gpio;
	struct gpio_desc *wake_gpio;
};

static void stm32_pcie_deassert_perst(struct stm32_pcie *stm32_pcie)
{
	if (stm32_pcie->perst_gpio) {
		msleep(PCIE_T_PVPERL_MS);
		gpiod_set_value(stm32_pcie->perst_gpio, 0);
	}

	msleep(PCIE_RESET_CONFIG_WAIT_MS);
}

static void stm32_pcie_assert_perst(struct stm32_pcie *stm32_pcie)
{
	gpiod_set_value(stm32_pcie->perst_gpio, 1);
}

static int stm32_pcie_start_link(struct dw_pcie *pci)
{
	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);

	return regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
				  STM32MP25_PCIECR_LTSSM_EN,
				  STM32MP25_PCIECR_LTSSM_EN);
}

static void stm32_pcie_stop_link(struct dw_pcie *pci)
{
	struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci);

	regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR,
			   STM32MP25_PCIECR_LTSSM_EN, 0);
}

static int stm32_pcie_suspend_noirq(struct device *dev)
{
	struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev);
	int ret;

	ret = dw_pcie_suspend_noirq(&stm32_pcie->pci);
	if (ret)
		return ret;

	stm32_pcie_assert_perst(stm32_pcie);

	clk_disable_unprepare(stm32_pcie->clk);

	if (!device_wakeup_path(dev))
		phy_exit(stm32_pcie->phy);

	return pinctrl_pm_select_sleep_state(dev);
}

static int stm32_pcie_resume_noirq(struct device *dev)
{
	struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev);
	int ret;

	/*
	 * The core clock is gated with CLKREQ# from the COMBOPHY REFCLK,
	 * thus if no device is present, must deassert it with a GPIO from
	 * pinctrl pinmux before accessing the DBI registers.
	 */
	ret = pinctrl_pm_select_init_state(dev);
	if (ret) {
		dev_err(dev, "Failed to activate pinctrl pm state: %d\n", ret);
		return ret;
	}

	if (!device_wakeup_path(dev)) {
		ret = phy_init(stm32_pcie->phy);
		if (ret) {
			pinctrl_pm_select_default_state(dev);
			return ret;
		}
	}

	ret = clk_prepare_enable(stm32_pcie->clk);
	if (ret)
		goto err_phy_exit;

	stm32_pcie_deassert_perst(stm32_pcie);

Annotation

Implementation Notes