Skip to content

Commit a6e68f0

Browse files
Frank Saedavem330
authored andcommitted
net: phy: Add dts support for Motorcomm yt8521 gigabit ethernet phy
Add dts support for Motorcomm yt8521 gigabit ethernet phy. Add ytphy_rgmii_clk_delay_config function to support dst config for the delay of rgmii clk. This funciont is common for yt8521, yt8531s and yt8531. This patch has been verified on AM335x platform. Signed-off-by: Frank Sae <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4869a14 commit a6e68f0

File tree

1 file changed

+199
-54
lines changed

1 file changed

+199
-54
lines changed

drivers/net/phy/motorcomm.c

Lines changed: 199 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/kernel.h>
1111
#include <linux/module.h>
1212
#include <linux/phy.h>
13+
#include <linux/of.h>
1314

1415
#define PHY_ID_YT8511 0x0000010a
1516
#define PHY_ID_YT8521 0x0000011a
@@ -187,21 +188,9 @@
187188
* 1b1 use inverted tx_clk_rgmii.
188189
*/
189190
#define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14)
190-
/* TX Gig-E Delay is bits 3:0, default 0x1
191-
* TX Fast-E Delay is bits 7:4, default 0xf
192-
* RX Delay is bits 13:10, default 0x0
193-
* Delay = 150ps * N
194-
* On = 2250ps, off = 0ps
195-
*/
196191
#define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10)
197-
#define YT8521_RC1R_RX_DELAY_EN (0xF << 10)
198-
#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10)
199192
#define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
200-
#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4)
201-
#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4)
202193
#define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
203-
#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0)
204-
#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0)
205194
#define YT8521_RC1R_RGMII_0_000_NS 0
206195
#define YT8521_RC1R_RGMII_0_150_NS 1
207196
#define YT8521_RC1R_RGMII_0_300_NS 2
@@ -274,6 +263,10 @@
274263

275264
/* Extended Register end */
276265

