Commit 102779c6 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'macb-sama7g5'



Claudiu Beznea says:

====================
net: macb: add support for sama7g5

This series adds support for SAMA7G5 Ethernet interfaces: one 10/100Mbps
and one 1Gbps interfaces.

Along with it I also included a fix to disable clocks for SiFive FU540-C000
on failure path of fu540_c000_clk_init().

Thank you,
Claudiu Beznea

Changed in v3:
- use clk_bulk_disable_unprepare in patch 3/8
- corrected clang compilation warning in patch 3/8
- revert changes in macb_clk_init() in patch 3/8

Changes in v2:
- introduced patch "net: macb: add function to disable all macb clocks" and
  update patch "net: macb: unprepare clocks in case of failure" accordingly
- collected tags
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 102e2c07 700d566e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@ Required properties:
  Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
  Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
  Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
  Use "microchip,sama7g5-emac" for Microchip SAMA7G5 ethernet interface.
  Use "microchip,sama7g5-gem" for Microchip SAMA7G5 gigabit ethernet interface.
  Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device
	For "sifive,fu540-c000-gem", second range is required to specify the
+11 −0
Original line number Diff line number Diff line
@@ -699,6 +699,7 @@
#define MACB_CAPS_GEM_HAS_PTP			0x00000040
#define MACB_CAPS_BD_RD_PREFETCH		0x00000080
#define MACB_CAPS_NEEDS_RSTONUBR		0x00000100
#define MACB_CAPS_CLK_HW_CHG			0x04000000
#define MACB_CAPS_MACB_IS_EMAC			0x08000000
#define MACB_CAPS_FIFO_MODE			0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
@@ -1147,6 +1148,14 @@ struct macb_pm_data {
	u32 usrio;
};

struct macb_usrio_config {
	u32 mii;
	u32 rmii;
	u32 rgmii;
	u32 refclk;
	u32 hdfctlen;
};

struct macb_config {
	u32			caps;
	unsigned int		dma_burst_length;
@@ -1155,6 +1164,7 @@ struct macb_config {
			    struct clk **rx_clk, struct clk **tsu_clk);
	int	(*init)(struct platform_device *pdev);
	int	jumbo_max_len;
	const struct macb_usrio_config *usrio;
};

