1 // SPDX-License-Identifier: GPL-2.0+
6 * Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
10 #include <dm/devres.h>
11 #include <linux/delay.h>
12 #include <linux/math64.h>
13 #include <linux/mdio.h>
16 #define PHY_ID_TJA_1103 0x001BB010
18 #define VEND1_DEVICE_CONTROL 0x0040
19 #define DEVICE_CONTROL_RESET BIT(15)
20 #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14)
21 #define DEVICE_CONTROL_CONFIG_ALL_EN BIT(13)
23 #define VEND1_PORT_CONTROL 0x8040
24 #define PORT_CONTROL_EN BIT(14)
26 #define VEND1_PHY_CONTROL 0x8100
27 #define PHY_CONFIG_EN BIT(14)
28 #define PHY_START_OP BIT(0)
30 #define VEND1_PHY_CONFIG 0x8108
31 #define PHY_CONFIG_AUTO BIT(0)
33 #define VEND1_PORT_INFRA_CONTROL 0xAC00
34 #define PORT_INFRA_CONTROL_EN BIT(14)
36 #define VEND1_RXID 0xAFCC
37 #define VEND1_TXID 0xAFCD
38 #define ID_ENABLE BIT(15)
40 #define VEND1_ABILITIES 0xAFC4
41 #define RGMII_ID_ABILITY BIT(15)
42 #define RGMII_ABILITY BIT(14)
43 #define RMII_ABILITY BIT(10)
44 #define REVMII_ABILITY BIT(9)
45 #define MII_ABILITY BIT(8)
46 #define SGMII_ABILITY BIT(0)
48 #define VEND1_MII_BASIC_CONFIG 0xAFC6
49 #define MII_BASIC_CONFIG_REV BIT(8)
50 #define MII_BASIC_CONFIG_SGMII 0x9
51 #define MII_BASIC_CONFIG_RGMII 0x7
52 #define MII_BASIC_CONFIG_RMII 0x5
53 #define MII_BASIC_CONFIG_MII 0x4
55 #define RGMII_PERIOD_PS 8000U
56 #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360)
57 #define MIN_ID_PS 1644U
58 #define MAX_ID_PS 2260U
59 #define DEFAULT_ID_PS 2000U
61 #define RESET_DELAY_MS 25
62 #define CONF_EN_DELAY_US 450
69 static int nxp_c45_soft_reset(struct phy_device
*phydev
)
73 ret
= phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_DEVICE_CONTROL
,
74 DEVICE_CONTROL_RESET
);
79 ret
= phy_read_mmd(phydev
, MDIO_MMD_VEND1
,
80 VEND1_DEVICE_CONTROL
);
81 if (!(ret
& DEVICE_CONTROL_RESET
))
83 mdelay(RESET_DELAY_MS
);
89 static int nxp_c45_start_op(struct phy_device
*phydev
)
91 return phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_PHY_CONTROL
,
95 static int nxp_c45_config_enable(struct phy_device
*phydev
)
97 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_DEVICE_CONTROL
,
98 DEVICE_CONTROL_CONFIG_GLOBAL_EN
|
99 DEVICE_CONTROL_CONFIG_ALL_EN
);
100 udelay(CONF_EN_DELAY_US
);
102 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_PORT_CONTROL
,
104 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_PHY_CONTROL
,
106 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_PORT_INFRA_CONTROL
,
107 PORT_INFRA_CONTROL_EN
);
112 static u64
nxp_c45_get_phase_shift(u64 phase_offset_raw
)
114 /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9.
115 * To avoid floating point operations we'll multiply by 10
116 * and get 1 decimal point precision.
118 phase_offset_raw
*= 10;
119 phase_offset_raw
-= 738;
120 return div_u64(phase_offset_raw
, 9);
123 static void nxp_c45_disable_delays(struct phy_device
*phydev
)
125 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_TXID
, 0);
126 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_RXID
, 0);
129 static int nxp_c45_check_delay(struct phy_device
*phydev
, u32 delay
)
131 if (delay
< MIN_ID_PS
) {
132 pr_err("%s: delay value smaller than %u\n",
133 phydev
->drv
->name
, MIN_ID_PS
);
137 if (delay
> MAX_ID_PS
) {
138 pr_err("%s: delay value higher than %u\n",
139 phydev
->drv
->name
, MAX_ID_PS
);
146 static int nxp_c45_get_delays(struct phy_device
*phydev
)
148 struct nxp_c45_phy
*priv
= phydev
->priv
;
151 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
152 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_TXID
) {
153 ret
= dev_read_u32(phydev
->dev
, "tx-internal-delay-ps",
156 priv
->tx_delay
= DEFAULT_ID_PS
;
158 ret
= nxp_c45_check_delay(phydev
, priv
->tx_delay
);
160 pr_err("%s: tx-internal-delay-ps invalid value\n",
166 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
167 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_RXID
) {
168 ret
= dev_read_u32(phydev
->dev
, "rx-internal-delay-ps",
171 priv
->rx_delay
= DEFAULT_ID_PS
;
173 ret
= nxp_c45_check_delay(phydev
, priv
->rx_delay
);
175 pr_err("%s: rx-internal-delay-ps invalid value\n",
184 static void nxp_c45_set_delays(struct phy_device
*phydev
)
186 struct nxp_c45_phy
*priv
= phydev
->priv
;
187 u64 tx_delay
= priv
->tx_delay
;
188 u64 rx_delay
= priv
->rx_delay
;
191 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
192 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_TXID
) {
193 degree
= div_u64(tx_delay
, PS_PER_DEGREE
);
194 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_TXID
,
195 ID_ENABLE
| nxp_c45_get_phase_shift(degree
));
197 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_TXID
, 0);
200 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
201 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_RXID
) {
202 degree
= div_u64(rx_delay
, PS_PER_DEGREE
);
203 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_RXID
,
204 ID_ENABLE
| nxp_c45_get_phase_shift(degree
));
206 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_RXID
, 0);
210 static int nxp_c45_set_phy_mode(struct phy_device
*phydev
)
214 ret
= phy_read_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_ABILITIES
);
215 pr_debug("%s: Clause 45 managed PHY abilities 0x%x\n",
216 phydev
->drv
->name
, ret
);
218 switch (phydev
->interface
) {
219 case PHY_INTERFACE_MODE_RGMII
:
220 if (!(ret
& RGMII_ABILITY
)) {
221 pr_err("%s: rgmii mode not supported\n",
225 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_MII_BASIC_CONFIG
,
226 MII_BASIC_CONFIG_RGMII
);
227 nxp_c45_disable_delays(phydev
);
229 case PHY_INTERFACE_MODE_RGMII_ID
:
230 case PHY_INTERFACE_MODE_RGMII_TXID
:
231 case PHY_INTERFACE_MODE_RGMII_RXID
:
232 if (!(ret
& RGMII_ID_ABILITY
)) {
233 pr_err("%s: rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n",
237 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_MII_BASIC_CONFIG
,
238 MII_BASIC_CONFIG_RGMII
);
239 ret
= nxp_c45_get_delays(phydev
);
243 nxp_c45_set_delays(phydev
);
245 case PHY_INTERFACE_MODE_MII
:
246 if (!(ret
& MII_ABILITY
)) {
247 pr_err("%s: mii mode not supported\n",
251 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_MII_BASIC_CONFIG
,
252 MII_BASIC_CONFIG_MII
);
254 case PHY_INTERFACE_MODE_RMII
:
255 if (!(ret
& RMII_ABILITY
)) {
256 pr_err("%s: rmii mode not supported\n",
260 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_MII_BASIC_CONFIG
,
261 MII_BASIC_CONFIG_RMII
);
263 case PHY_INTERFACE_MODE_SGMII
:
264 if (!(ret
& SGMII_ABILITY
)) {
265 pr_err("%s: sgmii mode not supported\n",
269 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_MII_BASIC_CONFIG
,
270 MII_BASIC_CONFIG_SGMII
);
272 case PHY_INTERFACE_MODE_INTERNAL
:
281 static int nxp_c45_config(struct phy_device
*phydev
)
285 ret
= nxp_c45_soft_reset(phydev
);
289 ret
= nxp_c45_config_enable(phydev
);
291 pr_err("%s: Failed to enable config\n", phydev
->drv
->name
);
295 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_PHY_CONFIG
,
298 ret
= nxp_c45_set_phy_mode(phydev
);
300 pr_err("%s: Failed to set phy mode\n", phydev
->drv
->name
);
304 phydev
->autoneg
= AUTONEG_DISABLE
;
306 return nxp_c45_start_op(phydev
);
309 static int nxp_c45_startup(struct phy_device
*phydev
)
313 reg
= phy_read_mmd(phydev
, MDIO_MMD_PMAPMD
, MDIO_STAT1
);
314 phydev
->link
= !!(reg
& MDIO_STAT1_LSTATUS
);
315 phydev
->speed
= SPEED_100
;
316 phydev
->duplex
= DUPLEX_FULL
;
320 static int nxp_c45_probe(struct phy_device
*phydev
)
322 struct nxp_c45_phy
*priv
;
324 priv
= devm_kzalloc(phydev
->priv
, sizeof(*priv
), GFP_KERNEL
);
333 U_BOOT_PHY_DRIVER(nxp_c45_tja11xx
) = {
334 .name
= "NXP C45 TJA1103",
335 .uid
= PHY_ID_TJA_1103
,
337 .features
= PHY_100BT1_FEATURES
,
338 .probe
= &nxp_c45_probe
,
339 .config
= &nxp_c45_config
,
340 .startup
= &nxp_c45_startup
,
341 .shutdown
= &genphy_shutdown
,