266+
#define YTPHY_DTS_OUTPUT_CLK_DIS 0
267+
#define YTPHY_DTS_OUTPUT_CLK_25M 25000000
268+
#define YTPHY_DTS_OUTPUT_CLK_125M 125000000
269+
277270
struct yt8521_priv {
278271
/* combo_advertising is used for case of YT8521 in combo mode,
279272
* this means that yt8521 may work in utp or fiber mode which depends
@@ -640,6 +633,142 @@ static int yt8521_write_page(struct phy_device *phydev, int page)
640633
return ytphy_modify_ext(phydev, YT8521_REG_SPACE_SELECT_REG, mask, set);
641634
};
642635

636+
/**
637+
* struct ytphy_cfg_reg_map - map a config value to a register value
638+
* @cfg: value in device configuration
639+
* @reg: value in the register
640+
*/
641+
struct ytphy_cfg_reg_map {
642+
u32 cfg;
643+
u32 reg;
644+
};
645+
646+
static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = {
647+
/* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */
648+
{ 0, YT8521_RC1R_RGMII_0_000_NS },
649+
{ 150, YT8521_RC1R_RGMII_0_150_NS },
650+
{ 300, YT8521_RC1R_RGMII_0_300_NS },
651+
{ 450, YT8521_RC1R_RGMII_0_450_NS },
652+
{ 600, YT8521_RC1R_RGMII_0_600_NS },
653+
{ 750, YT8521_RC1R_RGMII_0_750_NS },
654+
{ 900, YT8521_RC1R_RGMII_0_900_NS },
655+
{ 1050, YT8521_RC1R_RGMII_1_050_NS },
656+
{ 1200, YT8521_RC1R_RGMII_1_200_NS },
657+
{ 1350, YT8521_RC1R_RGMII_1_350_NS },
658+
{ 1500, YT8521_RC1R_RGMII_1_500_NS },
659+
{ 1650, YT8521_RC1R_RGMII_1_650_NS },
660+
{ 1800, YT8521_RC1R_RGMII_1_800_NS },
661+
{ 1950, YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
662+
{ 2100, YT8521_RC1R_RGMII_2_100_NS },
663+
{ 2250, YT8521_RC1R_RGMII_2_250_NS },
664+
665+
/* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */
666+
{ 0 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_000_NS },
667+
{ 150 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_150_NS },
668+
{ 300 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_300_NS },
669+
{ 450 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_450_NS },
670+
{ 600 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_600_NS },
671+
{ 750 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_750_NS },
672+
{ 900 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_900_NS },
673+
{ 1050 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_050_NS },
674+
{ 1200 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_200_NS },
675+
{ 1350 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_350_NS },
676+
{ 1500 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_500_NS },
677+
{ 1650 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_650_NS },
678+
{ 1800 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_800_NS },
679+
{ 1950 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_950_NS },
680+
{ 2100 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_100_NS },
681+
{ 2250 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_250_NS }
682+
};
683+
684+
static u32 ytphy_get_delay_reg_value(struct phy_device *phydev,
685+
const char *prop_name,
686+
const struct ytphy_cfg_reg_map *tbl,
687+
int tb_size,
688+
u16 *rxc_dly_en,
689+
u32 dflt)
690+
{
691+
struct device_node *node = phydev->mdio.dev.of_node;
692+
int tb_size_half = tb_size / 2;
693+
u32 val;
694+
int i;
695+
696+
if (of_property_read_u32(node, prop_name, &val))
697+
goto err_dts_val;
698+
699+
/* when rxc_dly_en is NULL, it is get the delay for tx, only half of
700+
* tb_size is valid.
701+
*/
702+
if (!rxc_dly_en)
703+
tb_size = tb_size_half;
704+
705+
for (i = 0; i < tb_size; i++) {
706+
if (tbl[i].cfg == val) {
707+
if (rxc_dly_en && i < tb_size_half)
708+
*rxc_dly_en = 0;
709+
return tbl[i].reg;
710+
}
711+
}
712+
713+
phydev_warn(phydev, "Unsupported value %d for %s using default (%u)\n",
714+
val, prop_name, dflt);
715+
716+
err_dts_val:
717+
/* when rxc_dly_en is not NULL, it is get the delay for rx.
718+
* The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
719+
* so YT8521_CCR_RXC_DLY_EN should not be set.
720+
*/
721+
if (rxc_dly_en)
722+
*rxc_dly_en = 0;
723+
724+
return dflt;
725+
}
726+
727+
static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev)
728+
{
729+
int tb_size = ARRAY_SIZE(ytphy_rgmii_delays);
730+
u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN;
731+
u32 rx_reg, tx_reg;
732+
u16 mask, val = 0;
733+
int ret;
734+
735+
rx_reg = ytphy_get_delay_reg_value(phydev, "rx-internal-delay-ps",
736+
ytphy_rgmii_delays, tb_size,
737+
&rxc_dly_en,
738+
YT8521_RC1R_RGMII_1_950_NS);
739+
tx_reg = ytphy_get_delay_reg_value(phydev, "tx-internal-delay-ps",
740+
ytphy_rgmii_delays, tb_size, NULL,
741+
YT8521_RC1R_RGMII_1_950_NS);
742+
743+
switch (phydev->interface) {
744+
case PHY_INTERFACE_MODE_RGMII:
745+
rxc_dly_en = 0;
746+
break;
747+
case PHY_INTERFACE_MODE_RGMII_RXID:
748+
val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg);
749+
break;
750+
case PHY_INTERFACE_MODE_RGMII_TXID:
751+
rxc_dly_en = 0;
752+
val |= FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg);
753+
break;
754+
case PHY_INTERFACE_MODE_RGMII_ID:
755+
val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg) |
756+
FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg);
757+
break;
758+
default: /* do not support other modes */
759+
return -EOPNOTSUPP;
760+
}
761+
762+
ret = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG,
763+
YT8521_CCR_RXC_DLY_EN, rxc_dly_en);
764+
if (ret < 0)
765+
return ret;
766+
767+
/* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */
768+
mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK;
769+
return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val);
770+
}
771+
643772
/**
644773
* yt8521_probe() - read chip config then set suitable polling_mode
645774
* @phydev: a pointer to a &struct phy_device
@@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_device *phydev, int page)
648777
*/
649778
static int yt8521_probe(struct phy_device *phydev)
650779
{
780+
struct device_node *node = phydev->mdio.dev.of_node;
651781
struct device *dev = &phydev->mdio.dev;
652782
struct yt8521_priv *priv;
653783
int chip_config;
784+
u16 mask, val;
785+
u32 freq;
654786
int ret;
655787

656788
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_device *phydev)
695827
return ret;
696828
}
697829

