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

Commit e2867cff authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: pcie: Add support for two RCs"

parents 4c29d317 3190ca6f
Loading
Loading
Loading
Loading
+214 −245
Original line number Diff line number Diff line
@@ -216,9 +216,9 @@ static void msm_pcie_write_mask(void __iomem *addr,
	wmb();  /* ensure data is written to hardware register */
}

static int msm_pcie_is_link_up(u32 rc_idx)
static int msm_pcie_is_link_up(struct msm_pcie_dev_t *dev)
{
	return readl_relaxed(msm_pcie_dev[rc_idx].dm_core +
	return readl_relaxed(dev->dm_core +
			PCIE20_CAP_LINKCTRLSTATUS) & BIT(29);
}

@@ -233,6 +233,16 @@ static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
	u32 rc_idx;
	int rv = 0;

	dev = ((struct msm_pcie_dev_t *)
		(((struct pci_sys_data *)bus->sysdata)->private_data));

	if (!dev) {
		pr_err("PCIe: No device found for this bus.\n");
		*val = ~0;
		rv = PCIBIOS_DEVICE_NOT_FOUND;
		goto out;
	}

	/* Do the bus->number based access control since we don't support
	   ECAM mechanism */

@@ -240,18 +250,7 @@ static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
	case 0:
		rc = true;
	case 1:
		if (pcie_drv.rc_expected > 1)
			rc_idx = 0;
		else
			rc_idx = pcie_drv.current_rc;
		break;
	case 2:
		rc = true;
	case 3:
		if (pcie_drv.rc_expected > 1)
			rc_idx = 1;
		else
			rc_idx = pcie_drv.current_rc;
		rc_idx = dev->rc_idx;
		break;
	default:
		pr_err("PCIe: unsupported bus number.\n");
@@ -260,32 +259,29 @@ static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
		goto out;
	}

	dev = &msm_pcie_dev[rc_idx];

	if ((bus->number > MAX_BUS_NUM) || (devfn != 0)) {
		PCIE_DBG("invalid %s - bus %d devfn %d\n",
		PCIE_DBG("RC%d invalid %s - bus %d devfn %d\n", rc_idx,
			 (oper == RD) ? "rd" : "wr", bus->number, devfn);
		*val = ~0;
		rv = PCIBIOS_DEVICE_NOT_FOUND;
		goto out;
	}

	spin_lock_irqsave(&msm_pcie_dev[rc_idx].cfg_lock,
				msm_pcie_dev[rc_idx].irqsave_flags);
	spin_lock_irqsave(&dev->cfg_lock, dev->irqsave_flags);

	if (!msm_pcie_dev[rc_idx].cfg_access) {
		PCIE_DBG("access denied for %d:0x%02x + 0x%04x[%d]\n",
			 bus->number, devfn, where, size);
	if (!dev->cfg_access) {
		PCIE_DBG("Access denied for RC%d %d:0x%02x + 0x%04x[%d]\n",
			rc_idx, bus->number, devfn, where, size);
		*val = ~0;
		rv = PCIBIOS_DEVICE_NOT_FOUND;
		goto unlock;
	}

	/* check if the link is up for endpoint */
	if (((bus->number == 1) || (bus->number == 3))
		&& (!msm_pcie_is_link_up(rc_idx))) {
			pr_err("%s fail, link down - bus %d devfn %d\n",
				(oper == RD) ? "rd" : "wr", bus->number, devfn);
	if (!rc && !msm_pcie_is_link_up(dev)) {
			pr_err("RC%d %s fail, link down - bus %d devfn %d\n",
				rc_idx, (oper == RD) ? "rd" : "wr",
				bus->number, devfn);
			*val = ~0;
			rv = PCIBIOS_DEVICE_NOT_FOUND;
			goto unlock;
@@ -300,8 +296,8 @@ static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,

	if (oper == RD) {
		*val = ((rd_val & mask) >> (8 * byte_offset));
		PCIE_DBG("%d:0x%02x + 0x%04x[%d] -> 0x%08x; rd 0x%08x\n",
			bus->number, devfn, where, size, *val, rd_val);
		PCIE_DBG("RC%d %d:0x%02x + 0x%04x[%d] -> 0x%08x; rd 0x%08x\n",
			rc_idx, bus->number, devfn, where, size, *val, rd_val);
	} else {
		wr_val = (rd_val & ~mask) |
				((*val << (8 * byte_offset)) & mask);
@@ -309,13 +305,13 @@ static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
		wmb(); /* ensure config data is written to hardware register */

		PCIE_DBG(
			"%d:0x%02x + 0x%04x[%d] <- 0x%08x; rd 0x%08x val 0x%08x\n",
			bus->number, devfn, where, size, wr_val, rd_val, *val);
			"RC%d %d:0x%02x + 0x%04x[%d] <- 0x%08x; rd 0x%08x val 0x%08x\n",
			rc_idx, bus->number, devfn, where, size,
			wr_val, rd_val, *val);
	}

unlock:
	spin_unlock_irqrestore(&msm_pcie_dev[rc_idx].cfg_lock,
				msm_pcie_dev[rc_idx].irqsave_flags);
	spin_unlock_irqrestore(&dev->cfg_lock, dev->irqsave_flags);
out:
	return rv;
}
@@ -344,15 +340,15 @@ static struct pci_ops msm_pcie_ops = {
	.write = msm_pcie_wr_conf,
};

static int msm_pcie_gpio_init(u32 rc_idx)
static int msm_pcie_gpio_init(struct msm_pcie_dev_t *dev)
{
	int rc, i;
	struct msm_pcie_gpio_info_t *info;

	PCIE_DBG("\n");

	for (i = 0; i < msm_pcie_dev[rc_idx].gpio_n; i++) {
		info = &msm_pcie_dev[rc_idx].gpio[i];
	for (i = 0; i < dev->gpio_n; i++) {
		info = &dev->gpio[i];

		if (!info->num)
			continue;
@@ -377,20 +373,20 @@ static int msm_pcie_gpio_init(u32 rc_idx)

	if (rc)
		while (i--)
			gpio_free(msm_pcie_dev[rc_idx].gpio[i].num);
			gpio_free(dev->gpio[i].num);

	return rc;
}

static void msm_pcie_gpio_deinit(u32 rc_idx)
static void msm_pcie_gpio_deinit(struct msm_pcie_dev_t *dev)
{
	int i;

	for (i = 0; i < msm_pcie_dev[rc_idx].gpio_n; i++)
		gpio_free(msm_pcie_dev[rc_idx].gpio[i].num);
	for (i = 0; i < dev->gpio_n; i++)
		gpio_free(dev->gpio[i].num);
}

static int msm_pcie_vreg_init(u32 rc_idx, struct device *dev)
int msm_pcie_vreg_init(struct msm_pcie_dev_t *dev)
{
	int i, rc = 0;
	struct regulator *vreg;
@@ -398,15 +394,8 @@ static int msm_pcie_vreg_init(u32 rc_idx, struct device *dev)

	PCIE_DBG("\n");

	if (pcie_drv.vreg_on) {
		PCIE_DBG("Vreg has been turned on.\n");
		return rc;
	} else {
		pcie_drv.vreg_on = true;
	}

	for (i = 0; i < MSM_PCIE_MAX_VREG; i++) {
		info = &msm_pcie_dev[rc_idx].vreg[i];
		info = &dev->vreg[i];
		vreg = info->hdl;

		if (!vreg)
@@ -441,61 +430,42 @@ static int msm_pcie_vreg_init(u32 rc_idx, struct device *dev)

	if (rc)
		while (i--) {
			struct regulator *hdl =
				msm_pcie_dev[rc_idx].vreg[i].hdl;
			struct regulator *hdl = dev->vreg[i].hdl;
			if (hdl)
				regulator_disable(hdl);
		}

	if (rc)
		pcie_drv.vreg_on = false;

	return rc;
}

static void msm_pcie_vreg_deinit(u32 rc_idx)
static void msm_pcie_vreg_deinit(struct msm_pcie_dev_t *dev)
{
	int i;

	if (pcie_drv.vreg_on)
		pcie_drv.vreg_on = false;
	else {
		PCIE_DBG("Vreg has been turned off\n");
		return;
	}

	for (i = MSM_PCIE_MAX_VREG - 1; i >= 0; i--) {
		if (msm_pcie_dev[rc_idx].vreg[i].hdl) {
		if (dev->vreg[i].hdl) {
			PCIE_DBG("Vreg %s is being disabled\n",
				msm_pcie_dev[rc_idx].vreg[i].name);
			regulator_disable(msm_pcie_dev[rc_idx].vreg[i].hdl);
				dev->vreg[i].name);
			regulator_disable(dev->vreg[i].hdl);
		}
	}
}

static int msm_pcie_clk_init(u32 rc_idx, struct device *dev)
static int msm_pcie_clk_init(struct msm_pcie_dev_t *dev)
{
	int i, rc = 0;
	struct msm_pcie_clk_info_t *info;

	PCIE_DBG("\n");

	if (dev) {
		PCIE_DBG("dev name:%s\n", dev_name(dev));
	} else {
		pr_err("PCIe: dev is NULL\n");
		return -ENODEV;
	}

	rc = regulator_enable(msm_pcie_dev[rc_idx].gdsc);
	rc = regulator_enable(dev->gdsc);

	if (rc) {
		pr_err("PCIe: fail to enable GDSC for RC %d\n", rc_idx);
		pr_err("PCIe: fail to enable GDSC for RC %s\n",
			dev->pdev->name);
		return rc;
	}

	for (i = 0; i < MSM_PCIE_MAX_CLK; i++) {
		info = &msm_pcie_dev[rc_idx].clk[i];
		info = &dev->clk[i];

		if (!info->hdl)
			continue;
@@ -520,44 +490,35 @@ static int msm_pcie_clk_init(u32 rc_idx, struct device *dev)
	if (rc) {
		PCIE_DBG("disable clocks for error handling\n");
		while (i--) {
			struct clk *hdl = msm_pcie_dev[rc_idx].clk[i].hdl;
			struct clk *hdl = dev->clk[i].hdl;
			if (hdl)
				clk_disable_unprepare(hdl);
		}

		regulator_disable(msm_pcie_dev[rc_idx].gdsc);
		regulator_disable(dev->gdsc);
	}

	return rc;
}

static void msm_pcie_clk_deinit(u32 rc_idx)
static void msm_pcie_clk_deinit(struct msm_pcie_dev_t *dev)
{
	int i;

	for (i = 0; i < MSM_PCIE_MAX_CLK; i++)
		if (msm_pcie_dev[rc_idx].clk[i].hdl)
			clk_disable_unprepare(msm_pcie_dev[rc_idx].clk[i].hdl);
		if (dev->clk[i].hdl)
			clk_disable_unprepare(dev->clk[i].hdl);

	regulator_disable(msm_pcie_dev[rc_idx].gdsc);
	regulator_disable(dev->gdsc);
}

static int msm_pcie_pipe_clk_init(u32 rc_idx, struct device *dev)
static int msm_pcie_pipe_clk_init(struct msm_pcie_dev_t *dev)
{
	int i, rc = 0;
	struct msm_pcie_clk_info_t *info;

	PCIE_DBG("\n");

	if (dev) {
		PCIE_DBG("dev name:%s\n", dev_name(dev));
	} else {
		pr_err("PCIe: dev is NULL\n");
		return -ENODEV;
	}

	for (i = 0; i < MSM_PCIE_MAX_PIPE_CLK; i++) {
		info = &msm_pcie_dev[rc_idx].pipeclk[i];
		info = &dev->pipeclk[i];

		if (!info->hdl)
			continue;
@@ -584,28 +545,26 @@ static int msm_pcie_pipe_clk_init(u32 rc_idx, struct device *dev)
	if (rc) {
		PCIE_DBG("disable pipe clocks for error handling\n");
		while (i--)
			if (msm_pcie_dev[rc_idx].pipeclk[i].hdl)
				clk_disable_unprepare(
					msm_pcie_dev[rc_idx].pipeclk[i].hdl);
			if (dev->pipeclk[i].hdl)
				clk_disable_unprepare(dev->pipeclk[i].hdl);
	}

	return rc;
}

static void msm_pcie_pipe_clk_deinit(u32 rc_idx)
static void msm_pcie_pipe_clk_deinit(struct msm_pcie_dev_t *dev)
{
	int i;

	for (i = 0; i < MSM_PCIE_MAX_PIPE_CLK; i++)
		if (msm_pcie_dev[rc_idx].pipeclk[i].hdl)
		if (dev->pipeclk[i].hdl)
			clk_disable_unprepare(
				msm_pcie_dev[rc_idx].pipeclk[i].hdl);
				dev->pipeclk[i].hdl);
}


static void msm_pcie_config_controller(u32 rc_idx)
static void msm_pcie_config_controller(struct msm_pcie_dev_t *dev)
{
	struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx];
	struct resource *axi_conf = dev->res[MSM_PCIE_RES_CONF].resource;
	u32 dev_conf, upper, lower, limit;

@@ -621,13 +580,7 @@ static void msm_pcie_config_controller(u32 rc_idx)
		limit = axi_conf->end;
	}

	if (rc_idx == 0) {
		/* Should equate to 0x01000000 */
	dev_conf = BDF_OFFSET(1, 0, 0);
	} else {
		/* Should equate to 0x03000000 */
		dev_conf = BDF_OFFSET(3, 0, 0);
	}

	/*
	 * program and enable address translation region 0 (device config
@@ -665,10 +618,8 @@ static void msm_pcie_config_controller(u32 rc_idx)
		readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_CTRL2));
}

static void msm_pcie_config_l1ss(u32 rc_idx)
static void msm_pcie_config_l1ss(struct msm_pcie_dev_t *dev)
{
	struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx];

	PCIE_DBG("Original PCIE20_ACK_F_ASPM_CTRL_REG:0x%x\n",
		readl_relaxed(dev->dm_core + PCIE20_ACK_F_ASPM_CTRL_REG));
	msm_pcie_write_mask(dev->dm_core + PCIE20_ACK_F_ASPM_CTRL_REG, 0,
@@ -704,7 +655,8 @@ static void msm_pcie_config_l1ss(u32 rc_idx)
					PCIE20_EP_L1SUB_CTL1_OFFSET));
}

static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev,
					struct platform_device *pdev)
{
	int i, len, cnt, ret = 0;
	struct msm_pcie_vreg_info_t *vreg_info;
@@ -713,7 +665,6 @@ static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
	struct resource *res;
	struct msm_pcie_res_info_t *res_info;
	struct msm_pcie_irq_info_t *irq_info;
	struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx];
	char prop_name[MAX_PROP_SIZE];
	const __be32 *prop;
	u32 *clkfreq = NULL;
@@ -747,8 +698,8 @@ static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
				devm_regulator_get(&pdev->dev, vreg_info->name);

		if (PTR_ERR(vreg_info->hdl) == -EPROBE_DEFER) {
			PCIE_DBG("EPROBE_DEFER for PCIe_%d:%s\n",
				rc_idx, vreg_info->name);
			PCIE_DBG("EPROBE_DEFER for VReg:%s\n",
				vreg_info->name);
			return PTR_ERR(vreg_info->hdl);
		}

@@ -784,11 +735,11 @@ static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
	dev->gdsc = devm_regulator_get(&pdev->dev, "gdsc-vdd");

	if (IS_ERR(dev->gdsc)) {
		pr_err("PCIe: Failed to get PCIe_%d GDSC:%ld\n",
			rc_idx, PTR_ERR(dev->gdsc));
		pr_err("PCIe: Failed to get %s GDSC:%ld\n",
			dev->pdev->name, PTR_ERR(dev->gdsc));
		if (PTR_ERR(dev->gdsc) == -EPROBE_DEFER)
			PCIE_DBG("PCIe: EPROBE_DEFER for PCIe_%d GDSC\n",
					rc_idx);
			PCIE_DBG("PCIe: EPROBE_DEFER for %s GDSC\n",
					dev->pdev->name);
		return PTR_ERR(dev->gdsc);
	}

@@ -809,7 +760,7 @@ static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
	}

	for (i = 0; i < MSM_PCIE_MAX_CLK; i++) {
		clk_info = &msm_pcie_dev[rc_idx].clk[i];
		clk_info = &dev->clk[i];

		clk_info->hdl = devm_clk_get(&pdev->dev, clk_info->name);

@@ -833,7 +784,7 @@ static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
	}

	for (i = 0; i < MSM_PCIE_MAX_PIPE_CLK; i++) {
		clk_info = &msm_pcie_dev[rc_idx].pipeclk[i];
		clk_info = &dev->pipeclk[i];

		clk_info->hdl = devm_clk_get(&pdev->dev, clk_info->name);

@@ -917,21 +868,20 @@ static int msm_pcie_get_resources(u32 rc_idx, struct platform_device *pdev)
	return ret;
}

static void msm_pcie_release_resources(u32 rc_idx)
static void msm_pcie_release_resources(struct msm_pcie_dev_t *dev)
{
	msm_pcie_dev[rc_idx].parf = NULL;
	msm_pcie_dev[rc_idx].elbi = NULL;
	msm_pcie_dev[rc_idx].dm_core = NULL;
	msm_pcie_dev[rc_idx].conf = NULL;
	msm_pcie_dev[rc_idx].bars = NULL;
	msm_pcie_dev[rc_idx].dev_mem_res = NULL;
	msm_pcie_dev[rc_idx].dev_io_res = NULL;
	dev->parf = NULL;
	dev->elbi = NULL;
	dev->dm_core = NULL;
	dev->conf = NULL;
	dev->bars = NULL;
	dev->dev_mem_res = NULL;
	dev->dev_io_res = NULL;
}

static int msm_pcie_enable(u32 rc_idx, u32 options)
static int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options)
{
	int ret;
	struct msm_pcie_dev_t *dev;
	uint32_t val;
	long int retries = 0;

@@ -939,8 +889,6 @@ static int msm_pcie_enable(u32 rc_idx, u32 options)

	mutex_lock(&setup_lock);

	dev = &msm_pcie_dev[rc_idx];

	/* assert PCIe reset link to keep EP in reset */

	gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num,
@@ -951,14 +899,14 @@ static int msm_pcie_enable(u32 rc_idx, u32 options)
	/* enable power */

	if (options & PM_VREG) {
		ret = msm_pcie_vreg_init(rc_idx, &dev->pdev->dev);
		ret = msm_pcie_vreg_init(dev);
		if (ret)
			goto out;
	}

	/* enable clocks */
	if (options & PM_CLK) {
		ret = msm_pcie_clk_init(rc_idx, &dev->pdev->dev);
		ret = msm_pcie_clk_init(dev);
		wmb();
		if (ret)
			goto clk_fail;
@@ -975,7 +923,7 @@ static int msm_pcie_enable(u32 rc_idx, u32 options)

	if (options & PM_PIPE_CLK) {
		/* Enable the pipe clock */
		ret = msm_pcie_pipe_clk_init(rc_idx, &dev->pdev->dev);
		ret = msm_pcie_pipe_clk_init(dev);
		wmb();
		if (ret)
			goto link_fail;
@@ -1042,27 +990,21 @@ static int msm_pcie_enable(u32 rc_idx, u32 options)
		goto link_fail;
	}

	msm_pcie_config_controller(rc_idx);
	msm_pcie_config_controller(dev);

	if (!dev->msi_gicm_addr)
		msm_pcie_config_msi_controller(dev);

	if (dev->l1ss_supported)
		msm_pcie_config_l1ss(rc_idx);
		msm_pcie_config_l1ss(dev);

	if (options & PM_IRQ) {
		ret = msm_pcie_irq_init(dev);
		if (!ret)
			goto out;
	} else {
	goto out;
	}

link_fail:
	msm_pcie_clk_deinit(rc_idx);
	msm_pcie_clk_deinit(dev);
clk_fail:
	msm_pcie_vreg_deinit(rc_idx);
	msm_pcie_pipe_clk_deinit(rc_idx);
	msm_pcie_vreg_deinit(dev);
	msm_pcie_pipe_clk_deinit(dev);
out:
	dev->link_status = MSM_PCIE_LINK_ENABLED;
	mutex_unlock(&setup_lock);
@@ -1071,53 +1013,43 @@ out:
}


void msm_pcie_disable(u32 rc_idx, u32 options)
void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options)
{
	struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx];

	PCIE_DBG("\n");

	gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num,
				dev->gpio[MSM_PCIE_GPIO_PERST].on);

	if (options & PM_IRQ)
		msm_pcie_irq_deinit(dev);

	if (options & PM_CLK) {
		msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, 0,
					BIT(0));
		msm_pcie_clk_deinit(rc_idx);
		msm_pcie_clk_deinit(dev);
	}

	if (options & PM_VREG)
		msm_pcie_vreg_deinit(rc_idx);
		msm_pcie_vreg_deinit(dev);

	if (options & PM_PIPE_CLK)
		msm_pcie_pipe_clk_deinit(rc_idx);
		msm_pcie_pipe_clk_deinit(dev);

	dev->link_status = MSM_PCIE_LINK_DISABLED;
}

static int msm_pcie_setup(int nr, struct pci_sys_data *sys)
{
	static bool init;

	PCIE_DBG("bus %d\n", nr);

	/*
	 * specify linux PCI framework to allocate device memory (BARs)
	 * from msm_pcie_dev.dev_mem_res resource.
	 */
	if (!init) {
	sys->mem_offset = 0;
	sys->io_offset = 0;
		init = true;
	}

	pci_add_resource(&sys->resources,
			msm_pcie_dev[pcie_drv.current_rc].dev_io_res);
		((struct msm_pcie_dev_t *)(sys->private_data))->dev_io_res);
	pci_add_resource(&sys->resources,
			msm_pcie_dev[pcie_drv.current_rc].dev_mem_res);
		((struct msm_pcie_dev_t *)(sys->private_data))->dev_mem_res);
	return 1;
}

