Skip to content

Commit fee2d54

Browse files
lunndavem330
authored andcommitted
net: phy: marvell: mv88e6390 temperature sensor reading
The internal PHYs in the mv88e6390 switch have a temperature sensor. It uses a different register layout to other PHY currently supported. It also has an errata, in that some reads of the sensor result in bad values. So a number of reads need to be made, and the average taken. Signed-off-by: Andrew Lunn <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0c959a2 commit fee2d54

File tree

1 file changed

+150
-1
lines changed

1 file changed

+150
-1
lines changed

drivers/net/phy/marvell.c

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@
9696
#define MII_88E1510_TEMP_SENSOR 0x1b
9797
#define MII_88E1510_TEMP_SENSOR_MASK 0xff
9898

99+
#define MII_88E6390_MISC_TEST 0x1b
100+
#define MII_88E6390_MISC_TEST_SAMPLE_1S 0
101+
#define MII_88E6390_MISC_TEST_SAMPLE_10MS BIT(14)
102+
#define MII_88E6390_MISC_TEST_SAMPLE_DISABLE BIT(15)
103+
#define MII_88E6390_MISC_TEST_SAMPLE_ENABLE 0
104+
#define MII_88E6390_MISC_TEST_SAMPLE_MASK (0x3 << 14)
105+
106+
#define MII_88E6390_TEMP_SENSOR 0x1c
107+
#define MII_88E6390_TEMP_SENSOR_MASK 0xff
108+
#define MII_88E6390_TEMP_SENSOR_SAMPLES 10
109+
99110
#define MII_88E1318S_PHY_MSCR1_REG 16
100111
#define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
101112

@@ -1738,6 +1749,123 @@ static const struct hwmon_chip_info m88e1510_hwmon_chip_info = {
17381749
.info = m88e1510_hwmon_info,
17391750
};
17401751