698-
return 0;
830+
if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq))
831+
freq = YTPHY_DTS_OUTPUT_CLK_DIS;
832+
833+
if (phydev->drv->phy_id == PHY_ID_YT8521) {
834+
switch (freq) {
835+
case YTPHY_DTS_OUTPUT_CLK_DIS:
836+
mask = YT8521_SCR_SYNCE_ENABLE;
837+
val = 0;
838+
break;
839+
case YTPHY_DTS_OUTPUT_CLK_25M:
840+
mask = YT8521_SCR_SYNCE_ENABLE |
841+
YT8521_SCR_CLK_SRC_MASK |
842+
YT8521_SCR_CLK_FRE_SEL_125M;
843+
val = YT8521_SCR_SYNCE_ENABLE |
844+
FIELD_PREP(YT8521_SCR_CLK_SRC_MASK,
845+
YT8521_SCR_CLK_SRC_REF_25M);
846+
break;
847+
case YTPHY_DTS_OUTPUT_CLK_125M:
848+
mask = YT8521_SCR_SYNCE_ENABLE |
849+
YT8521_SCR_CLK_SRC_MASK |
850+
YT8521_SCR_CLK_FRE_SEL_125M;
851+
val = YT8521_SCR_SYNCE_ENABLE |
852+
YT8521_SCR_CLK_FRE_SEL_125M |
853+
FIELD_PREP(YT8521_SCR_CLK_SRC_MASK,
854+
YT8521_SCR_CLK_SRC_PLL_125M);
855+
break;
856+
default:
857+
phydev_warn(phydev, "Freq err:%u\n", freq);
858+
return -EINVAL;
859+
}
860+
} else if (phydev->drv->phy_id == PHY_ID_YT8531S) {
861+
return 0;
862+
} else {
863+
phydev_warn(phydev, "PHY id err\n");
864+
return -EINVAL;
865+
}
866+
867+
return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask,
868+
val);
699869
}
700870

701871
/**
@@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_device *phydev)
11801350
*/
11811351
static int yt8521_config_init(struct phy_device *phydev)
11821352
{
1353+
struct device_node *node = phydev->mdio.dev.of_node;
11831354
int old_page;
11841355
int ret = 0;
1185-
u16 val;
11861356

11871357
old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE);
11881358
if (old_page < 0)
11891359
goto err_restore_page;
11901360

1191-
switch (phydev->interface) {
1192-
case PHY_INTERFACE_MODE_RGMII:
1193-
val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS;
1194-
val |= YT8521_RC1R_RX_DELAY_DIS;
1195-
break;
1196-
case PHY_INTERFACE_MODE_RGMII_RXID:
1197-
val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS;
1198-
val |= YT8521_RC1R_RX_DELAY_EN;
1199-
break;
1200-
case PHY_INTERFACE_MODE_RGMII_TXID:
1201-
val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN;
1202-
val |= YT8521_RC1R_RX_DELAY_DIS;
1203-
break;
1204-
case PHY_INTERFACE_MODE_RGMII_ID:
1205-
val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN;
1206-
val |= YT8521_RC1R_RX_DELAY_EN;
1207-
break;
1208-
case PHY_INTERFACE_MODE_SGMII:
1209-
break;
1210-
default: /* do not support other modes */
1211-
ret = -EOPNOTSUPP;
1212-
goto err_restore_page;
1213-
}
1214-
12151361
/* set rgmii delay mode */
12161362
if (phydev->interface != PHY_INTERFACE_MODE_SGMII) {
1217-
ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG,
1218-
(YT8521_RC1R_RX_DELAY_MASK |
1219-
YT8521_RC1R_FE_TX_DELAY_MASK |
1220-
YT8521_RC1R_GE_TX_DELAY_MASK),
1221-
val);
1363+
ret = ytphy_rgmii_clk_delay_config(phydev);
12221364
if (ret < 0)
12231365
goto err_restore_page;
12241366
}
12251367

1226-
/* disable auto sleep */
1227-
ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG,
1228-
YT8521_ESC1R_SLEEP_SW, 0);
1229-
if (ret < 0)
1230-
goto err_restore_page;
1231-
1232-
/* enable RXC clock when no wire plug */
1233-
ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG,
1234-
YT8521_CGR_RX_CLK_EN, 0);
1235-
if (ret < 0)
1236-
goto err_restore_page;
1368+
if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) {
1369+
/* disable auto sleep */
1370+
ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG,
1371+
YT8521_ESC1R_SLEEP_SW, 0);
1372+
if (ret < 0)
1373+
goto err_restore_page;
1374+
}
12371375

1376+
if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) {
1377+
/* enable RXC clock when no wire plug */
1378+
ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG,
1379+
YT8521_CGR_RX_CLK_EN, 0);
1380+
if (ret < 0)
1381+
goto err_restore_page;
1382+
}
12381383
err_restore_page:
12391384
return phy_restore_page(phydev, old_page, ret);
12401385
}

0 commit comments

Comments
 (0)