mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-18 16:40:29 +00:00
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 <git@birger-koblitz.de>
This commit is contained in:
parent
caaac9ab3b
commit
0538dc693b
@ -229,7 +229,7 @@
|
|||||||
#define RTL838X_LED_GLB_CTRL (0xA000)
|
#define RTL838X_LED_GLB_CTRL (0xA000)
|
||||||
#define RTL839X_LED_GLB_CTRL (0x00E4)
|
#define RTL839X_LED_GLB_CTRL (0x00E4)
|
||||||
#define RTL9302_LED_GLB_CTRL (0xcc00)
|
#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 RTL931X_LED_GLB_CTRL (0x0600)
|
||||||
|
|
||||||
#define RTL838X_EXT_GPIO_DIR (0xA08C)
|
#define RTL838X_EXT_GPIO_DIR (0xA08C)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <net/netevent.h>
|
#include <net/netevent.h>
|
||||||
#include <linux/inetdevice.h>
|
#include <linux/inetdevice.h>
|
||||||
#include <linux/rhashtable.h>
|
#include <linux/rhashtable.h>
|
||||||
|
#include <linux/of_net.h>
|
||||||
|
|
||||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||||
#include "rtl83xx.h"
|
#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") {
|
for_each_node_by_name(dn, "port") {
|
||||||
|
phy_interface_t interface;
|
||||||
|
u32 led_set;
|
||||||
|
|
||||||
if (of_property_read_u32(dn, "reg", &pn))
|
if (of_property_read_u32(dn, "reg", &pn))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -321,6 +325,28 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
|||||||
continue;
|
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
|
// Check for the integrated SerDes of the RTL8380M first
|
||||||
if (of_property_read_bool(phy_node, "phy-is-integrated")
|
if (of_property_read_bool(phy_node, "phy-is-integrated")
|
||||||
&& priv->id == 0x8380 && pn >= 24) {
|
&& 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 */
|
/* Disable MAC polling the PHY so that we can start configuration */
|
||||||
priv->r->set_port_reg_le(0ULL, priv->r->smi_poll_ctrl);
|
priv->r->set_port_reg_le(0ULL, priv->r->smi_poll_ctrl);
|
||||||
|
|
||||||
|
@ -258,6 +258,8 @@ static int rtl93xx_setup(struct dsa_switch *ds)
|
|||||||
|
|
||||||
priv->r->pie_init(priv);
|
priv->r->pie_init(priv);
|
||||||
|
|
||||||
|
priv->r->led_init(priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,6 +518,7 @@ typedef enum {
|
|||||||
#define RTL931X_ACL_PORT_LOOKUP_CTRL(p) (0x44F8 + (((p) << 2)))
|
#define RTL931X_ACL_PORT_LOOKUP_CTRL(p) (0x44F8 + (((p) << 2)))
|
||||||
|
|
||||||
#define RTL930X_PIE_BLK_PHASE_CTRL (0xA5A4)
|
#define RTL930X_PIE_BLK_PHASE_CTRL (0xA5A4)
|
||||||
|
#define RTL931X_PIE_BLK_PHASE_CTRL (0x4184)
|
||||||
|
|
||||||
// PIE actions
|
// PIE actions
|
||||||
#define PIE_ACT_COPY_TO_PORT 2
|
#define PIE_ACT_COPY_TO_PORT 2
|
||||||
@ -554,6 +555,23 @@ typedef enum {
|
|||||||
#define RTL930X_L3_HW_LU_CTRL (0xACC0)
|
#define RTL930X_L3_HW_LU_CTRL (0xACC0)
|
||||||
#define RTL930X_L3_IP_ROUTE_CTRL 0xab44
|
#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_VLANS 4096
|
||||||
#define MAX_LAGS 16
|
#define MAX_LAGS 16
|
||||||
#define MAX_PRIOS 8
|
#define MAX_PRIOS 8
|
||||||
@ -605,6 +623,7 @@ struct rtl838x_port {
|
|||||||
bool is10G;
|
bool is10G;
|
||||||
bool is2G5;
|
bool is2G5;
|
||||||
int sds_num;
|
int sds_num;
|
||||||
|
int led_set;
|
||||||
const struct dsa_port *dp;
|
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_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf);
|
||||||
void (*set_distribution_algorithm)(int group, int algoidx, u32 algomask);
|
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 (*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 {
|
struct rtl838x_switch_priv {
|
||||||
|
@ -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));
|
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 = {
|
const struct rtl838x_reg rtl930x_reg = {
|
||||||
.mask_port_reg_be = rtl838x_mask_port_reg,
|
.mask_port_reg_be = rtl838x_mask_port_reg,
|
||||||
.set_port_reg_be = rtl838x_set_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_router_mac = rtl930x_set_l3_router_mac,
|
||||||
.set_l3_egress_intf = rtl930x_set_l3_egress_intf,
|
.set_l3_egress_intf = rtl930x_set_l3_egress_intf,
|
||||||
.set_distribution_algorithm = rtl930x_set_distribution_algorithm,
|
.set_distribution_algorithm = rtl930x_set_distribution_algorithm,
|
||||||
|
.led_init = rtl930x_led_init,
|
||||||
};
|
};
|
||||||
|
@ -1424,7 +1424,7 @@ static void rtl931x_pie_init(struct rtl838x_switch_priv *priv)
|
|||||||
// 4: Ingress Flow Table 3, 5: Egress flow table 0
|
// 4: Ingress Flow Table 3, 5: Egress flow table 0
|
||||||
for (i = 0; i < priv->n_pie_blocks; i++) {
|
for (i = 0; i < priv->n_pie_blocks; i++) {
|
||||||
int pos = (i % 10) * 3;
|
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)
|
if (i < priv->n_pie_blocks / 2)
|
||||||
sw_w32_mask(0x7 << pos, 0, r);
|
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));
|
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 = {
|
const struct rtl838x_reg rtl931x_reg = {
|
||||||
.mask_port_reg_be = rtl839x_mask_port_reg_be,
|
.mask_port_reg_be = rtl839x_mask_port_reg_be,
|
||||||
.set_port_reg_be = rtl839x_set_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,
|
.pie_rule_rm = rtl931x_pie_rule_rm,
|
||||||
.l2_learning_setup = rtl931x_l2_learning_setup,
|
.l2_learning_setup = rtl931x_l2_learning_setup,
|
||||||
.l3_setup = rtl931x_l3_setup,
|
.l3_setup = rtl931x_l3_setup,
|
||||||
|
.led_init = rtl931x_led_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user