Commit 1e6bbc46 authored by Remi Pommarel's avatar Remi Pommarel Committed by Lorenzo Pieralisi
Browse files

PCI: amlogic: Use AXG PCIE



Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy
logic can be mutualized between AXG and G12A platforms.

This new PHY makes use of the shared MIPI/PCIE analog PHY found on AXG
platforms, which need to be used in order to have reliable PCIE
communications.

Signed-off-by: default avatarRemi Pommarel <repk@triplefau.lt>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Acked-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
parent e2463559
Loading
Loading
Loading
Loading
+22 −94
Original line number Diff line number Diff line
@@ -66,7 +66,6 @@
#define PORT_CLK_RATE			100000000UL
#define MAX_PAYLOAD_SIZE		256
#define MAX_READ_REQ_SIZE		256
#define MESON_PCIE_PHY_POWERUP		0x1c
#define PCIE_RESET_DELAY		500
#define PCIE_SHARED_RESET		1
#define PCIE_NORMAL_RESET		0
@@ -81,26 +80,19 @@ enum pcie_data_rate {
struct meson_pcie_mem_res {
	void __iomem *elbi_base;
	void __iomem *cfg_base;
	void __iomem *phy_base;
};

struct meson_pcie_clk_res {
	struct clk *clk;
	struct clk *mipi_gate;
	struct clk *port_clk;
	struct clk *general_clk;
};

struct meson_pcie_rc_reset {
	struct reset_control *phy;
	struct reset_control *port;
	struct reset_control *apb;
};

struct meson_pcie_param {
	bool has_shared_phy;
};

struct meson_pcie {
	struct dw_pcie pci;
	struct meson_pcie_mem_res mem_res;
@@ -108,7 +100,6 @@ struct meson_pcie {
	struct meson_pcie_rc_reset mrst;
	struct gpio_desc *reset_gpio;
	struct phy *phy;
	const struct meson_pcie_param *param;
};

static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp,
@@ -130,13 +121,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)
{
	struct meson_pcie_rc_reset *mrst = &mp->mrst;

	if (!mp->param->has_shared_phy) {
		mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET);
		if (IS_ERR(mrst->phy))
			return PTR_ERR(mrst->phy);
		reset_control_deassert(mrst->phy);
	}

	mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET);
	if (IS_ERR(mrst->port))
		return PTR_ERR(mrst->port);
@@ -162,22 +146,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev,
	return devm_ioremap_resource(dev, res);
}

static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev,
					       struct meson_pcie *mp,
					       const char *id)
{
	struct device *dev = mp->pci.dev;
	struct resource *res;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id);
	if (!res) {
		dev_err(dev, "No REG resource %s\n", id);
		return ERR_PTR(-ENXIO);
	}

	return devm_ioremap(dev, res->start, resource_size(res));
}

static int meson_pcie_get_mems(struct platform_device *pdev,
			       struct meson_pcie *mp)
{
@@ -189,14 +157,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
	if (IS_ERR(mp->mem_res.cfg_base))
		return PTR_ERR(mp->mem_res.cfg_base);

	/* Meson AXG SoC has two PCI controllers use same phy register */
	if (!mp->param->has_shared_phy) {
		mp->mem_res.phy_base =
			meson_pcie_get_mem_shared(pdev, mp, "phy");
		if (IS_ERR(mp->mem_res.phy_base))
			return PTR_ERR(mp->mem_res.phy_base);
	}

	return 0;
}

@@ -204,7 +164,6 @@ static int meson_pcie_power_on(struct meson_pcie *mp)
{
	int ret = 0;

	if (mp->param->has_shared_phy) {
	ret = phy_init(mp->phy);
	if (ret)
		return ret;
@@ -214,27 +173,24 @@ static int meson_pcie_power_on(struct meson_pcie *mp)
		phy_exit(mp->phy);
		return ret;
	}
	} else
		writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base);

	return 0;
}

static void meson_pcie_power_off(struct meson_pcie *mp)
{
	phy_power_off(mp->phy);
	phy_exit(mp->phy);
}

static int meson_pcie_reset(struct meson_pcie *mp)
{
	struct meson_pcie_rc_reset *mrst = &mp->mrst;
	int ret = 0;

	if (mp->param->has_shared_phy) {
	ret = phy_reset(mp->phy);
	if (ret)
		return ret;
	} else {
		reset_control_assert(mrst->phy);
		udelay(PCIE_RESET_DELAY);
		reset_control_deassert(mrst->phy);
		udelay(PCIE_RESET_DELAY);
	}

	reset_control_assert(mrst->port);
	reset_control_assert(mrst->apb);
@@ -286,12 +242,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)
	if (IS_ERR(res->port_clk))
		return PTR_ERR(res->port_clk);

	if (!mp->param->has_shared_phy) {
		res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0);
		if (IS_ERR(res->mipi_gate))
			return PTR_ERR(res->mipi_gate);
	}

	res->general_clk = meson_pcie_probe_clock(dev, "general", 0);
	if (IS_ERR(res->general_clk))
		return PTR_ERR(res->general_clk);
@@ -562,7 +512,6 @@ static const struct dw_pcie_ops dw_pcie_ops = {

static int meson_pcie_probe(struct platform_device *pdev)
{
	const struct meson_pcie_param *match_data;
	struct device *dev = &pdev->dev;
	struct dw_pcie *pci;
	struct meson_pcie *mp;
@@ -576,16 +525,9 @@ static int meson_pcie_probe(struct platform_device *pdev)
	pci->dev = dev;
	pci->ops = &dw_pcie_ops;

	match_data = of_device_get_match_data(dev);
	if (!match_data) {
		dev_err(dev, "failed to get match data\n");
		return -ENODEV;
	}
	mp->param = match_data;

	if (mp->param->has_shared_phy) {
	mp->phy = devm_phy_get(dev, "pcie");
		if (IS_ERR(mp->phy))
	if (IS_ERR(mp->phy)) {
		dev_err(dev, "get phy failed, %ld\n", PTR_ERR(mp->phy));
		return PTR_ERR(mp->phy);
	}

@@ -636,30 +578,16 @@ static int meson_pcie_probe(struct platform_device *pdev)
	return 0;

err_phy:
	if (mp->param->has_shared_phy) {
		phy_power_off(mp->phy);
		phy_exit(mp->phy);
	}

	meson_pcie_power_off(mp);
	return ret;
}

static struct meson_pcie_param meson_pcie_axg_param = {
	.has_shared_phy = false,
};

static struct meson_pcie_param meson_pcie_g12a_param = {
	.has_shared_phy = true,
};

static const struct of_device_id meson_pcie_of_match[] = {
	{
		.compatible = "amlogic,axg-pcie",
		.data = &meson_pcie_axg_param,
	},
	{
		.compatible = "amlogic,g12a-pcie",
		.data = &meson_pcie_g12a_param,
	},
	{},
};