struct tsu_incr {
@@ -1288,6 +1298,7 @@ struct macb {
	u32	rx_intr_mask;

	struct macb_pm_data pm_data;
	const struct macb_usrio_config *usrio;
};

#ifdef CONFIG_MACB_USE_HWSTAMP
+98 −36
Original line number Diff line number Diff line
@@ -460,15 +460,14 @@ static void macb_init_buffers(struct macb *bp)

/**
 * macb_set_tx_clk() - Set a clock to a new frequency
 * @clk:	Pointer to the clock to change
 * @bp:		pointer to struct macb
 * @speed:	New frequency in Hz
 * @dev:	Pointer to the struct net_device
 */
static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
static void macb_set_tx_clk(struct macb *bp, int speed)
{
	long ferr, rate, rate_rounded;

	if (!clk)
	if (!bp->tx_clk || !(bp->caps & MACB_CAPS_CLK_HW_CHG))
		return;

	switch (speed) {
@@ -485,7 +484,7 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
		return;
	}

	rate_rounded = clk_round_rate(clk, rate);
	rate_rounded = clk_round_rate(bp->tx_clk, rate);
	if (rate_rounded < 0)
		return;

@@ -495,11 +494,12 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
	ferr = abs(rate_rounded - rate);
	ferr = DIV_ROUND_UP(ferr, rate / 100000);
	if (ferr > 5)
		netdev_warn(dev, "unable to generate target frequency: %ld Hz\n",
		netdev_warn(bp->dev,
			    "unable to generate target frequency: %ld Hz\n",
			    rate);

	if (clk_set_rate(clk, rate_rounded))
		netdev_err(dev, "adjusting tx_clk failed.\n");
	if (clk_set_rate(bp->tx_clk, rate_rounded))
		netdev_err(bp->dev, "adjusting tx_clk failed.\n");
}

static void macb_validate(struct phylink_config *config,
@@ -751,7 +751,7 @@ static void macb_mac_link_up(struct phylink_config *config,
		if (rx_pause)
			ctrl |= MACB_BIT(PAE);

		macb_set_tx_clk(bp->tx_clk, speed, ndev);
		macb_set_tx_clk(bp, speed);

		/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
		 * cleared the pipeline and control registers.
@@ -3694,6 +3694,20 @@ static void macb_probe_queues(void __iomem *mem,
	*num_queues = hweight32(*queue_mask);
}

static void macb_clks_disable(struct clk *pclk, struct clk *hclk, struct clk *tx_clk,
			      struct clk *rx_clk, struct clk *tsu_clk)
{
	struct clk_bulk_data clks[] = {
		{ .clk = tsu_clk, },
		{ .clk = rx_clk, },
		{ .clk = pclk, },
		{ .clk = hclk, },
		{ .clk = tx_clk },
	};

	clk_bulk_disable_unprepare(ARRAY_SIZE(clks), clks);
}

static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
			 struct clk **hclk, struct clk **tx_clk,
			 struct clk **rx_clk, struct clk **tsu_clk)
@@ -3913,15 +3927,15 @@ static int macb_init(struct platform_device *pdev)
	if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) {
		val = 0;
		if (phy_interface_mode_is_rgmii(bp->phy_interface))
			val = GEM_BIT(RGMII);
			val = bp->usrio->rgmii;
		else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
			 (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
			val = MACB_BIT(RMII);
			val = bp->usrio->rmii;
		else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
			val = MACB_BIT(MII);
			val = bp->usrio->mii;

		if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
			val |= MACB_BIT(CLKEN);
			val |= bp->usrio->refclk;

		macb_or_gem_writel(bp, USRIO, val);
	}
@@ -4406,8 +4420,10 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
		return err;

	mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL);
	if (!mgmt)
		return -ENOMEM;
	if (!mgmt) {
		err = -ENOMEM;
		goto err_disable_clks;
	}

	init.name = "sifive-gemgxl-mgmt";
	init.ops = &fu540_c000_ops;
@@ -4418,16 +4434,26 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
	mgmt->hw.init = &init;

	*tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw);
	if (IS_ERR(*tx_clk))
		return PTR_ERR(*tx_clk);
	if (IS_ERR(*tx_clk)) {
		err = PTR_ERR(*tx_clk);
		goto err_disable_clks;
	}

	err = clk_prepare_enable(*tx_clk);
	if (err)
	if (err) {
		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
	else
		*tx_clk = NULL;
		goto err_disable_clks;
	} else {
		dev_info(&pdev->dev, "Registered clk switch '%s'\n", init.name);
	}

	return 0;

err_disable_clks:
	macb_clks_disable(*pclk, *hclk, *tx_clk, *rx_clk, *tsu_clk);

	return err;
}

static int fu540_c000_init(struct platform_device *pdev)
@@ -4439,6 +4465,21 @@ static int fu540_c000_init(struct platform_device *pdev)
	return macb_init(pdev);
}

static const struct macb_usrio_config macb_default_usrio = {
	.mii = MACB_BIT(MII),
	.rmii = MACB_BIT(RMII),
	.rgmii = GEM_BIT(RGMII),
	.refclk = MACB_BIT(CLKEN),
};

static const struct macb_usrio_config sama7g5_usrio = {
	.mii = 0,
	.rmii = 1,
	.rgmii = 2,
	.refclk = BIT(2),
	.hdfctlen = BIT(6),
};

