blob: b6726031ebb8f13a43ee16c658cbcae1089cb5f6 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -07002/*
3 * TI PHY drivers
4 *
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -07005 */
Tom Riniabb9a042024-05-18 20:20:43 -06006#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -07008#include <phy.h>
Simon Glassd66c5f72020-02-03 07:36:15 -07009#include <dm/devres.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060010#include <linux/bitops.h>
Dan Murphy83fbd0a2016-05-02 15:45:59 -050011#include <linux/compat.h>
12#include <malloc.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060013#include <linux/printk.h>
Dan Murphy83fbd0a2016-05-02 15:45:59 -050014
Dan Murphy83fbd0a2016-05-02 15:45:59 -050015#include <dm.h>
16#include <dt-bindings/net/ti-dp83867.h>
17
Dan Murphy8b8d73a2020-05-04 16:14:39 -050018#include "ti_phy_init.h"
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070019
20/* TI DP83867 */
21#define DP83867_DEVADDR 0x1f
22
23#define MII_DP83867_PHYCTRL 0x10
24#define MII_DP83867_MICR 0x12
Siva Durga Prasad Paladugu02c7be62016-03-25 12:53:43 +053025#define MII_DP83867_CFG2 0x14
26#define MII_DP83867_BISCR 0x16
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070027#define DP83867_CTRL 0x1f
28
29/* Extended Registers */
Murali Karicheri9b050762018-06-28 14:26:34 -050030#define DP83867_CFG4 0x0031
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070031#define DP83867_RGMIICTL 0x0032
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +020032#define DP83867_STRAP_STS1 0x006E
Grygorii Strashko5b2742c2019-11-18 23:04:44 +020033#define DP83867_STRAP_STS2 0x006f
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070034#define DP83867_RGMIIDCTL 0x0086
Mugunthan V N5b6b18e2017-01-24 11:15:40 -060035#define DP83867_IO_MUX_CFG 0x0170
Michal Simeka3a34702020-02-18 13:51:02 +010036#define DP83867_SGMIICTL 0x00D3
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070037
38#define DP83867_SW_RESET BIT(15)
39#define DP83867_SW_RESTART BIT(14)
40
41/* MICR Interrupt bits */
42#define MII_DP83867_MICR_AN_ERR_INT_EN BIT(15)
43#define MII_DP83867_MICR_SPEED_CHNG_INT_EN BIT(14)
44#define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN BIT(13)
45#define MII_DP83867_MICR_PAGE_RXD_INT_EN BIT(12)
46#define MII_DP83867_MICR_AUTONEG_COMP_INT_EN BIT(11)
47#define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN BIT(10)
48#define MII_DP83867_MICR_FALSE_CARRIER_INT_EN BIT(8)
49#define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN BIT(4)
50#define MII_DP83867_MICR_WOL_INT_EN BIT(3)
51#define MII_DP83867_MICR_XGMII_ERR_INT_EN BIT(2)
52#define MII_DP83867_MICR_POL_CHNG_INT_EN BIT(1)
53#define MII_DP83867_MICR_JABBER_INT_EN BIT(0)
54
55/* RGMIICTL bits */
56#define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1)
57#define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0)
58
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +020059/* STRAP_STS1 bits */
60#define DP83867_STRAP_STS1_RESERVED BIT(11)
61
Grygorii Strashko5b2742c2019-11-18 23:04:44 +020062/* STRAP_STS2 bits */
63#define DP83867_STRAP_STS2_CLK_SKEW_TX_MASK GENMASK(6, 4)
64#define DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT 4
65#define DP83867_STRAP_STS2_CLK_SKEW_RX_MASK GENMASK(2, 0)
66#define DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT 0
67#define DP83867_STRAP_STS2_CLK_SKEW_NONE BIT(2)
68
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070069/* PHY CTRL bits */
70#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
Grygorii Strashko78492a22019-11-18 23:04:46 +020071#define DP83867_PHYCR_FIFO_DEPTH_MASK GENMASK(15, 14)
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +020072#define DP83867_PHYCR_RESERVED_MASK BIT(11)
Michal Simekc7f95ed2020-02-06 15:59:23 +010073#define DP83867_PHYCR_FORCE_LINK_GOOD BIT(10)
Michal Simekf6459152015-10-19 10:43:30 +020074#define DP83867_MDI_CROSSOVER 5
Siva Durga Prasad Paladugu02c7be62016-03-25 12:53:43 +053075#define DP83867_MDI_CROSSOVER_MDIX 2
76#define DP83867_PHYCTRL_SGMIIEN 0x0800
77#define DP83867_PHYCTRL_RXFIFO_SHIFT 12
78#define DP83867_PHYCTRL_TXFIFO_SHIFT 14
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070079
80/* RGMIIDCTL bits */
Grygorii Strashko5b2742c2019-11-18 23:04:44 +020081#define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070082#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
Grygorii Strashko5b2742c2019-11-18 23:04:44 +020083#define DP83867_RGMII_RX_CLK_DELAY_MAX 0xf
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -070084
Siva Durga Prasad Paladugu02c7be62016-03-25 12:53:43 +053085/* CFG2 bits */
86#define MII_DP83867_CFG2_SPEEDOPT_10EN 0x0040
87#define MII_DP83867_CFG2_SGMII_AUTONEGEN 0x0080
88#define MII_DP83867_CFG2_SPEEDOPT_ENH 0x0100
89#define MII_DP83867_CFG2_SPEEDOPT_CNT 0x0800
90#define MII_DP83867_CFG2_SPEEDOPT_INTLOW 0x2000
91#define MII_DP83867_CFG2_MASK 0x003F
92
Dan Murphy83fbd0a2016-05-02 15:45:59 -050093/* User setting - can be taken from DTS */
Dan Murphy83fbd0a2016-05-02 15:45:59 -050094#define DEFAULT_FIFO_DEPTH DP83867_PHYCR_FIFO_DEPTH_4_B_NIB
95
Mugunthan V N5b6b18e2017-01-24 11:15:40 -060096/* IO_MUX_CFG bits */
97#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f
98
99#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0
100#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f
Grygorii Strashko1c35b572019-11-18 23:04:43 +0200101#define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6)
Janine Hagemann1c2ba092018-08-28 08:25:39 +0200102#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8
103#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \
104 GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT)
Mugunthan V N5b6b18e2017-01-24 11:15:40 -0600105
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200106/* CFG4 bits */
107#define DP83867_CFG4_PORT_MIRROR_EN BIT(0)
108
Michal Simeka3a34702020-02-18 13:51:02 +0100109/* SGMIICTL bits */
110#define DP83867_SGMII_TYPE BIT(14)
111
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200112enum {
113 DP83867_PORT_MIRRORING_KEEP,
114 DP83867_PORT_MIRRORING_EN,
115 DP83867_PORT_MIRRORING_DIS,
116};
117
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500118struct dp83867_private {
Grygorii Strashko5b2742c2019-11-18 23:04:44 +0200119 u32 rx_id_delay;
120 u32 tx_id_delay;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500121 int fifo_depth;
Mugunthan V N5b6b18e2017-01-24 11:15:40 -0600122 int io_impedance;
Murali Karicheri9b050762018-06-28 14:26:34 -0500123 bool rxctrl_strap_quirk;
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200124 int port_mirroring;
Grygorii Strashko1c35b572019-11-18 23:04:43 +0200125 bool set_clk_output;
Trent Piephob0a86e52019-05-10 17:49:08 +0000126 unsigned int clk_output_sel;
Michal Simeka3a34702020-02-18 13:51:02 +0100127 bool sgmii_ref_clk_en;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500128};
129
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200130static int dp83867_config_port_mirroring(struct phy_device *phydev)
131{
132 struct dp83867_private *dp83867 =
133 (struct dp83867_private *)phydev->priv;
134 u16 val;
135
Carlo Caionea8abcff2019-02-08 17:25:07 +0000136 val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200137
138 if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN)
139 val |= DP83867_CFG4_PORT_MIRROR_EN;
140 else
141 val &= ~DP83867_CFG4_PORT_MIRROR_EN;
142
Carlo Caionea8abcff2019-02-08 17:25:07 +0000143 phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200144
145 return 0;
146}
147
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500148/**
149 * dp83867_data_init - Convenience function for setting PHY specific data
150 *
151 * @phydev: the phy_device struct
152 */
153static int dp83867_of_init(struct phy_device *phydev)
154{
155 struct dp83867_private *dp83867 = phydev->priv;
Grygorii Strashko00e2c242018-07-05 12:02:49 -0500156 ofnode node;
Grygorii Strashko1c35b572019-11-18 23:04:43 +0200157 int ret;
Janine Hagemann1c2ba092018-08-28 08:25:39 +0200158
Michal Simek8e102a82019-03-16 12:43:17 +0100159 node = phy_get_ofnode(phydev);
160 if (!ofnode_valid(node))
Vladimir Oltean9a4ba3d2022-02-23 15:20:55 +0200161 return 0;
Michal Simek8e102a82019-03-16 12:43:17 +0100162
Grygorii Strashko1c35b572019-11-18 23:04:43 +0200163 /* Optional configuration */
164 ret = ofnode_read_u32(node, "ti,clk-output-sel",
165 &dp83867->clk_output_sel);
166 /* If not set, keep default */
167 if (!ret) {
168 dp83867->set_clk_output = true;
169 /* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or
170 * DP83867_CLK_O_SEL_OFF.
171 */
172 if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK &&
173 dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) {
174 pr_debug("ti,clk-output-sel value %u out of range\n",
175 dp83867->clk_output_sel);
176 return -EINVAL;
177 }
178 }
Grygorii Strashko00e2c242018-07-05 12:02:49 -0500179
Grygorii Strashko9df35052018-06-28 14:26:35 -0500180 if (ofnode_read_bool(node, "ti,max-output-impedance"))
Mugunthan V N5b6b18e2017-01-24 11:15:40 -0600181 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
Grygorii Strashko9df35052018-06-28 14:26:35 -0500182 else if (ofnode_read_bool(node, "ti,min-output-impedance"))
Mugunthan V N5b6b18e2017-01-24 11:15:40 -0600183 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
184 else
185 dp83867->io_impedance = -EINVAL;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500186
Grygorii Strashko9df35052018-06-28 14:26:35 -0500187 if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk"))
Murali Karicheri9b050762018-06-28 14:26:34 -0500188 dp83867->rxctrl_strap_quirk = true;
Grygorii Strashko5b2742c2019-11-18 23:04:44 +0200189
190 /* Existing behavior was to use default pin strapping delay in rgmii
191 * mode, but rgmii should have meant no delay. Warn existing users.
192 */
193 if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
194 u16 val = phy_read_mmd(phydev, DP83867_DEVADDR,
195 DP83867_STRAP_STS2);
196 u16 txskew = (val & DP83867_STRAP_STS2_CLK_SKEW_TX_MASK) >>
197 DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT;
198 u16 rxskew = (val & DP83867_STRAP_STS2_CLK_SKEW_RX_MASK) >>
199 DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500200
Grygorii Strashko5b2742c2019-11-18 23:04:44 +0200201 if (txskew != DP83867_STRAP_STS2_CLK_SKEW_NONE ||
202 rxskew != DP83867_STRAP_STS2_CLK_SKEW_NONE)
203 pr_warn("PHY has delays via pin strapping, but phy-mode = 'rgmii'\n"
204 "Should be 'rgmii-id' to use internal delays\n");
205 }
206
207 /* RX delay *must* be specified if internal delay of RX is used. */
208 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
209 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
210 ret = ofnode_read_u32(node, "ti,rx-internal-delay",
211 &dp83867->rx_id_delay);
212 if (ret) {
213 pr_debug("ti,rx-internal-delay must be specified\n");
214 return ret;
215 }
216 if (dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) {
217 pr_debug("ti,rx-internal-delay value of %u out of range\n",
218 dp83867->rx_id_delay);
219 return -EINVAL;
220 }
221 }
222
223 /* TX delay *must* be specified if internal delay of RX is used. */
224 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
225 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
226 ret = ofnode_read_u32(node, "ti,tx-internal-delay",
227 &dp83867->tx_id_delay);
228 if (ret) {
229 debug("ti,tx-internal-delay must be specified\n");
230 return ret;
231 }
232 if (dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) {
233 pr_debug("ti,tx-internal-delay value of %u out of range\n",
234 dp83867->tx_id_delay);
235 return -EINVAL;
236 }
237 }
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500238
Grygorii Strashko9df35052018-06-28 14:26:35 -0500239 dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
Trent Piepho19d7aee2019-05-09 19:41:51 +0000240 DEFAULT_FIFO_DEPTH);
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200241 if (ofnode_read_bool(node, "enet-phy-lane-swap"))
242 dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN;
243
244 if (ofnode_read_bool(node, "enet-phy-lane-no-swap"))
245 dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS;
246
Michal Simeka3a34702020-02-18 13:51:02 +0100247 if (ofnode_read_bool(node, "ti,sgmii-ref-clock-output-enable"))
248 dp83867->sgmii_ref_clk_en = true;
249
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500250 return 0;
251}
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700252
253static int dp83867_config(struct phy_device *phydev)
254{
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500255 struct dp83867_private *dp83867;
Haolin Licf587cf2022-03-19 07:02:42 -0700256 int val, delay, cfg2;
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +0200257 int ret, bs;
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700258
Grygorii Strashko1d8b5522019-11-18 23:04:41 +0200259 dp83867 = (struct dp83867_private *)phydev->priv;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500260
Grygorii Strashko1d8b5522019-11-18 23:04:41 +0200261 ret = dp83867_of_init(phydev);
262 if (ret)
263 return ret;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500264
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700265 /* Restart the PHY. */
266 val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL);
267 phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
268 val | DP83867_SW_RESTART);
269
Murali Karicheri9b050762018-06-28 14:26:34 -0500270 /* Mode 1 or 2 workaround */
271 if (dp83867->rxctrl_strap_quirk) {
Carlo Caionea8abcff2019-02-08 17:25:07 +0000272 val = phy_read_mmd(phydev, DP83867_DEVADDR,
273 DP83867_CFG4);
Murali Karicheri9b050762018-06-28 14:26:34 -0500274 val &= ~BIT(7);
Carlo Caionea8abcff2019-02-08 17:25:07 +0000275 phy_write_mmd(phydev, DP83867_DEVADDR,
276 DP83867_CFG4, val);
Murali Karicheri9b050762018-06-28 14:26:34 -0500277 }
278
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700279 if (phy_interface_is_rgmii(phydev)) {
Grygorii Strashko78492a22019-11-18 23:04:46 +0200280 val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
Haolin Licf587cf2022-03-19 07:02:42 -0700281 if (val < 0) {
282 ret = val;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500283 goto err_out;
Haolin Licf587cf2022-03-19 07:02:42 -0700284 }
285
Grygorii Strashko78492a22019-11-18 23:04:46 +0200286 val &= ~DP83867_PHYCR_FIFO_DEPTH_MASK;
287 val |= (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT);
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +0200288
Michal Simekc7f95ed2020-02-06 15:59:23 +0100289 /* Do not force link good */
290 val &= ~DP83867_PHYCR_FORCE_LINK_GOOD;
291
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +0200292 /* The code below checks if "port mirroring" N/A MODE4 has been
293 * enabled during power on bootstrap.
294 *
295 * Such N/A mode enabled by mistake can put PHY IC in some
296 * internal testing mode and disable RGMII transmission.
297 *
298 * In this particular case one needs to check STRAP_STS1
299 * register's bit 11 (marked as RESERVED).
300 */
301
Grygorii Strashko78492a22019-11-18 23:04:46 +0200302 bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS1);
303 if (bs & DP83867_STRAP_STS1_RESERVED)
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +0200304 val &= ~DP83867_PHYCR_RESERVED_MASK;
Grygorii Strashko78492a22019-11-18 23:04:46 +0200305
306 ret = phy_write(phydev, MDIO_DEVAD_NONE,
307 MII_DP83867_PHYCTRL, val);
308
309 val = phy_read_mmd(phydev, DP83867_DEVADDR,
310 DP83867_RGMIICTL);
311
312 val &= ~(DP83867_RGMII_TX_CLK_DELAY_EN |
313 DP83867_RGMII_RX_CLK_DELAY_EN);
314 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
315 val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
316 DP83867_RGMII_RX_CLK_DELAY_EN);
317
318 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
319 val |= DP83867_RGMII_TX_CLK_DELAY_EN;
320
321 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
322 val |= DP83867_RGMII_RX_CLK_DELAY_EN;
323
324 phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val);
325
326 delay = (dp83867->rx_id_delay |
327 (dp83867->tx_id_delay <<
328 DP83867_RGMII_TX_CLK_DELAY_SHIFT));
329
330 phy_write_mmd(phydev, DP83867_DEVADDR,
331 DP83867_RGMIIDCTL, delay);
332 }
Janine Hagemannb3dd2ed2018-08-28 08:25:38 +0200333
Nishanth Menon21876c22023-04-14 17:06:43 -0500334 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
Michal Simeka3a34702020-02-18 13:51:02 +0100335 if (dp83867->sgmii_ref_clk_en)
336 phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL,
337 DP83867_SGMII_TYPE);
338
Siva Durga Prasad Paladugu02c7be62016-03-25 12:53:43 +0530339 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
340 (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
341
342 cfg2 = phy_read(phydev, phydev->addr, MII_DP83867_CFG2);
343 cfg2 &= MII_DP83867_CFG2_MASK;
344 cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN |
345 MII_DP83867_CFG2_SGMII_AUTONEGEN |
346 MII_DP83867_CFG2_SPEEDOPT_ENH |
347 MII_DP83867_CFG2_SPEEDOPT_CNT |
348 MII_DP83867_CFG2_SPEEDOPT_INTLOW);
349 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG2, cfg2);
350
Carlo Caionea8abcff2019-02-08 17:25:07 +0000351 phy_write_mmd(phydev, DP83867_DEVADDR,
352 DP83867_RGMIICTL, 0x0);
Siva Durga Prasad Paladugu02c7be62016-03-25 12:53:43 +0530353
354 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
355 DP83867_PHYCTRL_SGMIIEN |
356 (DP83867_MDI_CROSSOVER_MDIX <<
357 DP83867_MDI_CROSSOVER) |
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500358 (dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) |
359 (dp83867->fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT));
Siva Durga Prasad Paladugu02c7be62016-03-25 12:53:43 +0530360 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0);
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700361 }
362
Grygorii Strashko38432512019-11-18 23:04:45 +0200363 if (dp83867->io_impedance >= 0) {
364 val = phy_read_mmd(phydev,
365 DP83867_DEVADDR,
366 DP83867_IO_MUX_CFG);
367 val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
368 val |= dp83867->io_impedance &
369 DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
370 phy_write_mmd(phydev, DP83867_DEVADDR,
371 DP83867_IO_MUX_CFG, val);
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700372 }
373
Janine Hagemanned51bfc2018-08-28 08:25:37 +0200374 if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP)
375 dp83867_config_port_mirroring(phydev);
376
Grygorii Strashko1c35b572019-11-18 23:04:43 +0200377 /* Clock output selection if muxing property is set */
378 if (dp83867->set_clk_output) {
379 val = phy_read_mmd(phydev, DP83867_DEVADDR,
380 DP83867_IO_MUX_CFG);
381
382 if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) {
383 val |= DP83867_IO_MUX_CFG_CLK_O_DISABLE;
384 } else {
385 val &= ~(DP83867_IO_MUX_CFG_CLK_O_SEL_MASK |
386 DP83867_IO_MUX_CFG_CLK_O_DISABLE);
387 val |= dp83867->clk_output_sel <<
388 DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT;
389 }
390 phy_write_mmd(phydev, DP83867_DEVADDR,
391 DP83867_IO_MUX_CFG, val);
392 }
393
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700394 genphy_config_aneg(phydev);
395 return 0;
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500396
397err_out:
Dan Murphy83fbd0a2016-05-02 15:45:59 -0500398 return ret;
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700399}
400
Grygorii Strashko1d8b5522019-11-18 23:04:41 +0200401static int dp83867_probe(struct phy_device *phydev)
402{
403 struct dp83867_private *dp83867;
404
405 dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
406 if (!dp83867)
407 return -ENOMEM;
408
409 phydev->priv = dp83867;
410 return 0;
411}
412
Marek Vasut417463c2023-03-19 18:03:04 +0100413U_BOOT_PHY_DRIVER(dp83867) = {
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700414 .name = "TI DP83867",
415 .uid = 0x2000a231,
416 .mask = 0xfffffff0,
417 .features = PHY_GBIT_FEATURES,
Grygorii Strashko1d8b5522019-11-18 23:04:41 +0200418 .probe = dp83867_probe,
Edgar E. Iglesias8d3ce682015-09-25 23:46:08 -0700419 .config = &dp83867_config,
420 .startup = &genphy_startup,
421 .shutdown = &genphy_shutdown,
422};