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

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
...@@ -381,6 +381,9 @@ struct bufdesc_ex { ...@@ -381,6 +381,9 @@ struct bufdesc_ex {
#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF) #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF)
#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~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 */ /* ENET interrupt coalescing macro define */
#define FEC_ITR_CLK_SEL (0x1 << 30) #define FEC_ITR_CLK_SEL (0x1 << 30)
#define FEC_ITR_EN (0x1 << 31) #define FEC_ITR_EN (0x1 << 31)
...@@ -543,6 +546,7 @@ struct fec_enet_private { ...@@ -543,6 +546,7 @@ struct fec_enet_private {
struct clk *clk_ref; struct clk *clk_ref;
struct clk *clk_enet_out; struct clk *clk_enet_out;
struct clk *clk_ptp; struct clk *clk_ptp;
struct clk *clk_2x_txclk;
bool ptp_clk_on; bool ptp_clk_on;
struct mutex ptp_clk_mutex; struct mutex ptp_clk_mutex;
...@@ -565,6 +569,8 @@ struct fec_enet_private { ...@@ -565,6 +569,8 @@ struct fec_enet_private {
uint phy_speed; uint phy_speed;
phy_interface_t phy_interface; phy_interface_t phy_interface;
struct device_node *phy_node; struct device_node *phy_node;
bool rgmii_txc_dly;
bool rgmii_rxc_dly;
int link; int link;
int full_duplex; int full_duplex;
int speed; int speed;
......
...@@ -1137,6 +1137,13 @@ fec_restart(struct net_device *ndev) ...@@ -1137,6 +1137,13 @@ fec_restart(struct net_device *ndev)
if (fep->bufdesc_ex) if (fep->bufdesc_ex)
ecntl |= (1 << 4); 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 #ifndef CONFIG_M5272
/* Enable the MIB statistic event counters */ /* Enable the MIB statistic event counters */
writel(0 << 31, fep->hwp + FEC_MIB_CTRLSTAT); writel(0 << 31, fep->hwp + FEC_MIB_CTRLSTAT);
...@@ -2000,6 +2007,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) ...@@ -2000,6 +2007,10 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
if (ret) if (ret)
goto failed_clk_ref; 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); fec_enet_phy_reset_after_clk_enable(ndev);
} else { } else {
clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_enet_out);
...@@ -2010,10 +2021,14 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) ...@@ -2010,10 +2021,14 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
mutex_unlock(&fep->ptp_clk_mutex); mutex_unlock(&fep->ptp_clk_mutex);
} }
clk_disable_unprepare(fep->clk_ref); clk_disable_unprepare(fep->clk_ref);
clk_disable_unprepare(fep->clk_2x_txclk);
} }
return 0; return 0;
failed_clk_2x_txclk:
if (fep->clk_ref)
clk_disable_unprepare(fep->clk_ref);
failed_clk_ref: failed_clk_ref:
if (fep->clk_ptp) { if (fep->clk_ptp) {
mutex_lock(&fep->ptp_clk_mutex); mutex_lock(&fep->ptp_clk_mutex);
...@@ -3704,6 +3719,7 @@ fec_probe(struct platform_device *pdev) ...@@ -3704,6 +3719,7 @@ fec_probe(struct platform_device *pdev)
char irq_name[8]; char irq_name[8];
int irq_cnt; int irq_cnt;
struct fec_devinfo *dev_info; struct fec_devinfo *dev_info;
u32 rgmii_delay;
fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
...@@ -3761,6 +3777,12 @@ fec_probe(struct platform_device *pdev) ...@@ -3761,6 +3777,12 @@ fec_probe(struct platform_device *pdev)
if (ret) if (ret)
goto failed_stop_mode; 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); phy_node = of_parse_phandle(np, "phy-handle", 0);
if (!phy_node && of_phy_is_fixed_link(np)) { if (!phy_node && of_phy_is_fixed_link(np)) {
ret = of_phy_register_fixed_link(np); ret = of_phy_register_fixed_link(np);
...@@ -3812,6 +3834,11 @@ fec_probe(struct platform_device *pdev) ...@@ -3812,6 +3834,11 @@ fec_probe(struct platform_device *pdev)
fep->clk_ref = NULL; fep->clk_ref = NULL;
fep->clk_ref_rate = clk_get_rate(fep->clk_ref); 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->bufdesc_ex = fep->quirks & FEC_QUIRK_HAS_BUFDESC_EX;
fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
if (IS_ERR(fep->clk_ptp)) { if (IS_ERR(fep->clk_ptp)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment