From 0538dc693b54e52fdfb8b7cd052eb96b5eb65708 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Wed, 2 Feb 2022 07:29:25 +0100 Subject: [PATCH] realtek: add support for port led configuration on RTL93XX Using the led-set attribute of a port in the dts we allow configuration of the port leds. Each led-set is being defined in the led-set configuration of the .dts, giving a specific configuration to steer the port LEDs via a serial connection. Signed-off-by: Birger Koblitz --- .../include/asm/mach-rtl838x/mach-rtl83xx.h | 2 +- .../drivers/net/dsa/rtl83xx/common.c | 32 +++++++-- .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 2 + .../drivers/net/dsa/rtl83xx/rtl838x.h | 20 ++++++ .../drivers/net/dsa/rtl83xx/rtl930x.c | 62 ++++++++++++++++++ .../drivers/net/dsa/rtl83xx/rtl931x.c | 65 ++++++++++++++++++- 6 files changed, 175 insertions(+), 8 deletions(-) diff --git a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h index 9f8b210c44..d95e5fb098 100644 --- a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h +++ b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h @@ -229,7 +229,7 @@ #define RTL838X_LED_GLB_CTRL (0xA000) #define RTL839X_LED_GLB_CTRL (0x00E4) #define RTL9302_LED_GLB_CTRL (0xcc00) -#define RTL930X_LED_GLB_CTRL (0xC400) +#define RTL930X_LED_GLB_CTRL (0xCC00) #define RTL931X_LED_GLB_CTRL (0x0600) #define RTL838X_EXT_GPIO_DIR (0xA08C) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index ea08ca12fc..9675ba88f1 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "rtl83xx.h" @@ -310,6 +311,9 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) } for_each_node_by_name(dn, "port") { + phy_interface_t interface; + u32 led_set; + if (of_property_read_u32(dn, "reg", &pn)) continue; @@ -321,6 +325,28 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) continue; } + pr_info("%s port %d has phandle\n", __func__, pn); + if (of_property_read_u32(phy_node, "sds", &priv->ports[pn].sds_num)) + priv->ports[pn].sds_num = -1; + else { + pr_info("%s sds port %d is %d\n", __func__, pn, + priv->ports[pn].sds_num); + } + pr_info("%s port %d has SDS\n", __func__, priv->ports[pn].sds_num); + + if (of_get_phy_mode(dn, &interface)) + interface = PHY_INTERFACE_MODE_NA; + if (interface == PHY_INTERFACE_MODE_HSGMII) + priv->ports[pn].is2G5 = true; + if (interface == PHY_INTERFACE_MODE_USXGMII) + priv->ports[pn].is2G5 = priv->ports[pn].is10G = true; + 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; + // Check for the integrated SerDes of the RTL8380M first if (of_property_read_bool(phy_node, "phy-is-integrated") && priv->id == 0x8380 && pn >= 24) { @@ -356,12 +382,6 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) } } - // TODO: Do this needs to come from the .dts - if (priv->family_id == RTL9300_FAMILY_ID) { - priv->ports[24].is2G5 = true; - priv->ports[25].is2G5 = true; - } - /* Disable MAC polling the PHY so that we can start configuration */ priv->r->set_port_reg_le(0ULL, priv->r->smi_poll_ctrl); diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index 8c4cd0b4a2..4e8bbc00db 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -258,6 +258,8 @@ static int rtl93xx_setup(struct dsa_switch *ds) priv->r->pie_init(priv); + priv->r->led_init(priv); + return 0; } diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h index 2c63885881..e2b82a4975 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -518,6 +518,7 @@ typedef enum { #define RTL931X_ACL_PORT_LOOKUP_CTRL(p) (0x44F8 + (((p) << 2))) #define RTL930X_PIE_BLK_PHASE_CTRL (0xA5A4) +#define RTL931X_PIE_BLK_PHASE_CTRL (0x4184) // PIE actions #define PIE_ACT_COPY_TO_PORT 2 @@ -554,6 +555,23 @@ typedef enum { #define RTL930X_L3_HW_LU_CTRL (0xACC0) #define RTL930X_L3_IP_ROUTE_CTRL 0xab44 +/* Port LED Control */ +#define RTL930X_LED_PORT_NUM_CTRL(p) (0xCC04 + (((p >> 4) << 2))) +#define RTL930X_LED_SET0_0_CTRL (0xCC28) +#define RTL930X_LED_PORT_COPR_SET_SEL_CTRL(p) (0xCC2C + (((p >> 4) << 2))) +#define RTL930X_LED_PORT_FIB_SET_SEL_CTRL(p) (0xCC34 + (((p >> 4) << 2))) +#define RTL930X_LED_PORT_COPR_MASK_CTRL (0xCC3C) +#define RTL930X_LED_PORT_FIB_MASK_CTRL (0xCC40) +#define RTL930X_LED_PORT_COMBO_MASK_CTRL (0xCC44) + +#define RTL931X_LED_PORT_NUM_CTRL(p) (0x0604 + (((p >> 4) << 2))) +#define RTL931X_LED_SET0_0_CTRL (0x0630) +#define RTL931X_LED_PORT_COPR_SET_SEL_CTRL(p) (0x0634 + (((p >> 4) << 2))) +#define RTL931X_LED_PORT_FIB_SET_SEL_CTRL(p) (0x0644 + (((p >> 4) << 2))) +#define RTL931X_LED_PORT_COPR_MASK_CTRL (0x0654) +#define RTL931X_LED_PORT_FIB_MASK_CTRL (0x065c) +#define RTL931X_LED_PORT_COMBO_MASK_CTRL (0x0664) + #define MAX_VLANS 4096 #define MAX_LAGS 16 #define MAX_PRIOS 8 @@ -605,6 +623,7 @@ struct rtl838x_port { bool is10G; bool is2G5; int sds_num; + int led_set; const struct dsa_port *dp; }; @@ -1017,6 +1036,7 @@ struct rtl838x_reg { void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf); void (*set_distribution_algorithm)(int group, int algoidx, u32 algomask); void (*set_receive_management_action)(int port, rma_ctrl_t type, action_type_t action); + void (*led_init)(struct rtl838x_switch_priv *priv); }; struct rtl838x_switch_priv { diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c index 28f9da8672..cd93e4bc8e 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c @@ -2400,6 +2400,67 @@ void rtl930x_set_distribution_algorithm(int group, int algoidx, u32 algomsk) sw_w32(newmask << l3shift, RTL930X_TRK_HASH_CTRL + (algoidx << 2)); } +static void rtl930x_led_init(struct rtl838x_switch_priv *priv) +{ + int i, pos; + u32 v, pm = 0, set; + u32 setlen; + const __be32 *led_set; + char set_name[9]; + struct device_node *node; + + pr_info("%s called\n", __func__); + node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); + if (!node) { + pr_info("%s No compatible LED node found\n", __func__); + return; + } + + for (i= 0; i < priv->cpu_port; i++) { + pos = (i << 1) % 32; + 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)); + + 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)); + + pm |= BIT(i); + + set = priv->ports[i].led_set; + sw_w32_mask(0, set << pos, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i)); + sw_w32_mask(0, set << pos, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); + } + + for (i = 0; i < 4; i++) { + 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); + + // Set port type masks + sw_w32(pm, RTL930X_LED_PORT_COPR_MASK_CTRL); + sw_w32(pm, RTL930X_LED_PORT_FIB_MASK_CTRL); + sw_w32(pm, RTL930X_LED_PORT_COMBO_MASK_CTRL); + + for (i = 0; i < 24; i++) + pr_info("%s %08x: %08x\n",__func__, 0xbb00cc00 + i * 4, sw_r32(0xcc00 + i * 4)); +} + const struct rtl838x_reg rtl930x_reg = { .mask_port_reg_be = rtl838x_mask_port_reg, .set_port_reg_be = rtl838x_set_port_reg, @@ -2486,4 +2547,5 @@ const struct rtl838x_reg rtl930x_reg = { .set_l3_router_mac = rtl930x_set_l3_router_mac, .set_l3_egress_intf = rtl930x_set_l3_egress_intf, .set_distribution_algorithm = rtl930x_set_distribution_algorithm, + .led_init = rtl930x_led_init, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c index c0c8a225a8..9ba120899a 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c @@ -1424,7 +1424,7 @@ static void rtl931x_pie_init(struct rtl838x_switch_priv *priv) // 4: Ingress Flow Table 3, 5: Egress flow table 0 for (i = 0; i < priv->n_pie_blocks; i++) { int pos = (i % 10) * 3; - u32 r = RTL930X_PIE_BLK_PHASE_CTRL + 4 * (i / 10); + u32 r = RTL931X_PIE_BLK_PHASE_CTRL + 4 * (i / 10); if (i < priv->n_pie_blocks / 2) sw_w32_mask(0x7 << pos, 0, r); @@ -1527,6 +1527,68 @@ void rtl931x_set_distribution_algorithm(int group, int algoidx, u32 algomsk) sw_w32(newmask << l3shift, RTL931X_TRK_HASH_CTRL + (algoidx << 2)); } +static void rtl931x_led_init(struct rtl838x_switch_priv *priv) +{ + int i, pos; + u32 v, set; + u64 pm_copper = 0, pm_fiber = 0; + u32 setlen; + const __be32 *led_set; + char set_name[9]; + struct device_node *node; + + pr_info("%s called\n", __func__); + node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); + if (!node) { + pr_info("%s No compatible LED node found\n", __func__); + return; + } + + for (i= 0; i < priv->cpu_port; i++) { + pos = (i << 1) % 32; + sw_w32_mask(0x3 << pos, 0, RTL931X_LED_PORT_FIB_SET_SEL_CTRL(i)); + sw_w32_mask(0x3 << pos, 0, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i)); + + if (!priv->ports[i].phy) + continue; + + v = 0x1; // Found on the EdgeCore, but we do not have any HW description + sw_w32_mask(0x3 << pos, v << pos, RTL931X_LED_PORT_NUM_CTRL(i)); + + if (priv->ports[i].phy_is_integrated) + pm_fiber |= BIT_ULL(i); + else + pm_copper |= BIT_ULL(i); + + set = priv->ports[i].led_set; + sw_w32_mask(0, set << pos, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i)); + sw_w32_mask(0, set << pos, RTL931X_LED_PORT_FIB_SET_SEL_CTRL(i)); + } + + for (i = 0; i < 4; i++) { + sprintf(set_name, "led_set%d", i); + pr_info(">%s<\n", set_name); + 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, RTL931X_LED_SET0_0_CTRL - 4 - i * 8); + v = be32_to_cpup(led_set + 2) << 16 | be32_to_cpup(led_set + 3); + sw_w32(v, RTL931X_LED_SET0_0_CTRL - i * 8); + } + + // Set LED mode to serial (0x1) + sw_w32_mask(0x3, 0x1, RTL931X_LED_GLB_CTRL); + + rtl839x_set_port_reg_le(pm_copper, RTL931X_LED_PORT_COPR_MASK_CTRL); + rtl839x_set_port_reg_le(pm_fiber, RTL931X_LED_PORT_FIB_MASK_CTRL); + rtl839x_set_port_reg_le(pm_copper | pm_fiber, RTL931X_LED_PORT_COMBO_MASK_CTRL); + + for (i = 0; i < 32; i++) + pr_info("%s %08x: %08x\n",__func__, 0xbb000600 + i * 4, sw_r32(0x0600 + i * 4)); + +} + const struct rtl838x_reg rtl931x_reg = { .mask_port_reg_be = rtl839x_mask_port_reg_be, .set_port_reg_be = rtl839x_set_port_reg_be, @@ -1594,5 +1656,6 @@ const struct rtl838x_reg rtl931x_reg = { .pie_rule_rm = rtl931x_pie_rule_rm, .l2_learning_setup = rtl931x_l2_learning_setup, .l3_setup = rtl931x_l3_setup, + .led_init = rtl931x_led_init, }; -- 2.30.2