1752+
static int m88e6390_get_temp(struct phy_device *phydev, long *temp)
1753+
{
1754+
int sum = 0;
1755+
int oldpage;
1756+
int ret = 0;
1757+
int i;
1758+
1759+
*temp = 0;
1760+
1761+
oldpage = phy_select_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
1762+
if (oldpage < 0)
1763+
goto error;
1764+
1765+
/* Enable temperature sensor */
1766+
ret = __phy_read(phydev, MII_88E6390_MISC_TEST);
1767+
if (ret < 0)
1768+
goto error;
1769+
1770+
ret = ret & ~MII_88E6390_MISC_TEST_SAMPLE_MASK;
1771+
ret |= MII_88E6390_MISC_TEST_SAMPLE_ENABLE |
1772+
MII_88E6390_MISC_TEST_SAMPLE_1S;
1773+
1774+
ret = __phy_write(phydev, MII_88E6390_MISC_TEST, ret);
1775+
if (ret < 0)
1776+
goto error;
1777+
1778+
/* Wait for temperature to stabilize */
1779+
usleep_range(10000, 12000);
1780+
1781+
/* Reading the temperature sense has an errata. You need to read
1782+
* a number of times and take an average.
1783+
*/
1784+
for (i = 0; i < MII_88E6390_TEMP_SENSOR_SAMPLES; i++) {
1785+
ret = __phy_read(phydev, MII_88E6390_TEMP_SENSOR);
1786+
if (ret < 0)
1787+
goto error;
1788+
sum += ret & MII_88E6390_TEMP_SENSOR_MASK;
1789+
}
1790+
1791+
sum /= MII_88E6390_TEMP_SENSOR_SAMPLES;
1792+
*temp = (sum - 75) * 1000;
1793+
1794+
/* Disable temperature sensor */
1795+
ret = __phy_read(phydev, MII_88E6390_MISC_TEST);
1796+
if (ret < 0)
1797+
goto error;
1798+
1799+
ret = ret & ~MII_88E6390_MISC_TEST_SAMPLE_MASK;
1800+
ret |= MII_88E6390_MISC_TEST_SAMPLE_DISABLE;
1801+
1802+
ret = __phy_write(phydev, MII_88E6390_MISC_TEST, ret);
1803+
1804+
error:
1805+
phy_restore_page(phydev, oldpage, ret);
1806+
1807+
return ret;
1808+
}
1809+
1810+
static int m88e6390_hwmon_read(struct device *dev,
1811+
enum hwmon_sensor_types type,
1812+
u32 attr, int channel, long *temp)
1813+
{
1814+
struct phy_device *phydev = dev_get_drvdata(dev);
1815+
int err;
1816+
1817+
switch (attr) {
1818+
case hwmon_temp_input:
1819+
err = m88e6390_get_temp(phydev, temp);
1820+
break;
1821+
default:
1822+
return -EOPNOTSUPP;
1823+
}
1824+
1825+
return err;
1826+
}
1827+
1828+
static umode_t m88e6390_hwmon_is_visible(const void *data,
1829+
enum hwmon_sensor_types type,
1830+
u32 attr, int channel)
1831+
{
1832+
if (type != hwmon_temp)
1833+
return 0;
1834+
1835+
switch (attr) {
1836+
case hwmon_temp_input:
1837+
return 0444;
1838+
default:
1839+
return 0;
1840+
}
1841+
}
1842+
1843+
static u32 m88e6390_hwmon_temp_config[] = {
1844+
HWMON_T_INPUT,
1845+
0
1846+
};
1847+
1848+
static const struct hwmon_channel_info m88e6390_hwmon_temp = {
1849+
.type = hwmon_temp,
1850+
.config = m88e6390_hwmon_temp_config,
1851+
};
1852+
1853+
static const struct hwmon_channel_info *m88e6390_hwmon_info[] = {
1854+
&m88e1121_hwmon_chip,
1855+
&m88e6390_hwmon_temp,
1856+
NULL
1857+
};
1858+
1859+
static const struct hwmon_ops m88e6390_hwmon_hwmon_ops = {
1860+
.is_visible = m88e6390_hwmon_is_visible,
1861+
.read = m88e6390_hwmon_read,
1862+
};
1863+
1864+
static const struct hwmon_chip_info m88e6390_hwmon_chip_info = {
1865+
.ops = &m88e6390_hwmon_hwmon_ops,
1866+
.info = m88e6390_hwmon_info,
1867+
};
1868+
17411869
static int marvell_hwmon_name(struct phy_device *phydev)
17421870
{
17431871
struct marvell_priv *priv = phydev->priv;
@@ -1784,6 +1912,11 @@ static int m88e1510_hwmon_probe(struct phy_device *phydev)
17841912
{
17851913
return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info);
17861914
}
1915+
1916+
static int m88e6390_hwmon_probe(struct phy_device *phydev)
1917+
{
1918+
return marvell_hwmon_probe(phydev, &m88e6390_hwmon_chip_info);
1919+
}
17871920
#else
17881921
static int m88e1121_hwmon_probe(struct phy_device *phydev)
17891922
{
@@ -1794,6 +1927,11 @@ static int m88e1510_hwmon_probe(struct phy_device *phydev)
17941927
{
17951928
return 0;
17961929
}
1930+
1931+
static int m88e6390_hwmon_probe(struct phy_device *phydev)
1932+
{
1933+
return 0;
1934+
}
17971935
#endif
17981936

17991937
static int marvell_probe(struct phy_device *phydev)
@@ -1831,6 +1969,17 @@ static int m88e1510_probe(struct phy_device *phydev)
18311969
return m88e1510_hwmon_probe(phydev);
18321970
}
18331971

1972+
static int m88e6390_probe(struct phy_device *phydev)
1973+
{
1974+
int err;
1975+
1976+
err = marvell_probe(phydev);
1977+
if (err)
1978+
return err;
1979+
1980+
return m88e6390_hwmon_probe(phydev);
1981+
}
1982+
18341983
static struct phy_driver marvell_drivers[] = {
18351984
{
18361985
.phy_id = MARVELL_PHY_ID_88E1101,
@@ -2122,7 +2271,7 @@ static struct phy_driver marvell_drivers[] = {
21222271
.name = "Marvell 88E6390",
21232272
.features = PHY_GBIT_FEATURES,
21242273
.flags = PHY_HAS_INTERRUPT,
2125-
.probe = m88e1510_probe,
2274+
.probe = m88e6390_probe,
21262275
.config_init = &marvell_config_init,
21272276
.config_aneg = &m88e1510_config_aneg,
21282277
.read_status = &marvell_read_status,

0 commit comments

Comments
 (0)