@@ -1136,23 +1068,23 @@ static struct pci_bus *msm_pcie_scan_bus(int nr,

static int msm_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	u32 rc_idx = pcie_drv.current_rc;
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);
	int ret = 0;

	PCIE_DBG("rc %d slot %d pin %d\n", rc_idx, slot, pin);
	PCIE_DBG("rc %s slot %d pin %d\n", pcie_dev->pdev->name, slot, pin);

	switch (pin) {
	case 1:
		ret = msm_pcie_dev[rc_idx].irq[MSM_PCIE_INT_A].num;
		ret = pcie_dev->irq[MSM_PCIE_INT_A].num;
		break;
	case 2:
		ret = msm_pcie_dev[rc_idx].irq[MSM_PCIE_INT_B].num;
		ret = pcie_dev->irq[MSM_PCIE_INT_B].num;
		break;
	case 3:
		ret = msm_pcie_dev[rc_idx].irq[MSM_PCIE_INT_C].num;
		ret = pcie_dev->irq[MSM_PCIE_INT_C].num;
		break;
	case 4:
		ret = msm_pcie_dev[rc_idx].irq[MSM_PCIE_INT_D].num;
		ret = pcie_dev->irq[MSM_PCIE_INT_D].num;
		break;
	default:
		pr_err("PCIe: unsupported pin number.\n");
@@ -1161,19 +1093,58 @@ static int msm_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
	return ret;
}

