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

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

Merge "msm: ep_pcie: support coexistence of MDM9x40 and mdmcalifornium"

parents 4f11fdea 8ec03cca
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ Optional Properties:
  - max-clock-frequency-hz: list of the maximum operating frequencies stored
				in the same order of clock names;
  - qcom,pcie-phy-ver: version of PCIe PHY.
  - qcom,phy-init: The initialization sequence to bring up the PCIe PHY.
    Should be specified in groups (offset, value, delay, direction).
  - qcom,phy-status-reg: Register offset for PHY status.
  - qcom,dbi-base-reg: Register offset for DBI base address.
  - qcom,slv-space-reg: Register offset for slave address space size.
  - qcom,pcie-link-speed: generation of PCIe link speed. The value could be
    1, 2 or 3.
  - qcom,pcie-active-config: boolean type; active configuration of PCIe
@@ -110,4 +115,13 @@ Example:
		qcom,pcie-link-speed = <1>;
		qcom,pcie-active-config;
		qcom,pcie-aggregated-irq;
		qcom,phy-status-reg = <0x728>;
		qcom,dbi-base-reg = <0x168>;
		qcom,slv-space-reg = <0x16c>;

		qcom,phy-init = <0x604 0x03 0x0 0x1
					0x048 0x08 0x0 0x1
					0x64c 0x4d 0x0 0x1
					0x600 0x00 0x0 0x1
					0x608 0x03 0x0 0x1>;
	};
+15 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/msm_ep_pcie.h>

#define PCIE20_PARF_SYS_CTRL           0x00
@@ -255,6 +256,14 @@ struct ep_pcie_irq_info_t {
	u32          num;
};

/* phy info structure */
struct ep_pcie_phy_info_t {
	u32	offset;
	u32	val;
	u32	delay;
	u32	direction;
};

/* pcie endpoint device structure */
struct ep_pcie_dev_t {
	struct platform_device       *pdev;
@@ -278,6 +287,11 @@ struct ep_pcie_dev_t {
	u32                          link_speed;
	bool                         active_config;
	bool                         aggregated_irq;
	u32                          dbi_base_reg;
	u32                          slv_space_reg;
	u32                          phy_status_reg;
	u32                          phy_init_len;
	struct ep_pcie_phy_info_t    *phy_init;

	u32                          rev;
	u32                          phy_rev;
+89 −11
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -131,12 +131,19 @@ static int ep_pcie_gpio_init(struct ep_pcie_dev_t *dev)
		info = &dev->gpio[i];

		if (!info->num) {
			if (i == EP_PCIE_GPIO_MDM2AP) {
				EP_PCIE_DBG(dev,
					"PCIe V%d: gpio %s does not exist.\n",
					dev->rev, info->name);
				continue;
			} else {
				EP_PCIE_ERR(dev,
					"PCIe V%d:  the number of gpio %s is invalid\n",
					dev->rev, info->name);
				rc = -EINVAL;
				break;
			}
		}

		rc = gpio_request(info->num, info->name);
		if (rc) {
@@ -463,9 +470,17 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
	ep_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x0);

	/* adjust DBI base address */
	writel_relaxed(0x3FFFE000, dev->parf + PCIE20_PARF_DBI_BASE_ADDR);
	if (dev->dbi_base_reg)
		writel_relaxed(0x3FFFE000, dev->parf + dev->dbi_base_reg);
	else
		writel_relaxed(0x3FFFE000,
			dev->parf + PCIE20_PARF_DBI_BASE_ADDR);

	/* Configure PCIe core to support 1GB aperture */
	if (dev->slv_space_reg)
		ep_pcie_write_reg(dev->parf, dev->slv_space_reg,
			0x40000000);
	else
		ep_pcie_write_reg(dev->parf, PCIE20_PARF_SLV_ADDR_SPACE_SIZE,
			0x40000000);

@@ -576,6 +591,7 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
			readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_MASK));
	}

	if (dev->active_config)
		ep_pcie_write_reg(dev->dm_core, PCIE20_AUX_CLK_FREQ_REG, 0x14);
}

@@ -681,7 +697,7 @@ static void ep_pcie_notify_event(struct ep_pcie_dev_t *dev,
static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
					struct platform_device *pdev)
{
	int i, len, cnt, ret = 0;
	int i, len, cnt, ret = 0, size = 0;
	struct ep_pcie_vreg_info_t *vreg_info;
	struct ep_pcie_gpio_info_t *gpio_info;
	struct ep_pcie_clk_info_t  *clk_info;
@@ -694,6 +710,34 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,

	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);

	of_get_property(pdev->dev.of_node, "qcom,phy-init", &size);
	if (size) {
		dev->phy_init = (struct ep_pcie_phy_info_t *)
			devm_kzalloc(&pdev->dev, size, GFP_KERNEL);

		if (dev->phy_init) {
			dev->phy_init_len =
				size / sizeof(*dev->phy_init);
			EP_PCIE_DBG(dev,
					"PCIe V%d: phy init length is 0x%x.\n",
					dev->rev, dev->phy_init_len);

			of_property_read_u32_array(pdev->dev.of_node,
				"qcom,phy-init",
				(unsigned int *)dev->phy_init,
				size / sizeof(dev->phy_init->offset));
		} else {
			EP_PCIE_ERR(dev,
					"PCIe V%d: Could not allocate memory for phy init sequence.\n",
					dev->rev);
			return -ENOMEM;
		}
	} else {
		EP_PCIE_DBG(dev,
			"PCIe V%d: PHY V%d: phy init sequence is not present in DT.\n",
			dev->rev, dev->phy_rev);
	}

	cnt = of_property_count_strings((&pdev->dev)->of_node,
			"clock-names");
	if (cnt > 0) {
@@ -782,6 +826,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
			EP_PCIE_DBG(dev,
				"GPIO %s is not supported in this configuration.\n",
				gpio_info->name);
			ret = 0;
		}
	}

