Skip to content

Commit

Permalink
Merge branch 'cpsw-errata-workaround'
Browse files Browse the repository at this point in the history
Mugunthan V N says:

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

With commit 870915f ("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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 13, 2015
2 parents 182ad46 + 21696f7 commit 646244b
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 8 deletions.
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/am33xx.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/dra7.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
83 changes: 77 additions & 6 deletions drivers/net/ethernet/ti/cpsw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit 646244b

Please sign in to comment.