static const struct macb_config fu540_c000_config = {
	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO |
		MACB_CAPS_GEM_HAS_PTP,
@@ -4446,12 +4487,14 @@ static const struct macb_config fu540_c000_config = {
	.clk_init = fu540_c000_clk_init,
	.init = fu540_c000_init,
	.jumbo_max_len = 10240,
	.usrio = &macb_default_usrio,
};

static const struct macb_config at91sam9260_config = {
	.caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config sama5d3macb_config = {
@@ -4459,6 +4502,7 @@ static const struct macb_config sama5d3macb_config = {
	      | MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config pc302gem_config = {
@@ -4466,6 +4510,7 @@ static const struct macb_config pc302gem_config = {
	.dma_burst_length = 16,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config sama5d2_config = {
@@ -4473,6 +4518,7 @@ static const struct macb_config sama5d2_config = {
	.dma_burst_length = 16,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config sama5d3_config = {
@@ -4482,6 +4528,7 @@ static const struct macb_config sama5d3_config = {
	.clk_init = macb_clk_init,
	.init = macb_init,
	.jumbo_max_len = 10240,
	.usrio = &macb_default_usrio,
};

static const struct macb_config sama5d4_config = {
@@ -4489,18 +4536,21 @@ static const struct macb_config sama5d4_config = {
	.dma_burst_length = 4,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config emac_config = {
	.caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC,
	.clk_init = at91ether_clk_init,
	.init = at91ether_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config np4_config = {
	.caps = MACB_CAPS_USRIO_DISABLED,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config zynqmp_config = {
@@ -4511,6 +4561,7 @@ static const struct macb_config zynqmp_config = {
	.clk_init = macb_clk_init,
	.init = macb_init,
	.jumbo_max_len = 10240,
	.usrio = &macb_default_usrio,
};

static const struct macb_config zynq_config = {
@@ -4519,6 +4570,23 @@ static const struct macb_config zynq_config = {
	.dma_burst_length = 16,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &macb_default_usrio,
};

static const struct macb_config sama7g5_gem_config = {
	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_CLK_HW_CHG,
	.dma_burst_length = 16,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &sama7g5_usrio,
};

static const struct macb_config sama7g5_emac_config = {
	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_USRIO_HAS_CLKEN,
	.dma_burst_length = 16,
	.clk_init = macb_clk_init,
	.init = macb_init,
	.usrio = &sama7g5_usrio,
};

static const struct of_device_id macb_dt_ids[] = {
@@ -4538,6 +4606,8 @@ static const struct of_device_id macb_dt_ids[] = {
	{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
	{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
	{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
	{ .compatible = "microchip,sama7g5-gem", .data = &sama7g5_gem_config },
	{ .compatible = "microchip,sama7g5-emac", .data = &sama7g5_emac_config },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, macb_dt_ids);
@@ -4640,6 +4710,8 @@ static int macb_probe(struct platform_device *pdev)
		bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
	device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);

	bp->usrio = macb_config->usrio;

	spin_lock_init(&bp->lock);

	/* setup capabilities */
@@ -4735,11 +4807,7 @@ err_out_free_netdev:
	free_netdev(dev);

err_disable_clocks:
	clk_disable_unprepare(tx_clk);
	clk_disable_unprepare(hclk);
	clk_disable_unprepare(pclk);
	clk_disable_unprepare(rx_clk);
	clk_disable_unprepare(tsu_clk);
	macb_clks_disable(pclk, hclk, tx_clk, rx_clk, tsu_clk);
	pm_runtime_disable(&pdev->dev);
	pm_runtime_set_suspended(&pdev->dev);
	pm_runtime_dont_use_autosuspend(&pdev->dev);
@@ -4764,11 +4832,8 @@ static int macb_remove(struct platform_device *pdev)
		pm_runtime_disable(&pdev->dev);
		pm_runtime_dont_use_autosuspend(&pdev->dev);
		if (!pm_runtime_suspended(&pdev->dev)) {
			clk_disable_unprepare(bp->tx_clk);
			clk_disable_unprepare(bp->hclk);
			clk_disable_unprepare(bp->pclk);
			clk_disable_unprepare(bp->rx_clk);
			clk_disable_unprepare(bp->tsu_clk);
			macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk,
					  bp->rx_clk, bp->tsu_clk);
			pm_runtime_set_suspended(&pdev->dev);
		}
		phylink_destroy(bp->phylink);
@@ -4947,13 +5012,10 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev)
	struct net_device *netdev = dev_get_drvdata(dev);
	struct macb *bp = netdev_priv(netdev);

	if (!(device_may_wakeup(dev))) {
		clk_disable_unprepare(bp->tx_clk);
		clk_disable_unprepare(bp->hclk);
		clk_disable_unprepare(bp->pclk);
		clk_disable_unprepare(bp->rx_clk);
	}
	clk_disable_unprepare(bp->tsu_clk);
	if (!(device_may_wakeup(dev)))
		macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, bp->rx_clk, bp->tsu_clk);
	else
		macb_clks_disable(NULL, NULL, NULL, NULL, bp->tsu_clk);

	return 0;
}