brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · 201c8df Raw
152 lines · c
1// SPDX-License-Identifier: GPL-2.02/* LED driver for Aquantia PHY3 *4 * Author: Daniel Golle <daniel@makrotopia.org>5 */6 7#include <linux/phy.h>8 9#include "aquantia.h"10 11int aqr_phy_led_brightness_set(struct phy_device *phydev,12			       u8 index, enum led_brightness value)13{14	if (index >= AQR_MAX_LEDS)15		return -EINVAL;16 17	return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index),18			      VEND1_GLOBAL_LED_PROV_LINK_MASK |19			      VEND1_GLOBAL_LED_PROV_FORCE_ON |20			      VEND1_GLOBAL_LED_PROV_RX_ACT |21			      VEND1_GLOBAL_LED_PROV_TX_ACT,22			      value ? VEND1_GLOBAL_LED_PROV_FORCE_ON : 0);23}24 25static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) |26						 BIT(TRIGGER_NETDEV_LINK_100) |27						 BIT(TRIGGER_NETDEV_LINK_1000) |28						 BIT(TRIGGER_NETDEV_LINK_2500) |29						 BIT(TRIGGER_NETDEV_LINK_5000) |30						 BIT(TRIGGER_NETDEV_LINK_10000)  |31						 BIT(TRIGGER_NETDEV_RX) |32						 BIT(TRIGGER_NETDEV_TX));33 34int aqr_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,35				unsigned long rules)36{37	if (index >= AQR_MAX_LEDS)38		return -EINVAL;39 40	/* All combinations of the supported triggers are allowed */41	if (rules & ~supported_triggers)42		return -EOPNOTSUPP;43 44	return 0;45}46 47int aqr_phy_led_hw_control_get(struct phy_device *phydev, u8 index,48			       unsigned long *rules)49{50	int val;51 52	if (index >= AQR_MAX_LEDS)53		return -EINVAL;54 55	val = phy_read_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index));56	if (val < 0)57		return val;58 59	*rules = 0;60	if (val & VEND1_GLOBAL_LED_PROV_LINK100)61		*rules |= BIT(TRIGGER_NETDEV_LINK_100);62 63	if (val & VEND1_GLOBAL_LED_PROV_LINK1000)64		*rules |= BIT(TRIGGER_NETDEV_LINK_1000);65 66	if (val & VEND1_GLOBAL_LED_PROV_LINK2500)67		*rules |= BIT(TRIGGER_NETDEV_LINK_2500);68 69	if (val & VEND1_GLOBAL_LED_PROV_LINK5000)70		*rules |= BIT(TRIGGER_NETDEV_LINK_5000);71 72	if (val & VEND1_GLOBAL_LED_PROV_LINK10000)73		*rules |= BIT(TRIGGER_NETDEV_LINK_10000);74 75	if (val & VEND1_GLOBAL_LED_PROV_RX_ACT)76		*rules |= BIT(TRIGGER_NETDEV_RX);77 78	if (val & VEND1_GLOBAL_LED_PROV_TX_ACT)79		*rules |= BIT(TRIGGER_NETDEV_TX);80 81	return 0;82}83 84int aqr_phy_led_hw_control_set(struct phy_device *phydev, u8 index,85			       unsigned long rules)86{87	u16 val = 0;88 89	if (index >= AQR_MAX_LEDS)90		return -EINVAL;91 92	if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))93		val |= VEND1_GLOBAL_LED_PROV_LINK100;94 95	if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))96		val |= VEND1_GLOBAL_LED_PROV_LINK1000;97 98	if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))99		val |= VEND1_GLOBAL_LED_PROV_LINK2500;100 101	if (rules & (BIT(TRIGGER_NETDEV_LINK_5000) | BIT(TRIGGER_NETDEV_LINK)))102		val |= VEND1_GLOBAL_LED_PROV_LINK5000;103 104	if (rules & (BIT(TRIGGER_NETDEV_LINK_10000) | BIT(TRIGGER_NETDEV_LINK)))105		val |= VEND1_GLOBAL_LED_PROV_LINK10000;106 107	if (rules & BIT(TRIGGER_NETDEV_RX))108		val |= VEND1_GLOBAL_LED_PROV_RX_ACT;109 110	if (rules & BIT(TRIGGER_NETDEV_TX))111		val |= VEND1_GLOBAL_LED_PROV_TX_ACT;112 113	return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index),114			      VEND1_GLOBAL_LED_PROV_LINK_MASK |115			      VEND1_GLOBAL_LED_PROV_FORCE_ON |116			      VEND1_GLOBAL_LED_PROV_RX_ACT |117			      VEND1_GLOBAL_LED_PROV_TX_ACT, val);118}119 120int aqr_phy_led_active_low_set(struct phy_device *phydev, int index, bool enable)121{122	return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_DRIVE(index),123			      VEND1_GLOBAL_LED_DRIVE_VDD,124			      enable ? VEND1_GLOBAL_LED_DRIVE_VDD : 0);125}126 127int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long modes)128{129	struct aqr107_priv *priv = phydev->priv;130	bool active_low = false;131	u32 mode;132 133	if (index >= AQR_MAX_LEDS)134		return -EINVAL;135 136	for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {137		switch (mode) {138		case PHY_LED_ACTIVE_LOW:139			active_low = true;140			break;141		default:142			return -EINVAL;143		}144	}145 146	/* Save LED driver vdd state to restore on SW reset */147	if (active_low)148		priv->leds_active_low |= BIT(index);149 150	return aqr_phy_led_active_low_set(phydev, index, active_low);151}152