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

Commit 646244b2 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'cpsw-errata-workaround'



Mugunthan V N says:

====================
Add AM335x PG1.0 CPSW errata workaround

With commit 870915fe ("drivers: net: cpsw: remove
disable_irq/enable_irq as irq can be masked from cpsw itself"),
CPSW on AM335x beagle bone white is broken as there is a errata
for AM335x PG1.0. This patch series implements the workaround by
disabling the interrupts from ARM IRQ controller for AM335x SoC
in addition to the masking of interrupts in CPSW.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 182ad468 21696f71
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -700,7 +700,7 @@
		};

		mac: ethernet@4a100000 {
			compatible = "ti,cpsw";
			compatible = "ti,am335x-cpsw","ti,cpsw";
			ti,hwmods = "cpgmac0";
			clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>;
			clock-names = "fck", "cpts";
+1 −1
Original line number Diff line number Diff line
@@ -1399,7 +1399,7 @@
		};

		mac: ethernet@4a100000 {
			compatible = "ti,cpsw";
			compatible = "ti,dra7-cpsw","ti,cpsw";
			ti,hwmods = "gmac";
			clocks = <&dpll_gmac_ck>, <&gmac_gmii_ref_clk_div>;
			clock-names = "fck", "cpts";
+77 −6
Original line number Diff line number Diff line
@@ -387,6 +387,9 @@ struct cpsw_priv {
	struct cpsw_ale			*ale;
	bool				rx_pause;
	bool				tx_pause;
	bool				quirk_irq;
	bool				rx_irq_disabled;
	bool				tx_irq_disabled;
	/* snapshot of IRQ numbers */
	u32 irqs_table[4];
	u32 num_irqs;
@@ -755,6 +758,11 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
	writel(0, &priv->wr_regs->tx_en);
	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);

	if (priv->quirk_irq) {
		disable_irq_nosync(priv->irqs_table[1]);
		priv->tx_irq_disabled = true;
	}

	napi_schedule(&priv->napi_tx);
	return IRQ_HANDLED;
}
@@ -766,6 +774,11 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
	writel(0, &priv->wr_regs->rx_en);

	if (priv->quirk_irq) {
		disable_irq_nosync(priv->irqs_table[0]);
		priv->rx_irq_disabled = true;
	}

	napi_schedule(&priv->napi_rx);
	return IRQ_HANDLED;
}
@@ -779,6 +792,10 @@ static int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
	if (num_tx < budget) {
		napi_complete(napi_tx);
		writel(0xff, &priv->wr_regs->tx_en);
		if (priv->quirk_irq && priv->tx_irq_disabled) {
			priv->tx_irq_disabled = false;
			enable_irq(priv->irqs_table[1]);
		}
	}

	if (num_tx)
@@ -796,6 +813,10 @@ static int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)
	if (num_rx < budget) {
		napi_complete(napi_rx);
		writel(0xff, &priv->wr_regs->rx_en);
		if (priv->quirk_irq && priv->rx_irq_disabled) {
			priv->rx_irq_disabled = false;
			enable_irq(priv->irqs_table[0]);
		}
	}

	if (num_rx)
@@ -1267,6 +1288,16 @@ static int cpsw_ndo_open(struct net_device *ndev)
		napi_enable(&priv_sl0->napi_rx);
		napi_enable(&priv_sl0->napi_tx);

		if (priv_sl0->tx_irq_disabled) {
			priv_sl0->tx_irq_disabled = false;
			enable_irq(priv->irqs_table[1]);
		}

		if (priv_sl0->rx_irq_disabled) {
			priv_sl0->rx_irq_disabled = false;
			enable_irq(priv->irqs_table[0]);
		}

		if (WARN_ON(!priv->data.rx_descs))
			priv->data.rx_descs = 128;

@@ -2128,6 +2159,44 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
	return ret;
}

#define CPSW_QUIRK_IRQ		BIT(0)

static struct platform_device_id cpsw_devtype[] = {
	{
		/* keep it for existing comaptibles */
		.name = "cpsw",
		.driver_data = CPSW_QUIRK_IRQ,
	}, {
		.name = "am335x-cpsw",
		.driver_data = CPSW_QUIRK_IRQ,
	}, {
		.name = "am4372-cpsw",
		.driver_data = 0,
	}, {
		.name = "dra7-cpsw",
		.driver_data = 0,
	}, {
		/* sentinel */
	}
};
MODULE_DEVICE_TABLE(platform, cpsw_devtype);

enum ti_cpsw_type {
	CPSW = 0,
	AM335X_CPSW,
	AM4372_CPSW,
	DRA7_CPSW,
};

static const struct of_device_id cpsw_of_mtable[] = {
	{ .compatible = "ti,cpsw", .data = &cpsw_devtype[CPSW], },
	{ .compatible = "ti,am335x-cpsw", .data = &cpsw_devtype[AM335X_CPSW], },
	{ .compatible = "ti,am4372-cpsw", .data = &cpsw_devtype[AM4372_CPSW], },
	{ .compatible = "ti,dra7-cpsw", .data = &cpsw_devtype[DRA7_CPSW], },
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, cpsw_of_mtable);

static int cpsw_probe(struct platform_device *pdev)
{
	struct cpsw_platform_data	*data;
@@ -2137,6 +2206,7 @@ static int cpsw_probe(struct platform_device *pdev)
	struct cpsw_ale_params		ale_params;
	void __iomem			*ss_regs;
	struct resource			*res, *ss_res;
	const struct of_device_id	*of_id;
	u32 slave_offset, sliver_offset, slave_size;
	int ret = 0, i;
	int irq;
@@ -2327,6 +2397,13 @@ static int cpsw_probe(struct platform_device *pdev)
		goto clean_ale_ret;
	}

	of_id = of_match_device(cpsw_of_mtable, &pdev->dev);
	if (of_id) {
		pdev->id_entry = of_id->data;
		if (pdev->id_entry->driver_data)
			priv->quirk_irq = true;
	}

	/* Grab RX and TX IRQs. Note that we also have RX_THRESHOLD and
	 * MISC IRQs which are always kept disabled with this driver so
	 * we will not request them.
@@ -2491,12 +2568,6 @@ static int cpsw_resume(struct device *dev)

static SIMPLE_DEV_PM_OPS(cpsw_pm_ops, cpsw_suspend, cpsw_resume);

static const struct of_device_id cpsw_of_mtable[] = {
	{ .compatible = "ti,cpsw", },
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, cpsw_of_mtable);

static struct platform_driver cpsw_driver = {
	.driver = {
		.name	 = "cpsw",