mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 06:57:57 +00:00
rtl930x: Rework per port LED configuration
Use led_setX to determine number of LEDs per port. Introduce macros to calculate register value and shift for particular LED in a particular set. Problem with previous implementation is that it uses is10G status to determine leds per port. However with usxgmii, driver sets 10g, 5g and 2.5g so even though there are only 2 leds per port it selects 4 leds per port This implementation relies on configured led_set node. Acked-by: Simon Wunderlich <sw@simonwunderlich.de> Signed-off-by: Harshal Gohel <hg@simonwunderlich.de>
This commit is contained in:
parent
a376508216
commit
2cfb1ecf10
@ -66,10 +66,10 @@
|
||||
compatible = "realtek,rtl9300-leds";
|
||||
active-low;
|
||||
|
||||
led_set0 = <0x0000 0xffff 0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps
|
||||
led_set0 = <0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps
|
||||
led_set1 = <0x0a0b 0x0a28 0x0a82 0x0a0b>; // LED set 1: (10G, 5G, 2.5G) (2.5G, 1G)
|
||||
// (5G, 10/100) (10G, 5G, 2.5G)
|
||||
led_set2 = <0x0000 0xffff 0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit
|
||||
led_set2 = <0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -271,7 +271,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val)
|
||||
static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct device *dev = priv->dev;
|
||||
struct device_node *dn, *phy_node, *mii_np = dev->of_node;
|
||||
struct device_node *dn, *phy_node, *led_node, *mii_np = dev->of_node;
|
||||
struct mii_bus *bus;
|
||||
int ret;
|
||||
u32 pn;
|
||||
@ -325,9 +325,12 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
led_node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds");
|
||||
|
||||
for_each_node_by_name(dn, "port") {
|
||||
phy_interface_t interface;
|
||||
u32 led_set;
|
||||
char led_set_str[16] = {0};
|
||||
|
||||
if (!of_device_is_available(dn))
|
||||
continue;
|
||||
@ -355,9 +358,18 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
if (interface == PHY_INTERFACE_MODE_10GBASER)
|
||||
priv->ports[pn].is10G = true;
|
||||
|
||||
if (of_property_read_u32(dn, "led-set", &led_set))
|
||||
led_set = 0;
|
||||
priv->ports[pn].led_set = led_set;
|
||||
priv->ports[pn].leds_on_this_port = 0;
|
||||
if (led_node) {
|
||||
if (of_property_read_u32(dn, "led-set", &led_set))
|
||||
led_set = 0;
|
||||
priv->ports[pn].led_set = led_set;
|
||||
sprintf(led_set_str, "led_set%d", led_set);
|
||||
priv->ports[pn].leds_on_this_port = of_property_count_u32_elems(led_node, led_set_str);
|
||||
if (priv->ports[pn].leds_on_this_port > 4) {
|
||||
dev_err(priv->dev, "led_set %d for port %d configuration is invalid\n", led_set, pn);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for the integrated SerDes of the RTL8380M first */
|
||||
if (of_property_read_bool(phy_node, "phy-is-integrated")
|
||||
|
@ -635,6 +635,7 @@ struct rtl838x_port {
|
||||
bool is2G5;
|
||||
int sds_num;
|
||||
int led_set;
|
||||
int leds_on_this_port;
|
||||
const struct dsa_port *dp;
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,15 @@
|
||||
|
||||
#define RTL930X_LED_GLB_ACTIVE_LOW BIT(22)
|
||||
|
||||
#define RTL930X_LED_SETX_0_CTRL(x) (RTL930X_LED_SET0_0_CTRL - (x * 8))
|
||||
#define RTL930X_LED_SETX_1_CTRL(x) (RTL930X_LED_SETX_0_CTRL(x) - 4)
|
||||
|
||||
/* get register for given set and led in the set */
|
||||
#define RTL930X_LED_SETX_LEDY(x,y) (RTL930X_LED_SETX_0_CTRL(x) - 4 * (y / 2))
|
||||
|
||||
/* get shift for given led in any set */
|
||||
#define RTL930X_LED_SET_LEDX_SHIFT(x) (16 * (x % 2))
|
||||
|
||||
extern struct mutex smi_lock;
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
@ -2396,10 +2405,44 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int set = 0; set < 4; set++) {
|
||||
char set_name[16] = {0};
|
||||
u32 set_config[4];
|
||||
int leds_in_this_set = 0;
|
||||
|
||||
/* Reset LED set configuration */
|
||||
sw_w32(0, RTL930X_LED_SETX_0_CTRL(set));
|
||||
sw_w32(0, RTL930X_LED_SETX_1_CTRL(set));
|
||||
|
||||
/**
|
||||
* Each led set has 4 number of leds, and each LED is configured with 16 bits
|
||||
* So each 32bit register holds configuration for 2 leds
|
||||
* And therefore each set requires 2 registers for configuring 4 LEDs
|
||||
*
|
||||
*/
|
||||
sprintf(set_name, "led_set%d", set);
|
||||
leds_in_this_set = of_property_count_u32_elems(node, set_name);
|
||||
|
||||
if (leds_in_this_set == 0 || leds_in_this_set > sizeof(set_config)) {
|
||||
pr_err("%s led_set configuration invalid skipping over this set\n", __func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(node, set_name, set_config, leds_in_this_set)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write configuration as per number of LEDs */
|
||||
for (int i=0, led = leds_in_this_set-1; led >= 0; led--,i++) {
|
||||
sw_w32_mask(0xffff << RTL930X_LED_SET_LEDX_SHIFT(led),
|
||||
(0xffff & set_config[i]) << RTL930X_LED_SET_LEDX_SHIFT(led),
|
||||
RTL930X_LED_SETX_LEDY(set, led));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
int pos = (i << 1) % 32;
|
||||
u32 set;
|
||||
u32 v;
|
||||
|
||||
sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i));
|
||||
sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i));
|
||||
@ -2407,12 +2450,8 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
|
||||
if (!priv->ports[i].phy)
|
||||
continue;
|
||||
|
||||
v = 0x1;
|
||||
if (priv->ports[i].is10G)
|
||||
v = 0x3;
|
||||
if (priv->ports[i].phy_is_integrated)
|
||||
v = 0x1;
|
||||
sw_w32_mask(0x3 << pos, v << pos, RTL930X_LED_PORT_NUM_CTRL(i));
|
||||
/* 0x0 = 1 led, 0x1 = 2 leds, 0x2 = 3 leds, 0x3 = 4 leds per port */
|
||||
sw_w32_mask(0x3 << pos, (priv->ports[i].leds_on_this_port -1) << pos, RTL930X_LED_PORT_NUM_CTRL(i));
|
||||
|
||||
pm |= BIT(i);
|
||||
|
||||
@ -2421,22 +2460,6 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
|
||||
sw_w32_mask(0, set << pos, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const __be32 *led_set;
|
||||
char set_name[9];
|
||||
u32 setlen;
|
||||
u32 v;
|
||||
|
||||
sprintf(set_name, "led_set%d", i);
|
||||
led_set = of_get_property(node, set_name, &setlen);
|
||||
if (!led_set || setlen != 16)
|
||||
break;
|
||||
v = be32_to_cpup(led_set) << 16 | be32_to_cpup(led_set + 1);
|
||||
sw_w32(v, RTL930X_LED_SET0_0_CTRL - 4 - i * 8);
|
||||
v = be32_to_cpup(led_set + 2) << 16 | be32_to_cpup(led_set + 3);
|
||||
sw_w32(v, RTL930X_LED_SET0_0_CTRL - i * 8);
|
||||
}
|
||||
|
||||
/* Set LED mode to serial (0x1) */
|
||||
sw_w32_mask(0x3, 0x1, RTL930X_LED_GLB_CTRL);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user