static struct hw_pci msm_pci = {
	.nr_controllers	= MAX_RC_NUM,

static struct hw_pci msm_pci[MAX_RC_NUM] = {
	{
	.domain = 0,
	.nr_controllers	= 1,
	.swizzle	= pci_common_swizzle,
	.setup		= msm_pcie_setup,
	.scan		= msm_pcie_scan_bus,
	.map_irq	= msm_pcie_map_irq,
	},
	{
	.domain = 1,
	.nr_controllers	= 1,
	.swizzle	= pci_common_swizzle,
	.setup		= msm_pcie_setup,
	.scan		= msm_pcie_scan_bus,
	.map_irq	= msm_pcie_map_irq,
	},
};

int msm_pcie_enumerate(u32 rc_idx)
{
	int ret = 0;
	struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx];

	PCIE_DBG("Enumerate RC %d\n", rc_idx);

	if (!dev->enumerated) {
		ret = msm_pcie_enable(dev, PM_ALL);

		/* kick start ARM PCI configuration framework */
		if (!ret) {
			msm_pci[rc_idx].private_data = (void **)&dev;
			pci_common_init(&msm_pci[rc_idx]);
			/* This has to happen only once */
			dev->enumerated = true;
		} else {
			pr_err("PCIe: %s: failed to enable RC %d.\n",
				__func__, dev->rc_idx);
		}
	} else {
		pr_err("PCIe: %s: RC %d has already been enumerated.\n",
			__func__, dev->rc_idx);
	}

