Commit fc539459 authored by Fugang Duan's avatar Fugang Duan Committed by David S. Miller
Browse files

net: fec: add MAC internal delayed clock feature support



i.MX8QM ENET IP version support timing specification that MAC
integrate clock delay in RGMII mode, the delayed TXC/RXC as an
alternative option to work well with various PHYs.

Signed-off-by: default avatarFugang Duan <fugang.duan@nxp.com>
Signed-off-by: default avatarJoakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b82f8c3f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -381,6 +381,9 @@ struct bufdesc_ex {
#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF)
#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))

#define FEC_ENET_TXC_DLY	((uint)0x00010000)
#define FEC_ENET_RXC_DLY	((uint)0x00020000)

/* ENET interrupt coalescing macro define */
#define FEC_ITR_CLK_SEL		(0x1 << 30)
#define FEC_ITR_EN		(0x1 << 31)
@@ -543,6 +546,7 @@ struct fec_enet_private {
	struct clk *clk_ref;
	struct clk *clk_enet_out;
	struct clk *clk_ptp;
	struct clk *clk_2x_txclk;

	bool ptp_clk_on;
	struct mutex ptp_clk_mutex;
@@ -565,6 +569,8 @@ struct fec_enet_private {
	uint	phy_speed;
	phy_interface_t	phy_interface;
	struct device_node *phy_node;
	bool	rgmii_txc_dly;
	bool	rgmii_rxc_dly;
	int	link;
	int	full_duplex;
	int	speed;
+27 −0
Original line number Diff line number Diff line
@@ -1137,6 +1137,13 @@ fec_restart(struct net_device *ndev)
	if (fep->bufdesc_ex)
		ecntl |= (1 << 4);

	if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&
	    fep->rgmii_txc_dly)
		ecntl |= FEC_ENET_TXC_DLY;
	if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&
	    fep->rgmii_rxc_dly)
		ecntl |= FEC_ENET_RXC_DLY;

#ifndef CONFIG_M5272
	/* Enable the MIB statistic event counters */
	writel(0 << 31, fep->hwp + FEC_MIB_CTRLSTAT);
@@ -2000,6 +2007,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
		if (ret)
			goto failed_clk_ref;

		ret = clk_prepare_enable(fep->clk_2x_txclk);
		if (ret)
			goto failed_clk_2x_txclk;

		fec_enet_phy_reset_after_clk_enable(ndev);
	} else {
		clk_disable_unprepare(fep->clk_enet_out);
@@ -2010,10 +2021,14 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
			mutex_unlock(&fep->ptp_clk_mutex);
		}
		clk_disable_unprepare(fep->clk_ref);
		clk_disable_unprepare(fep->clk_2x_txclk);
	}

	return 0;

failed_clk_2x_txclk:
	if (fep->clk_ref)
		clk_disable_unprepare(fep->clk_ref);
failed_clk_ref:
	if (fep->clk_ptp) {
		mutex_lock(&fep->ptp_clk_mutex);
@@ -3704,6 +3719,7 @@ fec_probe(struct platform_device *pdev)
	char irq_name[8];
	int irq_cnt;
	struct fec_devinfo *dev_info;
	u32 rgmii_delay;

	fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);

@@ -3761,6 +3777,12 @@ fec_probe(struct platform_device *pdev)
	if (ret)
		goto failed_stop_mode;

	/* For rgmii internal delay, valid values are 0ps and 2000ps */
	if (of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_delay))
		fep->rgmii_txc_dly = true;
	if (of_property_read_u32(np, "rx-internal-delay-ps", &rgmii_delay))
		fep->rgmii_rxc_dly = true;

	phy_node = of_parse_phandle(np, "phy-handle", 0);
	if (!phy_node && of_phy_is_fixed_link(np)) {
		ret = of_phy_register_fixed_link(np);
@@ -3812,6 +3834,11 @@ fec_probe(struct platform_device *pdev)
		fep->clk_ref = NULL;
	fep->clk_ref_rate = clk_get_rate(fep->clk_ref);

	/* clk_2x_txclk is optional, depends on board */
	fep->clk_2x_txclk = devm_clk_get(&pdev->dev, "enet_2x_txclk");
	if (IS_ERR(fep->clk_2x_txclk))
		fep->clk_2x_txclk = NULL;

	fep->bufdesc_ex = fep->quirks & FEC_QUIRK_HAS_BUFDESC_EX;
	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
	if (IS_ERR(fep->clk_ptp)) {