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

Commit 01a9259b authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/host-rockchip' into next

* pci/host-rockchip:
  PCI: rockchip: Use normal register bank for config accessors
  PCI: rockchip: Use local struct device pointer consistently
  PCI: rockchip: Check for clk_prepare_enable() errors during resume
  MAINTAINERS: Remove Wenrui Li as Rockchip PCIe driver maintainer
  PCI: rockchip: Configure RC's MPS setting
  PCI: rockchip: Reconfigure configuration space header type
  PCI: rockchip: Split out rockchip_pcie_cfg_configuration_accesses()
  PCI: rockchip: Move configuration accesses into rockchip_pcie_cfg_atu()
  PCI: rockchip: Rename rockchip_cfg_atu() to rockchip_pcie_cfg_atu()
  PCI: rockchip: Control vpcie0v9 for system PM
parents 66a63e15 dc8cca5e
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -9943,7 +9943,6 @@ F: drivers/pci/dwc/pcie-kirin.c

PCIE DRIVER FOR ROCKCHIP
M:	Shawn Lin <shawn.lin@rock-chips.com>
M:	Wenrui Li <wenrui.li@rock-chips.com>
L:	linux-pci@vger.kernel.org
L:	linux-rockchip@lists.infradead.org
S:	Maintained
+100 −25
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@
		 PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
		 PCIE_CORE_INT_MMVC)

#define PCIE_RC_CONFIG_NORMAL_BASE	0x800000
#define PCIE_RC_CONFIG_BASE		0xa00000
#define PCIE_RC_CONFIG_RID_CCR		(PCIE_RC_CONFIG_BASE + 0x08)
#define   PCIE_RC_CONFIG_SCC_SHIFT		16
@@ -146,6 +147,9 @@
#define   PCIE_RC_CONFIG_DCR_CSPL_SHIFT		18
#define   PCIE_RC_CONFIG_DCR_CSPL_LIMIT		0xff
#define   PCIE_RC_CONFIG_DCR_CPLS_SHIFT		26
#define PCIE_RC_CONFIG_DCSR		(PCIE_RC_CONFIG_BASE + 0xc8)
#define   PCIE_RC_CONFIG_DCSR_MPS_MASK		GENMASK(7, 5)
#define   PCIE_RC_CONFIG_DCSR_MPS_256		(0x1 << 5)
#define PCIE_RC_CONFIG_LINK_CAP		(PCIE_RC_CONFIG_BASE + 0xcc)
#define   PCIE_RC_CONFIG_LINK_CAP_L0S		BIT(10)
#define PCIE_RC_CONFIG_LCS		(PCIE_RC_CONFIG_BASE + 0xd0)
@@ -175,6 +179,8 @@
#define IB_ROOT_PORT_REG_SIZE_SHIFT		3
#define AXI_WRAPPER_IO_WRITE			0x6
#define AXI_WRAPPER_MEM_WRITE			0x2
#define AXI_WRAPPER_TYPE0_CFG			0xa
#define AXI_WRAPPER_TYPE1_CFG			0xb
#define AXI_WRAPPER_NOR_MSG			0xc

#define MAX_AXI_IB_ROOTPORT_REGION_NUM		3
@@ -198,6 +204,7 @@
#define RC_REGION_0_ADDR_TRANS_H		0x00000000
#define RC_REGION_0_ADDR_TRANS_L		0x00000000
#define RC_REGION_0_PASS_BITS			(25 - 1)
#define RC_REGION_0_TYPE_MASK			GENMASK(3, 0)
#define MAX_AXI_WRAPPER_REGION_NUM		33

struct rockchip_pcie {
@@ -295,7 +302,9 @@ static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip,
static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
				     int where, int size, u32 *val)
{
	void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where;
	void __iomem *addr;

	addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + where;

	if (!IS_ALIGNED((uintptr_t)addr, size)) {
		*val = 0;
@@ -319,11 +328,13 @@ static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip,
				     int where, int size, u32 val)
{
	u32 mask, tmp, offset;
	void __iomem *addr;

	offset = where & ~0x3;
	addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offset;

	if (size == 4) {
		writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
		writel(val, addr);
		return PCIBIOS_SUCCESSFUL;
	}

@@ -334,13 +345,33 @@ static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip,
	 * corrupt RW1C bits in adjacent registers.  But the hardware
	 * doesn't support smaller writes.
	 */
	tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
	tmp = readl(addr) & mask;
	tmp |= val << ((where & 0x3) * 8);
	writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
	writel(tmp, addr);

	return PCIBIOS_SUCCESSFUL;
}

static void rockchip_pcie_cfg_configuration_accesses(
		struct rockchip_pcie *rockchip, u32 type)
{
	u32 ob_desc_0;

	/* Configuration Accesses for region 0 */
	rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);

	rockchip_pcie_write(rockchip,
			    (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
			    PCIE_CORE_OB_REGION_ADDR0);
	rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H,
			    PCIE_CORE_OB_REGION_ADDR1);
	ob_desc_0 = rockchip_pcie_read(rockchip, PCIE_CORE_OB_REGION_DESC0);
	ob_desc_0 &= ~(RC_REGION_0_TYPE_MASK);
	ob_desc_0 |= (type | (0x1 << 23));
	rockchip_pcie_write(rockchip, ob_desc_0, PCIE_CORE_OB_REGION_DESC0);
	rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1);
}

static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
				       struct pci_bus *bus, u32 devfn,
				       int where, int size, u32 *val)