@@ -1977,6 +2022,39 @@ static int ep_pcie_probe(struct platform_device *pdev)
		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-link-speed:%d.\n",
			ep_pcie_dev.rev, ep_pcie_dev.link_speed);

	ret = of_property_read_u32((&pdev->dev)->of_node,
				"qcom,dbi-base-reg",
				&ep_pcie_dev.dbi_base_reg);
	if (ret)
		EP_PCIE_DBG(&ep_pcie_dev,
			"PCIe V%d: dbi-base-reg does not exist.\n",
			ep_pcie_dev.rev);
	else
		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: dbi-base-reg:0x%x.\n",
			ep_pcie_dev.rev, ep_pcie_dev.dbi_base_reg);

	ret = of_property_read_u32((&pdev->dev)->of_node,
				"qcom,slv-space-reg",
				&ep_pcie_dev.slv_space_reg);
	if (ret)
		EP_PCIE_DBG(&ep_pcie_dev,
			"PCIe V%d: slv-space-reg does not exist.\n",
			ep_pcie_dev.rev);
	else
		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: slv-space-reg:0x%x.\n",
			ep_pcie_dev.rev, ep_pcie_dev.slv_space_reg);

	ret = of_property_read_u32((&pdev->dev)->of_node,
				"qcom,phy-status-reg",
				&ep_pcie_dev.phy_status_reg);
	if (ret)
		EP_PCIE_DBG(&ep_pcie_dev,
			"PCIe V%d: phy-status-reg does not exist.\n",
			ep_pcie_dev.rev);
	else
		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: phy-status-reg:0x%x.\n",
			ep_pcie_dev.rev, ep_pcie_dev.phy_status_reg);

	ep_pcie_dev.phy_rev = 1;
	ret = of_property_read_u32((&pdev->dev)->of_node,
				"qcom,pcie-phy-ver",
@@ -2002,7 +2080,7 @@ static int ep_pcie_probe(struct platform_device *pdev)
		"PCIe V%d: aggregated IRQ is %s enabled.\n",
		ep_pcie_dev.rev, ep_pcie_dev.aggregated_irq ? "" : "not");

	ep_pcie_dev.rev = 1511053;
	ep_pcie_dev.rev = 1610071;
	ep_pcie_dev.pdev = pdev;
	memcpy(ep_pcie_dev.vreg, ep_pcie_vreg_info,
				sizeof(ep_pcie_vreg_info));
+1 −1
Original line number Diff line number Diff line
@@ -232,7 +232,7 @@ void ep_pcie_reg_dump(struct ep_pcie_dev_t *dev, u32 sel, bool linkdown)
		if (!(sel & BIT(r)))
			continue;

		if (r == EP_PCIE_RES_PHY)
		if ((r == EP_PCIE_RES_PHY) && (dev->phy_rev > 3))
			ep_pcie_phy_dump(dev);

		size = resource_size(dev->res[r].resource);
+52 −5
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -19,9 +19,49 @@

void ep_pcie_phy_init(struct ep_pcie_dev_t *dev)
{
	switch (dev->phy_rev) {
	case 3:
		EP_PCIE_DBG(dev,
			"PCIe V%d: PHY V%d: Initializing 20nm QMP phy - 100MHz\n",
			dev->rev, dev->phy_rev);
		break;
	case 4:
		EP_PCIE_DBG(dev,
			"PCIe V%d: PHY V%d: Initializing 14nm QMP phy - 100MHz\n",
			dev->rev, dev->phy_rev);
		break;
	case 5:
		EP_PCIE_DBG(dev,
			"PCIe V%d: PHY V%d: Initializing 10nm QMP phy - 100MHz\n",
			dev->rev, dev->phy_rev);
		break;
	default:
		EP_PCIE_ERR(dev,
			"PCIe V%d: Unexpected phy version %d is caught!\n",
			dev->rev, dev->phy_rev);
	}

	if (dev->phy_init_len && dev->phy_init) {
		int i;
		struct ep_pcie_phy_info_t *phy_init;

		EP_PCIE_DBG(dev,
			"PCIe V%d: PHY V%d: process the sequence specified by DT.\n",
			dev->rev, dev->phy_rev);

		i =  dev->phy_init_len;
		phy_init = dev->phy_init;
		while (i--) {
			ep_pcie_write_reg(dev->phy,
				phy_init->offset,
				phy_init->val);
			if (phy_init->delay)
				usleep_range(phy_init->delay,
					phy_init->delay + 1);
			phy_init++;
		}
		return;
	}

	ep_pcie_write_reg(dev->phy, PCIE_PHY_SW_RESET, 0x01);
	ep_pcie_write_reg(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x01);
@@ -106,7 +146,14 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev)

bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev)
{
	if (readl_relaxed(dev->phy + PCIE_PHY_PCS_STATUS) & BIT(6))
	u32 offset;

	if (dev->phy_status_reg)
		offset = dev->phy_status_reg;
	else
		offset = PCIE_PHY_PCS_STATUS;

	if (readl_relaxed(dev->phy + offset) & BIT(6))
		return false;
	else
		return true;