Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lan78xx: Read LED states from Device Tree

Add support for DT property "microchip,led-modes", a vector of zero
to four cells (u32s) in the range 0-15, each of which sets the mode
for one of the LEDs. Some possible values are:

0=link/activity 1=link1000/activity
2=link100/activity 3=link10/activity
4=link100/1000/activity 5=link10/1000/activity
6=link10/100/activity 14=off 15=on

These values are given symbolic constants in a dt-bindings header.

Also use the presence of the DT property to indicate that the
LEDs should be enabled - necessary in the event that no valid OTP
or EEPROM is available.

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Phil Elwell and committed by
David S. Miller
1827b067 760db29b

+81 -1
+1
MAINTAINERS
··· 14572 14572 L: netdev@vger.kernel.org 14573 14573 S: Maintained 14574 14574 F: drivers/net/usb/lan78xx.* 14575 + F: include/dt-bindings/net/microchip-lan78xx.h 14575 14576 14576 14577 USB MASS STORAGE DRIVER 14577 14578 M: Alan Stern <stern@rowland.harvard.edu>
+25
drivers/net/phy/microchip.c
··· 20 20 #include <linux/ethtool.h> 21 21 #include <linux/phy.h> 22 22 #include <linux/microchipphy.h> 23 + #include <linux/of.h> 24 + #include <dt-bindings/net/microchip-lan78xx.h> 23 25 24 26 #define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>" 25 27 #define DRIVER_DESC "Microchip LAN88XX PHY driver" ··· 72 70 { 73 71 struct device *dev = &phydev->mdio.dev; 74 72 struct lan88xx_priv *priv; 73 + u32 led_modes[4]; 74 + int len; 75 75 76 76 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 77 77 if (!priv) 78 78 return -ENOMEM; 79 79 80 80 priv->wolopts = 0; 81 + 82 + len = of_property_read_variable_u32_array(dev->of_node, 83 + "microchip,led-modes", 84 + led_modes, 85 + 0, 86 + ARRAY_SIZE(led_modes)); 87 + if (len >= 0) { 88 + u32 reg = 0; 89 + int i; 90 + 91 + for (i = 0; i < len; i++) { 92 + if (led_modes[i] > 15) 93 + return -EINVAL; 94 + reg |= led_modes[i] << (i * 4); 95 + } 96 + for (; i < ARRAY_SIZE(led_modes); i++) 97 + reg |= LAN78XX_FORCE_LED_OFF << (i * 4); 98 + (void)phy_write(phydev, LAN78XX_PHY_LED_MODE_SELECT, reg); 99 + } else if (len == -EOVERFLOW) { 100 + return -EINVAL; 101 + } 81 102 82 103 /* these values can be used to identify internal PHY */ 83 104 priv->chip_id = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_ID);
+31 -1
drivers/net/usb/lan78xx.c
··· 37 37 #include <linux/irqchip/chained_irq.h> 38 38 #include <linux/microchipphy.h> 39 39 #include <linux/phy.h> 40 + #include <linux/of_mdio.h> 40 41 #include <linux/of_net.h> 41 42 #include "lan78xx.h" 42 43 ··· 1761 1760 1762 1761 static int lan78xx_mdio_init(struct lan78xx_net *dev) 1763 1762 { 1763 + struct device_node *node; 1764 1764 int ret; 1765 1765 1766 1766 dev->mdiobus = mdiobus_alloc(); ··· 1790 1788 break; 1791 1789 } 1792 1790 1793 - ret = mdiobus_register(dev->mdiobus); 1791 + node = of_get_child_by_name(dev->udev->dev.of_node, "mdio"); 1792 + if (node) { 1793 + ret = of_mdiobus_register(dev->mdiobus, node); 1794 + of_node_put(node); 1795 + } else { 1796 + ret = mdiobus_register(dev->mdiobus); 1797 + } 1794 1798 if (ret) { 1795 1799 netdev_err(dev->net, "can't register MDIO bus\n"); 1796 1800 goto exit1; ··· 2084 2076 phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); 2085 2077 mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control); 2086 2078 phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv); 2079 + 2080 + if (phydev->mdio.dev.of_node) { 2081 + u32 reg; 2082 + int len; 2083 + 2084 + len = of_property_count_elems_of_size(phydev->mdio.dev.of_node, 2085 + "microchip,led-modes", 2086 + sizeof(u32)); 2087 + if (len >= 0) { 2088 + /* Ensure the appropriate LEDs are enabled */ 2089 + lan78xx_read_reg(dev, HW_CFG, &reg); 2090 + reg &= ~(HW_CFG_LED0_EN_ | 2091 + HW_CFG_LED1_EN_ | 2092 + HW_CFG_LED2_EN_ | 2093 + HW_CFG_LED3_EN_); 2094 + reg |= (len > 0) * HW_CFG_LED0_EN_ | 2095 + (len > 1) * HW_CFG_LED1_EN_ | 2096 + (len > 2) * HW_CFG_LED2_EN_ | 2097 + (len > 3) * HW_CFG_LED3_EN_; 2098 + lan78xx_write_reg(dev, HW_CFG, reg); 2099 + } 2100 + } 2087 2101 2088 2102 genphy_config_aneg(phydev); 2089 2103
+21
include/dt-bindings/net/microchip-lan78xx.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _DT_BINDINGS_MICROCHIP_LAN78XX_H 3 + #define _DT_BINDINGS_MICROCHIP_LAN78XX_H 4 + 5 + /* LED modes for LAN7800/LAN7850 embedded PHY */ 6 + 7 + #define LAN78XX_LINK_ACTIVITY 0 8 + #define LAN78XX_LINK_1000_ACTIVITY 1 9 + #define LAN78XX_LINK_100_ACTIVITY 2 10 + #define LAN78XX_LINK_10_ACTIVITY 3 11 + #define LAN78XX_LINK_100_1000_ACTIVITY 4 12 + #define LAN78XX_LINK_10_1000_ACTIVITY 5 13 + #define LAN78XX_LINK_10_100_ACTIVITY 6 14 + #define LAN78XX_DUPLEX_COLLISION 8 15 + #define LAN78XX_COLLISION 9 16 + #define LAN78XX_ACTIVITY 10 17 + #define LAN78XX_AUTONEG_FAULT 12 18 + #define LAN78XX_FORCE_LED_OFF 14 19 + #define LAN78XX_FORCE_LED_ON 15 20 + 21 + #endif
+3
include/linux/microchipphy.h
··· 70 70 #define LAN88XX_MMD3_CHIP_ID (32877) 71 71 #define LAN88XX_MMD3_CHIP_REV (32878) 72 72 73 + /* Registers specific to the LAN7800/LAN7850 embedded phy */ 74 + #define LAN78XX_PHY_LED_MODE_SELECT (0x1D) 75 + 73 76 #endif /* _MICROCHIPPHY_H */