	return ret;
}

static int msm_pcie_probe(struct platform_device *pdev)
{
	int ret = 0;
	int rc_idx;
	struct msm_pcie_dev_t *dev;

	PCIE_DBG("\n");

@@ -1246,6 +1217,7 @@ static int msm_pcie_probe(struct platform_device *pdev)
		}
	}

	msm_pcie_dev[rc_idx].rc_idx = rc_idx;
	msm_pcie_dev[rc_idx].pdev = pdev;
	msm_pcie_dev[rc_idx].vreg_n = 0;
	msm_pcie_dev[rc_idx].gpio_n = 0;
@@ -1254,6 +1226,7 @@ static int msm_pcie_probe(struct platform_device *pdev)
	msm_pcie_dev[rc_idx].link_status = MSM_PCIE_LINK_DEINIT;
	msm_pcie_dev[rc_idx].user_suspend = false;
	msm_pcie_dev[rc_idx].saved_state = NULL;
	msm_pcie_dev[rc_idx].enumerated = false;
	memcpy(msm_pcie_dev[rc_idx].vreg, msm_pcie_vreg_info,
				sizeof(msm_pcie_vreg_info));
	memcpy(msm_pcie_dev[rc_idx].gpio, msm_pcie_gpio_info,
@@ -1267,36 +1240,33 @@ static int msm_pcie_probe(struct platform_device *pdev)
	memcpy(msm_pcie_dev[rc_idx].irq, msm_pcie_irq_info,
				sizeof(msm_pcie_irq_info));

	ret = msm_pcie_get_resources(rc_idx, msm_pcie_dev[rc_idx].pdev);
	ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx],
				msm_pcie_dev[rc_idx].pdev);

	if (ret)
		goto decrease_rc_num;

	ret = msm_pcie_gpio_init(rc_idx);
	ret = msm_pcie_gpio_init(&msm_pcie_dev[rc_idx]);
	if (ret) {
		msm_pcie_release_resources(rc_idx);
		msm_pcie_release_resources(&msm_pcie_dev[rc_idx]);
		goto decrease_rc_num;
	}

	ret = msm_pcie_enable(rc_idx, PM_ALL);
	ret = msm_pcie_irq_init(&msm_pcie_dev[rc_idx]);
	if (ret) {
		pr_err("PCIe:failed to enable PCIe link in bootup\n");
		msm_pcie_gpio_deinit(rc_idx);
		msm_pcie_release_resources(rc_idx);
		msm_pcie_release_resources(&msm_pcie_dev[rc_idx]);
		msm_pcie_gpio_deinit(&msm_pcie_dev[rc_idx]);
		goto decrease_rc_num;
	}

	/* kick start ARM PCI configuration framework */
	if (pcie_drv.rc_num == pcie_drv.rc_expected) {
		msm_pci.nr_controllers = pcie_drv.rc_num;
		if (pcie_drv.rc_expected > 1)
			pcie_drv.current_rc = 0;
	ret = msm_pcie_enumerate(rc_idx);

	if (ret)
		pr_err(
			"PCIe:failed to enable RC %d in bootup; it will be enumerated upon WAKE signal.\n",
			rc_idx);
	else
			pcie_drv.current_rc = rc_idx;
		dev = &msm_pcie_dev[rc_idx];
		msm_pci.private_data = (void **)&dev;
		pci_common_init(&msm_pci);
	}
		PCIE_DBG("RC %d is enabled in bootup\n", rc_idx);

	msm_pcie_dev[rc_idx].dev = pci_get_device(PCIE_VENDOR_ID_RCP,
					PCIE_DEVICE_ID_RCP, NULL);