@@ -355,6 +386,13 @@ static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
		return PCIBIOS_BAD_REGISTER_NUMBER;
	}

	if (bus->parent->number == rockchip->root_bus_nr)
		rockchip_pcie_cfg_configuration_accesses(rockchip,
						AXI_WRAPPER_TYPE0_CFG);
	else
		rockchip_pcie_cfg_configuration_accesses(rockchip,
						AXI_WRAPPER_TYPE1_CFG);

	if (size == 4) {
		*val = readl(rockchip->reg_base + busdev);
	} else if (size == 2) {
@@ -379,6 +417,13 @@ static int rockchip_pcie_wr_other_conf(struct rockchip_pcie *rockchip,
	if (!IS_ALIGNED(busdev, size))
		return PCIBIOS_BAD_REGISTER_NUMBER;

	if (bus->parent->number == rockchip->root_bus_nr)
		rockchip_pcie_cfg_configuration_accesses(rockchip,
						AXI_WRAPPER_TYPE0_CFG);
	else
		rockchip_pcie_cfg_configuration_accesses(rockchip,
						AXI_WRAPPER_TYPE1_CFG);

	if (size == 4)
		writel(val, rockchip->reg_base + busdev);
	else if (size == 2)
@@ -664,15 +709,10 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
		rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP);
	}

	rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);

	rockchip_pcie_write(rockchip,
			    (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
			    PCIE_CORE_OB_REGION_ADDR0);
	rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H,
			    PCIE_CORE_OB_REGION_ADDR1);
	rockchip_pcie_write(rockchip, 0x0080000a, PCIE_CORE_OB_REGION_DESC0);
	rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1);
	status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCSR);
	status &= ~PCIE_RC_CONFIG_DCSR_MPS_MASK;
	status |= PCIE_RC_CONFIG_DCSR_MPS_256;
	rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR);

	return 0;
}
@@ -1156,13 +1196,16 @@ static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie *rockchip,
	return 0;
}

static int rockchip_cfg_atu(struct rockchip_pcie *rockchip)
static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
{
	struct device *dev = rockchip->dev;
	int offset;
	int err;
	int reg_no;

	rockchip_pcie_cfg_configuration_accesses(rockchip,
						 AXI_WRAPPER_TYPE0_CFG);

	for (reg_no = 0; reg_no < (rockchip->mem_size >> 20); reg_no++) {
		err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1,
						AXI_WRAPPER_MEM_WRITE,
@@ -1251,6 +1294,9 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev)
	clk_disable_unprepare(rockchip->aclk_perf_pcie);
	clk_disable_unprepare(rockchip->aclk_pcie);

	if (!IS_ERR(rockchip->vpcie0v9))
		regulator_disable(rockchip->vpcie0v9);

	return ret;
}

@@ -1259,24 +1305,54 @@ static int __maybe_unused rockchip_pcie_resume_noirq(struct device *dev)
	struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
	int err;

	clk_prepare_enable(rockchip->clk_pcie_pm);
	clk_prepare_enable(rockchip->hclk_pcie);
	clk_prepare_enable(rockchip->aclk_perf_pcie);
	clk_prepare_enable(rockchip->aclk_pcie);
	if (!IS_ERR(rockchip->vpcie0v9)) {
		err = regulator_enable(rockchip->vpcie0v9);
		if (err) {
			dev_err(dev, "fail to enable vpcie0v9 regulator\n");
			return err;
		}
	}

	err = clk_prepare_enable(rockchip->clk_pcie_pm);
	if (err)
		goto err_pcie_pm;

	err = clk_prepare_enable(rockchip->hclk_pcie);
	if (err)
		goto err_hclk_pcie;

	err = clk_prepare_enable(rockchip->aclk_perf_pcie);
	if (err)
		goto err_aclk_perf_pcie;

	err = clk_prepare_enable(rockchip->aclk_pcie);
	if (err)
		goto err_aclk_pcie;

	err = rockchip_pcie_init_port(rockchip);
	if (err)
		return err;
		goto err_pcie_resume;

	err = rockchip_cfg_atu(rockchip);
	err = rockchip_pcie_cfg_atu(rockchip);
	if (err)
		return err;
		goto err_pcie_resume;

	/* Need this to enter L1 again */
	rockchip_pcie_update_txcredit_mui(rockchip);
	rockchip_pcie_enable_interrupts(rockchip);

	return 0;

err_pcie_resume:
	clk_disable_unprepare(rockchip->aclk_pcie);
err_aclk_pcie:
	clk_disable_unprepare(rockchip->aclk_perf_pcie);
err_aclk_perf_pcie:
	clk_disable_unprepare(rockchip->hclk_pcie);
err_hclk_pcie:
	clk_disable_unprepare(rockchip->clk_pcie_pm);
err_pcie_pm:
	return err;
}

static int rockchip_pcie_probe(struct platform_device *pdev)
@@ -1388,19 +1464,18 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
		}
	}

	err = rockchip_cfg_atu(rockchip);
	err = rockchip_pcie_cfg_atu(rockchip);
	if (err)
		goto err_free_res;

	rockchip->msg_region = devm_ioremap(rockchip->dev,
					    rockchip->msg_bus_addr, SZ_1M);
	rockchip->msg_region = devm_ioremap(dev, rockchip->msg_bus_addr, SZ_1M);
	if (!rockchip->msg_region) {
		err = -ENOMEM;
		goto err_free_res;
	}

	list_splice_init(&res, &bridge->windows);
	bridge->dev.parent = &pdev->dev;
	bridge->dev.parent = dev;
	bridge->sysdata = rockchip;
	bridge->busnr = 0;
	bridge->ops = &rockchip_pcie_ops;