brintos

brintos / linux-shallow public Read only

0
0
Text · 22.1 KiB · 3ab64e0 Raw
843 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Driver for the Texas Instruments DP83822, DP83825 and DP83826 PHYs.3 *4 * Copyright (C) 2017 Texas Instruments Inc.5 */6 7#include <linux/ethtool.h>8#include <linux/etherdevice.h>9#include <linux/kernel.h>10#include <linux/mii.h>11#include <linux/module.h>12#include <linux/of.h>13#include <linux/phy.h>14#include <linux/netdevice.h>15#include <linux/bitfield.h>16 17#define DP83822_PHY_ID	        0x2000a24018#define DP83825S_PHY_ID		0x2000a14019#define DP83825I_PHY_ID		0x2000a15020#define DP83825CM_PHY_ID	0x2000a16021#define DP83825CS_PHY_ID	0x2000a17022#define DP83826C_PHY_ID		0x2000a13023#define DP83826NC_PHY_ID	0x2000a11024 25#define DP83822_DEVADDR		0x1f26 27#define MII_DP83822_CTRL_2	0x0a28#define MII_DP83822_PHYSTS	0x1029#define MII_DP83822_PHYSCR	0x1130#define MII_DP83822_MISR1	0x1231#define MII_DP83822_MISR2	0x1332#define MII_DP83822_FCSCR	0x1433#define MII_DP83822_RCSR	0x1734#define MII_DP83822_RESET_CTRL	0x1f35#define MII_DP83822_GENCFG	0x46536#define MII_DP83822_SOR1	0x46737 38/* DP83826 specific registers */39#define MII_DP83826_VOD_CFG1	0x30b40#define MII_DP83826_VOD_CFG2	0x30c41 42/* GENCFG */43#define DP83822_SIG_DET_LOW	BIT(0)44 45/* Control Register 2 bits */46#define DP83822_FX_ENABLE	BIT(14)47 48#define DP83822_SW_RESET	BIT(15)49#define DP83822_DIG_RESTART	BIT(14)50 51/* PHY STS bits */52#define DP83822_PHYSTS_DUPLEX			BIT(2)53#define DP83822_PHYSTS_10			BIT(1)54#define DP83822_PHYSTS_LINK			BIT(0)55 56/* PHYSCR Register Fields */57#define DP83822_PHYSCR_INT_OE		BIT(0) /* Interrupt Output Enable */58#define DP83822_PHYSCR_INTEN		BIT(1) /* Interrupt Enable */59 60/* MISR1 bits */61#define DP83822_RX_ERR_HF_INT_EN	BIT(0)62#define DP83822_FALSE_CARRIER_HF_INT_EN	BIT(1)63#define DP83822_ANEG_COMPLETE_INT_EN	BIT(2)64#define DP83822_DUP_MODE_CHANGE_INT_EN	BIT(3)65#define DP83822_SPEED_CHANGED_INT_EN	BIT(4)66#define DP83822_LINK_STAT_INT_EN	BIT(5)67#define DP83822_ENERGY_DET_INT_EN	BIT(6)68#define DP83822_LINK_QUAL_INT_EN	BIT(7)69 70/* MISR2 bits */71#define DP83822_JABBER_DET_INT_EN	BIT(0)72#define DP83822_WOL_PKT_INT_EN		BIT(1)73#define DP83822_SLEEP_MODE_INT_EN	BIT(2)74#define DP83822_MDI_XOVER_INT_EN	BIT(3)75#define DP83822_LB_FIFO_INT_EN		BIT(4)76#define DP83822_PAGE_RX_INT_EN		BIT(5)77#define DP83822_ANEG_ERR_INT_EN		BIT(6)78#define DP83822_EEE_ERROR_CHANGE_INT_EN	BIT(7)79 80/* INT_STAT1 bits */81#define DP83822_WOL_INT_EN	BIT(4)82#define DP83822_WOL_INT_STAT	BIT(12)83 84#define MII_DP83822_RXSOP1	0x04a585#define	MII_DP83822_RXSOP2	0x04a686#define	MII_DP83822_RXSOP3	0x04a787 88/* WoL Registers */89#define	MII_DP83822_WOL_CFG	0x04a090#define	MII_DP83822_WOL_STAT	0x04a191#define	MII_DP83822_WOL_DA1	0x04a292#define	MII_DP83822_WOL_DA2	0x04a393#define	MII_DP83822_WOL_DA3	0x04a494 95/* WoL bits */96#define DP83822_WOL_MAGIC_EN	BIT(0)97#define DP83822_WOL_SECURE_ON	BIT(5)98#define DP83822_WOL_EN		BIT(7)99#define DP83822_WOL_INDICATION_SEL BIT(8)100#define DP83822_WOL_CLR_INDICATION BIT(11)101 102/* RCSR bits */103#define DP83822_RMII_MODE_EN	BIT(5)104#define DP83822_RMII_MODE_SEL	BIT(7)105#define DP83822_RGMII_MODE_EN	BIT(9)106#define DP83822_RX_CLK_SHIFT	BIT(12)107#define DP83822_TX_CLK_SHIFT	BIT(11)108 109/* SOR1 mode */110#define DP83822_STRAP_MODE1	0111#define DP83822_STRAP_MODE2	BIT(0)112#define DP83822_STRAP_MODE3	BIT(1)113#define DP83822_STRAP_MODE4	GENMASK(1, 0)114 115#define DP83822_COL_STRAP_MASK	GENMASK(11, 10)116#define DP83822_COL_SHIFT	10117#define DP83822_RX_ER_STR_MASK	GENMASK(9, 8)118#define DP83822_RX_ER_SHIFT	8119 120/* DP83826: VOD_CFG1 & VOD_CFG2 */121#define DP83826_VOD_CFG1_MINUS_MDIX_MASK	GENMASK(13, 12)122#define DP83826_VOD_CFG1_MINUS_MDI_MASK		GENMASK(11, 6)123#define DP83826_VOD_CFG2_MINUS_MDIX_MASK	GENMASK(15, 12)124#define DP83826_VOD_CFG2_PLUS_MDIX_MASK		GENMASK(11, 6)125#define DP83826_VOD_CFG2_PLUS_MDI_MASK		GENMASK(5, 0)126#define DP83826_CFG_DAC_MINUS_MDIX_5_TO_4	GENMASK(5, 4)127#define DP83826_CFG_DAC_MINUS_MDIX_3_TO_0	GENMASK(3, 0)128#define DP83826_CFG_DAC_PERCENT_PER_STEP	625129#define DP83826_CFG_DAC_PERCENT_DEFAULT		10000130#define DP83826_CFG_DAC_MINUS_DEFAULT		0x30131#define DP83826_CFG_DAC_PLUS_DEFAULT		0x10132 133#define MII_DP83822_FIBER_ADVERTISE    (ADVERTISED_TP | ADVERTISED_MII | \134					ADVERTISED_FIBRE | \135					ADVERTISED_Pause | ADVERTISED_Asym_Pause)136 137struct dp83822_private {138	bool fx_signal_det_low;139	int fx_enabled;140	u16 fx_sd_enable;141	u8 cfg_dac_minus;142	u8 cfg_dac_plus;143	struct ethtool_wolinfo wol;144};145 146static int dp83822_config_wol(struct phy_device *phydev,147			      struct ethtool_wolinfo *wol)148{149	struct net_device *ndev = phydev->attached_dev;150	u16 value;151	const u8 *mac;152 153	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {154		mac = (const u8 *)ndev->dev_addr;155 156		if (!is_valid_ether_addr(mac))157			return -EINVAL;158 159		/* MAC addresses start with byte 5, but stored in mac[0].160		 * 822 PHYs store bytes 4|5, 2|3, 0|1161		 */162		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1,163			      (mac[1] << 8) | mac[0]);164		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2,165			      (mac[3] << 8) | mac[2]);166		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3,167			      (mac[5] << 8) | mac[4]);168 169		value = phy_read_mmd(phydev, DP83822_DEVADDR,170				     MII_DP83822_WOL_CFG);171		if (wol->wolopts & WAKE_MAGIC)172			value |= DP83822_WOL_MAGIC_EN;173		else174			value &= ~DP83822_WOL_MAGIC_EN;175 176		if (wol->wolopts & WAKE_MAGICSECURE) {177			phy_write_mmd(phydev, DP83822_DEVADDR,178				      MII_DP83822_RXSOP1,179				      (wol->sopass[1] << 8) | wol->sopass[0]);180			phy_write_mmd(phydev, DP83822_DEVADDR,181				      MII_DP83822_RXSOP2,182				      (wol->sopass[3] << 8) | wol->sopass[2]);183			phy_write_mmd(phydev, DP83822_DEVADDR,184				      MII_DP83822_RXSOP3,185				      (wol->sopass[5] << 8) | wol->sopass[4]);186			value |= DP83822_WOL_SECURE_ON;187		} else {188			value &= ~DP83822_WOL_SECURE_ON;189		}190 191		/* Clear any pending WoL interrupt */192		phy_read(phydev, MII_DP83822_MISR2);193 194		value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |195			 DP83822_WOL_CLR_INDICATION;196 197		return phy_write_mmd(phydev, DP83822_DEVADDR,198				     MII_DP83822_WOL_CFG, value);199	} else {200		return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,201					  MII_DP83822_WOL_CFG,202					  DP83822_WOL_EN |203					  DP83822_WOL_MAGIC_EN |204					  DP83822_WOL_SECURE_ON);205	}206}207 208static int dp83822_set_wol(struct phy_device *phydev,209			   struct ethtool_wolinfo *wol)210{211	struct dp83822_private *dp83822 = phydev->priv;212	int ret;213 214	ret = dp83822_config_wol(phydev, wol);215	if (!ret)216		memcpy(&dp83822->wol, wol, sizeof(*wol));217	return ret;218}219 220static void dp83822_get_wol(struct phy_device *phydev,221			    struct ethtool_wolinfo *wol)222{223	int value;224	u16 sopass_val;225 226	wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE);227	wol->wolopts = 0;228 229	value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);230 231	if (value & DP83822_WOL_MAGIC_EN)232		wol->wolopts |= WAKE_MAGIC;233 234	if (value & DP83822_WOL_SECURE_ON) {235		sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,236					  MII_DP83822_RXSOP1);237		wol->sopass[0] = (sopass_val & 0xff);238		wol->sopass[1] = (sopass_val >> 8);239 240		sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,241					  MII_DP83822_RXSOP2);242		wol->sopass[2] = (sopass_val & 0xff);243		wol->sopass[3] = (sopass_val >> 8);244 245		sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,246					  MII_DP83822_RXSOP3);247		wol->sopass[4] = (sopass_val & 0xff);248		wol->sopass[5] = (sopass_val >> 8);249 250		wol->wolopts |= WAKE_MAGICSECURE;251	}252 253	/* WoL is not enabled so set wolopts to 0 */254	if (!(value & DP83822_WOL_EN))255		wol->wolopts = 0;256}257 258static int dp83822_config_intr(struct phy_device *phydev)259{260	struct dp83822_private *dp83822 = phydev->priv;261	int misr_status;262	int physcr_status;263	int err;264 265	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {266		misr_status = phy_read(phydev, MII_DP83822_MISR1);267		if (misr_status < 0)268			return misr_status;269 270		misr_status |= (DP83822_LINK_STAT_INT_EN |271				DP83822_ENERGY_DET_INT_EN |272				DP83822_LINK_QUAL_INT_EN);273 274		if (!dp83822->fx_enabled)275			misr_status |= DP83822_ANEG_COMPLETE_INT_EN |276				       DP83822_DUP_MODE_CHANGE_INT_EN |277				       DP83822_SPEED_CHANGED_INT_EN;278 279 280		err = phy_write(phydev, MII_DP83822_MISR1, misr_status);281		if (err < 0)282			return err;283 284		misr_status = phy_read(phydev, MII_DP83822_MISR2);285		if (misr_status < 0)286			return misr_status;287 288		misr_status |= (DP83822_JABBER_DET_INT_EN |289				DP83822_SLEEP_MODE_INT_EN |290				DP83822_LB_FIFO_INT_EN |291				DP83822_PAGE_RX_INT_EN |292				DP83822_EEE_ERROR_CHANGE_INT_EN);293 294		if (!dp83822->fx_enabled)295			misr_status |= DP83822_ANEG_ERR_INT_EN |296				       DP83822_WOL_PKT_INT_EN;297 298		err = phy_write(phydev, MII_DP83822_MISR2, misr_status);299		if (err < 0)300			return err;301 302		physcr_status = phy_read(phydev, MII_DP83822_PHYSCR);303		if (physcr_status < 0)304			return physcr_status;305 306		physcr_status |= DP83822_PHYSCR_INT_OE | DP83822_PHYSCR_INTEN;307 308	} else {309		err = phy_write(phydev, MII_DP83822_MISR1, 0);310		if (err < 0)311			return err;312 313		err = phy_write(phydev, MII_DP83822_MISR2, 0);314		if (err < 0)315			return err;316 317		physcr_status = phy_read(phydev, MII_DP83822_PHYSCR);318		if (physcr_status < 0)319			return physcr_status;320 321		physcr_status &= ~DP83822_PHYSCR_INTEN;322	}323 324	return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status);325}326 327static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)328{329	bool trigger_machine = false;330	int irq_status;331 332	/* The MISR1 and MISR2 registers are holding the interrupt status in333	 * the upper half (15:8), while the lower half (7:0) is used for334	 * controlling the interrupt enable state of those individual interrupt335	 * sources. To determine the possible interrupt sources, just read the336	 * MISR* register and use it directly to know which interrupts have337	 * been enabled previously or not.338	 */339	irq_status = phy_read(phydev, MII_DP83822_MISR1);340	if (irq_status < 0) {341		phy_error(phydev);342		return IRQ_NONE;343	}344	if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))345		trigger_machine = true;346 347	irq_status = phy_read(phydev, MII_DP83822_MISR2);348	if (irq_status < 0) {349		phy_error(phydev);350		return IRQ_NONE;351	}352	if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))353		trigger_machine = true;354 355	if (!trigger_machine)356		return IRQ_NONE;357 358	phy_trigger_machine(phydev);359 360	return IRQ_HANDLED;361}362 363static int dp83822_read_status(struct phy_device *phydev)364{365	struct dp83822_private *dp83822 = phydev->priv;366	int status = phy_read(phydev, MII_DP83822_PHYSTS);367	int ctrl2;368	int ret;369 370	if (dp83822->fx_enabled) {371		if (status & DP83822_PHYSTS_LINK) {372			phydev->speed = SPEED_UNKNOWN;373			phydev->duplex = DUPLEX_UNKNOWN;374		} else {375			ctrl2 = phy_read(phydev, MII_DP83822_CTRL_2);376			if (ctrl2 < 0)377				return ctrl2;378 379			if (!(ctrl2 & DP83822_FX_ENABLE)) {380				ret = phy_write(phydev, MII_DP83822_CTRL_2,381						DP83822_FX_ENABLE | ctrl2);382				if (ret < 0)383					return ret;384			}385		}386	}387 388	ret = genphy_read_status(phydev);389	if (ret)390		return ret;391 392	if (status < 0)393		return status;394 395	if (status & DP83822_PHYSTS_DUPLEX)396		phydev->duplex = DUPLEX_FULL;397	else398		phydev->duplex = DUPLEX_HALF;399 400	if (status & DP83822_PHYSTS_10)401		phydev->speed = SPEED_10;402	else403		phydev->speed = SPEED_100;404 405	return 0;406}407 408static int dp83822_config_init(struct phy_device *phydev)409{410	struct dp83822_private *dp83822 = phydev->priv;411	struct device *dev = &phydev->mdio.dev;412	int rgmii_delay = 0;413	s32 rx_int_delay;414	s32 tx_int_delay;415	int err = 0;416	int bmcr;417 418	if (phy_interface_is_rgmii(phydev)) {419		rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,420						      true);421 422		/* Set DP83822_RX_CLK_SHIFT to enable rx clk internal delay */423		if (rx_int_delay > 0)424			rgmii_delay |= DP83822_RX_CLK_SHIFT;425 426		tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,427						      false);428 429		/* Set DP83822_TX_CLK_SHIFT to disable tx clk internal delay */430		if (tx_int_delay <= 0)431			rgmii_delay |= DP83822_TX_CLK_SHIFT;432 433		err = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,434				     DP83822_RX_CLK_SHIFT | DP83822_TX_CLK_SHIFT, rgmii_delay);435		if (err)436			return err;437 438		err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,439				       MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);440 441		if (err)442			return err;443	} else {444		err = phy_clear_bits_mmd(phydev, DP83822_DEVADDR,445					 MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);446 447		if (err)448			return err;449	}450 451	if (dp83822->fx_enabled) {452		err = phy_modify(phydev, MII_DP83822_CTRL_2,453				 DP83822_FX_ENABLE, 1);454		if (err < 0)455			return err;456 457		/* Only allow advertising what this PHY supports */458		linkmode_and(phydev->advertising, phydev->advertising,459			     phydev->supported);460 461		linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,462				 phydev->supported);463		linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,464				 phydev->advertising);465		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,466				 phydev->supported);467		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,468				 phydev->supported);469		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,470				 phydev->advertising);471		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,472				 phydev->advertising);473 474		/* Auto neg is not supported in fiber mode */475		bmcr = phy_read(phydev, MII_BMCR);476		if (bmcr < 0)477			return bmcr;478 479		if (bmcr & BMCR_ANENABLE) {480			err =  phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);481			if (err < 0)482				return err;483		}484		phydev->autoneg = AUTONEG_DISABLE;485		linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,486				   phydev->supported);487		linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,488				   phydev->advertising);489 490		/* Setup fiber advertisement */491		err = phy_modify_changed(phydev, MII_ADVERTISE,492					 MII_DP83822_FIBER_ADVERTISE,493					 MII_DP83822_FIBER_ADVERTISE);494 495		if (err < 0)496			return err;497 498		if (dp83822->fx_signal_det_low) {499			err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,500					       MII_DP83822_GENCFG,501					       DP83822_SIG_DET_LOW);502			if (err)503				return err;504		}505	}506	return dp83822_config_wol(phydev, &dp83822->wol);507}508 509static int dp83826_config_rmii_mode(struct phy_device *phydev)510{511	struct device *dev = &phydev->mdio.dev;512	const char *of_val;513	int ret;514 515	if (!device_property_read_string(dev, "ti,rmii-mode", &of_val)) {516		if (strcmp(of_val, "master") == 0) {517			ret = phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,518						 DP83822_RMII_MODE_SEL);519		} else if (strcmp(of_val, "slave") == 0) {520			ret = phy_set_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,521					       DP83822_RMII_MODE_SEL);522		} else {523			phydev_err(phydev, "Invalid value for ti,rmii-mode property (%s)\n",524				   of_val);525			ret = -EINVAL;526		}527 528		if (ret)529			return ret;530	}531 532	return 0;533}534 535static int dp83826_config_init(struct phy_device *phydev)536{537	struct dp83822_private *dp83822 = phydev->priv;538	u16 val, mask;539	int ret;540 541	if (phydev->interface == PHY_INTERFACE_MODE_RMII) {542		ret = phy_set_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,543				       DP83822_RMII_MODE_EN);544		if (ret)545			return ret;546 547		ret = dp83826_config_rmii_mode(phydev);548		if (ret)549			return ret;550	} else {551		ret = phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,552					 DP83822_RMII_MODE_EN);553		if (ret)554			return ret;555	}556 557	if (dp83822->cfg_dac_minus != DP83826_CFG_DAC_MINUS_DEFAULT) {558		val = FIELD_PREP(DP83826_VOD_CFG1_MINUS_MDI_MASK, dp83822->cfg_dac_minus) |559		      FIELD_PREP(DP83826_VOD_CFG1_MINUS_MDIX_MASK,560				 FIELD_GET(DP83826_CFG_DAC_MINUS_MDIX_5_TO_4,561					   dp83822->cfg_dac_minus));562		mask = DP83826_VOD_CFG1_MINUS_MDIX_MASK | DP83826_VOD_CFG1_MINUS_MDI_MASK;563		ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG1, mask, val);564		if (ret)565			return ret;566 567		val = FIELD_PREP(DP83826_VOD_CFG2_MINUS_MDIX_MASK,568				 FIELD_GET(DP83826_CFG_DAC_MINUS_MDIX_3_TO_0,569					   dp83822->cfg_dac_minus));570		mask = DP83826_VOD_CFG2_MINUS_MDIX_MASK;571		ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG2, mask, val);572		if (ret)573			return ret;574	}575 576	if (dp83822->cfg_dac_plus != DP83826_CFG_DAC_PLUS_DEFAULT) {577		val = FIELD_PREP(DP83826_VOD_CFG2_PLUS_MDIX_MASK, dp83822->cfg_dac_plus) |578		      FIELD_PREP(DP83826_VOD_CFG2_PLUS_MDI_MASK, dp83822->cfg_dac_plus);579		mask = DP83826_VOD_CFG2_PLUS_MDIX_MASK | DP83826_VOD_CFG2_PLUS_MDI_MASK;580		ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG2, mask, val);581		if (ret)582			return ret;583	}584 585	return dp83822_config_wol(phydev, &dp83822->wol);586}587 588static int dp8382x_config_init(struct phy_device *phydev)589{590	struct dp83822_private *dp83822 = phydev->priv;591 592	return dp83822_config_wol(phydev, &dp83822->wol);593}594 595static int dp83822_phy_reset(struct phy_device *phydev)596{597	int err;598 599	err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_SW_RESET);600	if (err < 0)601		return err;602 603	return phydev->drv->config_init(phydev);604}605 606#ifdef CONFIG_OF_MDIO607static int dp83822_of_init(struct phy_device *phydev)608{609	struct dp83822_private *dp83822 = phydev->priv;610	struct device *dev = &phydev->mdio.dev;611 612	/* Signal detection for the PHY is only enabled if the FX_EN and the613	 * SD_EN pins are strapped. Signal detection can only enabled if FX_EN614	 * is strapped otherwise signal detection is disabled for the PHY.615	 */616	if (dp83822->fx_enabled && dp83822->fx_sd_enable)617		dp83822->fx_signal_det_low = device_property_present(dev,618								     "ti,link-loss-low");619	if (!dp83822->fx_enabled)620		dp83822->fx_enabled = device_property_present(dev,621							      "ti,fiber-mode");622 623	return 0;624}625 626static int dp83826_to_dac_minus_one_regval(int percent)627{628	int tmp = DP83826_CFG_DAC_PERCENT_DEFAULT - percent;629 630	return tmp / DP83826_CFG_DAC_PERCENT_PER_STEP;631}632 633static int dp83826_to_dac_plus_one_regval(int percent)634{635	int tmp = percent - DP83826_CFG_DAC_PERCENT_DEFAULT;636 637	return tmp / DP83826_CFG_DAC_PERCENT_PER_STEP;638}639 640static void dp83826_of_init(struct phy_device *phydev)641{642	struct dp83822_private *dp83822 = phydev->priv;643	struct device *dev = &phydev->mdio.dev;644	u32 val;645 646	dp83822->cfg_dac_minus = DP83826_CFG_DAC_MINUS_DEFAULT;647	if (!device_property_read_u32(dev, "ti,cfg-dac-minus-one-bp", &val))648		dp83822->cfg_dac_minus += dp83826_to_dac_minus_one_regval(val);649 650	dp83822->cfg_dac_plus = DP83826_CFG_DAC_PLUS_DEFAULT;651	if (!device_property_read_u32(dev, "ti,cfg-dac-plus-one-bp", &val))652		dp83822->cfg_dac_plus += dp83826_to_dac_plus_one_regval(val);653}654#else655static int dp83822_of_init(struct phy_device *phydev)656{657	return 0;658}659 660static void dp83826_of_init(struct phy_device *phydev)661{662}663#endif /* CONFIG_OF_MDIO */664 665static int dp83822_read_straps(struct phy_device *phydev)666{667	struct dp83822_private *dp83822 = phydev->priv;668	int fx_enabled, fx_sd_enable;669	int val;670 671	val = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_SOR1);672	if (val < 0)673		return val;674 675	phydev_dbg(phydev, "SOR1 strap register: 0x%04x\n", val);676 677	fx_enabled = (val & DP83822_COL_STRAP_MASK) >> DP83822_COL_SHIFT;678	if (fx_enabled == DP83822_STRAP_MODE2 ||679	    fx_enabled == DP83822_STRAP_MODE3)680		dp83822->fx_enabled = 1;681 682	if (dp83822->fx_enabled) {683		fx_sd_enable = (val & DP83822_RX_ER_STR_MASK) >> DP83822_RX_ER_SHIFT;684		if (fx_sd_enable == DP83822_STRAP_MODE3 ||685		    fx_sd_enable == DP83822_STRAP_MODE4)686			dp83822->fx_sd_enable = 1;687	}688 689	return 0;690}691 692static int dp8382x_probe(struct phy_device *phydev)693{694	struct dp83822_private *dp83822;695 696	dp83822 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83822),697			       GFP_KERNEL);698	if (!dp83822)699		return -ENOMEM;700 701	phydev->priv = dp83822;702 703	return 0;704}705 706static int dp83822_probe(struct phy_device *phydev)707{708	struct dp83822_private *dp83822;709	int ret;710 711	ret = dp8382x_probe(phydev);712	if (ret)713		return ret;714 715	dp83822 = phydev->priv;716 717	ret = dp83822_read_straps(phydev);718	if (ret)719		return ret;720 721	dp83822_of_init(phydev);722 723	if (dp83822->fx_enabled)724		phydev->port = PORT_FIBRE;725 726	return 0;727}728 729static int dp83826_probe(struct phy_device *phydev)730{731	int ret;732 733	ret = dp8382x_probe(phydev);734	if (ret)735		return ret;736 737	dp83826_of_init(phydev);738 739	return 0;740}741 742static int dp83822_suspend(struct phy_device *phydev)743{744	int value;745 746	value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);747 748	if (!(value & DP83822_WOL_EN))749		genphy_suspend(phydev);750 751	return 0;752}753 754static int dp83822_resume(struct phy_device *phydev)755{756	int value;757 758	genphy_resume(phydev);759 760	value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);761 762	phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value |763		      DP83822_WOL_CLR_INDICATION);764 765	return 0;766}767 768#define DP83822_PHY_DRIVER(_id, _name)				\769	{							\770		PHY_ID_MATCH_MODEL(_id),			\771		.name		= (_name),			\772		/* PHY_BASIC_FEATURES */			\773		.probe          = dp83822_probe,		\774		.soft_reset	= dp83822_phy_reset,		\775		.config_init	= dp83822_config_init,		\776		.read_status	= dp83822_read_status,		\777		.get_wol = dp83822_get_wol,			\778		.set_wol = dp83822_set_wol,			\779		.config_intr = dp83822_config_intr,		\780		.handle_interrupt = dp83822_handle_interrupt,	\781		.suspend = dp83822_suspend,			\782		.resume = dp83822_resume,			\783	}784 785#define DP83826_PHY_DRIVER(_id, _name)				\786	{							\787		PHY_ID_MATCH_MODEL(_id),			\788		.name		= (_name),			\789		/* PHY_BASIC_FEATURES */			\790		.probe          = dp83826_probe,		\791		.soft_reset	= dp83822_phy_reset,		\792		.config_init	= dp83826_config_init,		\793		.get_wol = dp83822_get_wol,			\794		.set_wol = dp83822_set_wol,			\795		.config_intr = dp83822_config_intr,		\796		.handle_interrupt = dp83822_handle_interrupt,	\797		.suspend = dp83822_suspend,			\798		.resume = dp83822_resume,			\799	}800 801#define DP8382X_PHY_DRIVER(_id, _name)				\802	{							\803		PHY_ID_MATCH_MODEL(_id),			\804		.name		= (_name),			\805		/* PHY_BASIC_FEATURES */			\806		.probe          = dp8382x_probe,		\807		.soft_reset	= dp83822_phy_reset,		\808		.config_init	= dp8382x_config_init,		\809		.get_wol = dp83822_get_wol,			\810		.set_wol = dp83822_set_wol,			\811		.config_intr = dp83822_config_intr,		\812		.handle_interrupt = dp83822_handle_interrupt,	\813		.suspend = dp83822_suspend,			\814		.resume = dp83822_resume,			\815	}816 817static struct phy_driver dp83822_driver[] = {818	DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"),819	DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),820	DP83826_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),821	DP83826_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),822	DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),823	DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),824	DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),825};826module_phy_driver(dp83822_driver);827 828static struct mdio_device_id __maybe_unused dp83822_tbl[] = {829	{ DP83822_PHY_ID, 0xfffffff0 },830	{ DP83825I_PHY_ID, 0xfffffff0 },831	{ DP83826C_PHY_ID, 0xfffffff0 },832	{ DP83826NC_PHY_ID, 0xfffffff0 },833	{ DP83825S_PHY_ID, 0xfffffff0 },834	{ DP83825CM_PHY_ID, 0xfffffff0 },835	{ DP83825CS_PHY_ID, 0xfffffff0 },836	{ },837};838MODULE_DEVICE_TABLE(mdio, dp83822_tbl);839 840MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver");841MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");842MODULE_LICENSE("GPL v2");843