@@ -1332,10 +1302,10 @@ static int __exit msm_pcie_remove(struct platform_device *pdev)
	}

	msm_pcie_irq_deinit(&msm_pcie_dev[rc_idx]);
	msm_pcie_vreg_deinit(rc_idx);
	msm_pcie_clk_deinit(rc_idx);
	msm_pcie_gpio_deinit(rc_idx);
	msm_pcie_release_resources(rc_idx);
	msm_pcie_vreg_deinit(&msm_pcie_dev[rc_idx]);
	msm_pcie_clk_deinit(&msm_pcie_dev[rc_idx]);
	msm_pcie_gpio_deinit(&msm_pcie_dev[rc_idx]);
	msm_pcie_release_resources(&msm_pcie_dev[rc_idx]);

out:
	mutex_unlock(&pcie_drv.drv_lock);
@@ -1402,17 +1372,19 @@ DECLARE_PCI_FIXUP_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
			msm_pcie_fixup_early);

/* Suspend the PCIe link */
static int msm_pcie_pm_suspend(struct pci_dev *dev, u32 rc_idx,
static int msm_pcie_pm_suspend(struct pci_dev *dev,
			void *user, void *data, u32 options)
{
	int ret = 0;
	u32 val = 0;
	int ret_l23;
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);

	PCIE_DBG("RC %d\n", pcie_dev->rc_idx);

	if (dev) {
		ret = pci_save_state(dev);
		msm_pcie_dev[rc_idx].saved_state =
					pci_store_saved_state(dev);
		pcie_dev->saved_state =	pci_store_saved_state(dev);
	}
	if (ret) {
		pr_err("PCIe: fail to save state of RC 0x%p:%d.\n",
@@ -1429,18 +1401,18 @@ static int msm_pcie_pm_suspend(struct pci_dev *dev, u32 rc_idx,
		}
	}

	spin_lock_irqsave(&msm_pcie_dev[rc_idx].cfg_lock,
				msm_pcie_dev[rc_idx].irqsave_flags);
	msm_pcie_dev[rc_idx].cfg_access = false;
	spin_unlock_irqrestore(&msm_pcie_dev[rc_idx].cfg_lock,
				msm_pcie_dev[rc_idx].irqsave_flags);
	spin_lock_irqsave(&pcie_dev->cfg_lock,
				pcie_dev->irqsave_flags);
	pcie_dev->cfg_access = false;
	spin_unlock_irqrestore(&pcie_dev->cfg_lock,
				pcie_dev->irqsave_flags);

	msm_pcie_write_mask(msm_pcie_dev[rc_idx].elbi + PCIE20_ELBI_SYS_CTRL, 0,
	msm_pcie_write_mask(pcie_dev->elbi + PCIE20_ELBI_SYS_CTRL, 0,
				BIT(4));

	PCIE_DBG("PME_TURNOFF_MSG is sent out\n");

	ret_l23 = readl_poll_timeout((msm_pcie_dev[rc_idx].parf
	ret_l23 = readl_poll_timeout((pcie_dev->parf
		+ PCIE20_PARF_PM_STTS), val, (val & BIT(6)), 10000, 100000);

	/* check L23_Ready */
@@ -1449,7 +1421,7 @@ static int msm_pcie_pm_suspend(struct pci_dev *dev, u32 rc_idx,
	else
		PCIE_DBG("PM_Enter_L23 is NOT received\n");

	msm_pcie_disable(rc_idx, PM_PIPE_CLK | PM_CLK | PM_VREG);
	msm_pcie_disable(pcie_dev, PM_PIPE_CLK | PM_CLK | PM_VREG);

	return ret;
}
@@ -1457,12 +1429,14 @@ static int msm_pcie_pm_suspend(struct pci_dev *dev, u32 rc_idx,
static void msm_pcie_fixup_suspend(struct pci_dev *dev)
{
	int ret;
	u32 rc_idx = pcie_drv.current_rc;
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);

	PCIE_DBG("RC %d\n", pcie_dev->rc_idx);

	if (msm_pcie_dev[rc_idx].link_status != MSM_PCIE_LINK_ENABLED)
	if (pcie_dev->link_status != MSM_PCIE_LINK_ENABLED)
		return;

	ret = msm_pcie_pm_suspend(dev, rc_idx, NULL, NULL, 0);
	ret = msm_pcie_pm_suspend(dev, NULL, NULL, 0);
	if (ret)
		pr_err("PCIe: got failure in suspend:%d.\n", ret);
}
@@ -1470,18 +1444,21 @@ DECLARE_PCI_FIXUP_SUSPEND(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
			  msm_pcie_fixup_suspend);

/* Resume the PCIe link */
static int msm_pcie_pm_resume(struct pci_dev *dev, u32 rc_idx,
static int msm_pcie_pm_resume(struct pci_dev *dev,
			void *user, void *data, u32 options)
{
	int ret;
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);

	spin_lock_irqsave(&msm_pcie_dev[rc_idx].cfg_lock,
				msm_pcie_dev[rc_idx].irqsave_flags);
	msm_pcie_dev[rc_idx].cfg_access = true;
	spin_unlock_irqrestore(&msm_pcie_dev[rc_idx].cfg_lock,
				msm_pcie_dev[rc_idx].irqsave_flags);
	PCIE_DBG("RC %d\n", pcie_dev->rc_idx);

	ret = msm_pcie_enable(rc_idx, PM_PIPE_CLK | PM_CLK | PM_VREG);
	spin_lock_irqsave(&pcie_dev->cfg_lock,
				pcie_dev->irqsave_flags);
	pcie_dev->cfg_access = true;
	spin_unlock_irqrestore(&pcie_dev->cfg_lock,
				pcie_dev->irqsave_flags);

	ret = msm_pcie_enable(pcie_dev, PM_PIPE_CLK | PM_CLK | PM_VREG);
	if (ret) {
		pr_err("PCIe:fail to enable PCIe link in resume\n");
		return ret;
@@ -1489,8 +1466,7 @@ static int msm_pcie_pm_resume(struct pci_dev *dev, u32 rc_idx,
		PCIE_DBG("dev->bus->number = %d dev->bus->primary = %d\n",
			 dev->bus->number, dev->bus->primary);

		pci_load_and_free_saved_state(dev,
					&msm_pcie_dev[rc_idx].saved_state);
		pci_load_and_free_saved_state(dev, &pcie_dev->saved_state);

		pci_restore_state(dev);

@@ -1504,15 +1480,15 @@ static int msm_pcie_pm_resume(struct pci_dev *dev, u32 rc_idx,
void msm_pcie_fixup_resume(struct pci_dev *dev)
{
	int ret;
	u32 rc_idx = pcie_drv.current_rc;
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);

	PCIE_DBG("\n");
	PCIE_DBG("RC %d\n", pcie_dev->rc_idx);

	if ((msm_pcie_dev[rc_idx].link_status != MSM_PCIE_LINK_DISABLED) ||
		msm_pcie_dev[rc_idx].user_suspend)
	if ((pcie_dev->link_status != MSM_PCIE_LINK_DISABLED) ||
		pcie_dev->user_suspend)
		return;

	ret = msm_pcie_pm_resume(dev, rc_idx, NULL, NULL, 0);
	ret = msm_pcie_pm_resume(dev, NULL, NULL, 0);
	if (ret)
		pr_err("PCIe: got failure in fixup resume:%d.\n", ret);
}
@@ -1522,13 +1498,15 @@ DECLARE_PCI_FIXUP_RESUME(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
void msm_pcie_fixup_resume_early(struct pci_dev *dev)
{
	int ret;
	u32 rc_idx = pcie_drv.current_rc;
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);

	PCIE_DBG("RC %d\n", pcie_dev->rc_idx);

	if ((msm_pcie_dev[rc_idx].link_status != MSM_PCIE_LINK_DISABLED) ||
		msm_pcie_dev[rc_idx].user_suspend)
	if ((pcie_dev->link_status != MSM_PCIE_LINK_DISABLED) ||
		pcie_dev->user_suspend)
		return;

	ret = msm_pcie_pm_resume(dev, rc_idx, NULL, NULL, 0);
	ret = msm_pcie_pm_resume(dev, NULL, NULL, 0);
	if (ret)
		pr_err("PCIe: got failure in resume:%d.\n", ret);
}
@@ -1537,9 +1515,8 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,

static void msm_pcie_fixup_final(struct pci_dev *dev)
{
	PCIE_DBG("\n");

	if (pcie_drv.rc_expected > 1)
	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev);
	PCIE_DBG("RC %d\n", pcie_dev->rc_idx);
	pcie_drv.current_rc++;
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, msm_pcie_fixup_final);
@@ -1553,16 +1530,8 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,

	switch (busnr) {
	case 1:
		if (pcie_drv.rc_expected > 1)
		if (!options)
			rc_idx = 0;
		else
			rc_idx = pcie_drv.current_rc;
		break;
	case 3:
		if (pcie_drv.rc_expected > 1)
			rc_idx = 1;
		else
			rc_idx = pcie_drv.current_rc;
		break;
	default:
		pr_err("PCIe: unsupported bus number.\n");
@@ -1581,7 +1550,7 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
			break;
		}
		msm_pcie_dev[rc_idx].user_suspend = true;
		ret = msm_pcie_pm_suspend(dev, rc_idx, user, data, options);
		ret = msm_pcie_pm_suspend(dev, user, data, options);
		if (ret) {
			pr_err("PCIe: user failed to suspend the link.\n");
			msm_pcie_dev[rc_idx].user_suspend = false;
@@ -1595,7 +1564,7 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
				msm_pcie_dev[rc_idx].link_status);
			break;
		}
		ret = msm_pcie_pm_resume(dev, rc_idx, user, data, options);
		ret = msm_pcie_pm_resume(dev, user, data, options);
		if (ret)
			pr_err("PCIe: user failed to resume the link.\n");
		else
+5 −0
Original line number Diff line number Diff line
@@ -174,8 +174,13 @@ struct msm_pcie_dev_t {

	bool                         l1ss_supported;
	bool                         aux_clk_sync;

	uint32_t                     rc_idx;
	bool                         enumerated;
	struct work_struct	     handle_wake_work;
};

extern int msm_pcie_enumerate(u32 rc_idx);
extern void msm_pcie_config_msi_controller(struct msm_pcie_dev_t *dev);
extern int32_t msm_pcie_irq_init(struct msm_pcie_dev_t *dev);
extern void msm_pcie_irq_deinit(struct msm_pcie_dev_t *dev);
+32 −3

File changed.

Preview size limit exceeded, changes collapsed.