Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab8a1ce3 authored by Tony Truong's avatar Tony Truong
Browse files

msm: pcie: add PCIe bandwidth scale table support



Based on PCIe link Gen speed, CX voltage corner and rate change
clock frequency can be scaled accordingly. Add support to
retrieve bandwidth scale table from devicetree to support
robust scaling.

Change-Id: I2b22a397edfdde8d27c1a608df61ff10748b920d
Signed-off-by: default avatarTony Truong <truong@codeaurora.org>
parent b9adbfd9
Loading
Loading
Loading
Loading
+51 −2
Original line number Diff line number Diff line
@@ -551,6 +551,12 @@ struct msm_pcie_irq_info_t {
	uint32_t num;
};

/* bandwidth info structure */
struct msm_pcie_bw_scale_info_t {
	u32 cx_vreg_min;
	u32 rate_change_freq;
};

/* phy info structure */
struct msm_pcie_phy_info_t {
	u32 offset;
@@ -662,6 +668,8 @@ struct msm_pcie_dev_t {

	struct msm_pcie_vreg_info_t *cx_vreg;
	struct msm_pcie_clk_info_t *rate_change_clk;
	struct msm_pcie_bw_scale_info_t *bw_scale;
	u32 bw_gen_max;

	bool cfg_access;
	spinlock_t cfg_lock;
@@ -3741,6 +3749,29 @@ static int msm_pcie_get_reset(struct msm_pcie_dev_t *pcie_dev)
	return 0;
}

static int msm_pcie_get_bw_scale(struct msm_pcie_dev_t *pcie_dev)
{
	int size = 0;
	struct platform_device *pdev = pcie_dev->pdev;

	of_get_property(pdev->dev.of_node, "qcom,bw-scale", &size);
	if (size) {
		pcie_dev->bw_scale = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
		if (!pcie_dev->bw_scale)
			return -ENOMEM;

		of_property_read_u32_array(pdev->dev.of_node, "qcom,bw-scale",
				(u32 *)pcie_dev->bw_scale, size / sizeof(u32));

		pcie_dev->bw_gen_max = size / sizeof(u32);
	} else {
		PCIE_DBG(pcie_dev, "RC%d: bandwidth scaling is not supported\n",
			pcie_dev->rc_idx);
	}

	return 0;
}

static int msm_pcie_get_phy(struct msm_pcie_dev_t *pcie_dev)
{
	int ret, size = 0;
@@ -3953,6 +3984,10 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev,
	if (ret)
		return ret;

	ret = msm_pcie_get_bw_scale(dev);
	if (ret)
		return ret;

	ret = msm_pcie_get_phy(dev);
	if (ret)
		return ret;
@@ -6233,6 +6268,8 @@ int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
	u16 current_link_speed;
	u16 current_link_width;
	int ret;
	u32 index = target_link_speed - PCI_EXP_LNKCTL2_TLS_2_5GT;
	struct msm_pcie_bw_scale_info_t *bw_scale;

	if (!pci_dev)
		return -EINVAL;
@@ -6240,6 +6277,18 @@ int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
	root_pci_dev = pci_find_pcie_root_port(pci_dev);
	pcie_dev = PCIE_BUS_PRIV_DATA(root_pci_dev->bus);

	if (!pcie_dev->bw_scale)
		return -EINVAL;

	if (index >= pcie_dev->bw_gen_max) {
		PCIE_ERR(pcie_dev,
			"PCIe: RC%d: invalid target link speed: %d\n",
			pcie_dev->rc_idx, target_link_speed);
		return -EINVAL;
	}

	bw_scale = &pcie_dev->bw_scale[index];

	pcie_capability_read_word(root_pci_dev, PCI_EXP_LNKSTA, &link_status);

	current_link_speed = link_status & PCI_EXP_LNKSTA_CLS;
@@ -6269,7 +6318,7 @@ int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
	if (target_link_speed == PCI_EXP_LNKCTL2_TLS_8_0GT) {
		if (pcie_dev->cx_vreg)
			regulator_set_voltage(pcie_dev->cx_vreg->hdl,
						RPMH_REGULATOR_LEVEL_NOM,
						bw_scale->cx_vreg_min,
						pcie_dev->cx_vreg->max_v);

		if (pcie_dev->rate_change_clk) {
@@ -6292,7 +6341,7 @@ int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
	if ((link_status & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKCTL2_TLS_2_5GT) {
		if (pcie_dev->cx_vreg)
			regulator_set_voltage(pcie_dev->cx_vreg->hdl,
						RPMH_REGULATOR_LEVEL_LOW_SVS,
						bw_scale->cx_vreg_min,
						pcie_dev->cx_vreg->max_v);

		if (pcie_dev->rate_change_clk) {