From a4b5bc20d7ab4b6efeafd985e889eeac27116940 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 27 Aug 2021 12:32:00 +0200 Subject: [PATCH 01/82] kernel: add a bridge feature for filtering BPDU packets on ports This will be used to ensure that APs don't transmit unnecessary STP packets Signed-off-by: Felix Fietkau --- ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 177 ++++++++++++++++++ ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 177 ++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 target/linux/generic/pending-5.10/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch create mode 100644 target/linux/generic/pending-5.4/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch diff --git a/target/linux/generic/pending-5.10/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-5.10/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch new file mode 100644 index 0000000000..f05ff3bc04 --- /dev/null +++ b/target/linux/generic/pending-5.10/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -0,0 +1,177 @@ +From: Felix Fietkau +Date: Fri, 27 Aug 2021 12:22:32 +0200 +Subject: [PATCH] bridge: add knob for filtering rx/tx BPDU packets on a port + +Some devices (e.g. wireless APs) can't have devices behind them be part of +a bridge topology with redundant links, due to address limitations. +Additionally, broadcast traffic on these devices is somewhat expensive, due to +the low data rate and wakeups of clients in powersave mode. +This knob can be used to ensure that BPDU packets are never sent or forwarded +to/from these devices + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -56,6 +56,7 @@ struct br_ip_list { + #define BR_MRP_AWARE BIT(17) + #define BR_MRP_LOST_CONT BIT(18) + #define BR_MRP_LOST_IN_CONT BIT(19) ++#define BR_BPDU_FILTER BIT(20) + + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -191,6 +191,7 @@ out: + void br_flood(struct net_bridge *br, struct sk_buff *skb, + enum br_pkt_type pkt_type, bool local_rcv, bool local_orig) + { ++ const unsigned char *dest = eth_hdr(skb)->h_dest; + struct net_bridge_port *prev = NULL; + struct net_bridge_port *p; + +@@ -206,6 +207,10 @@ void br_flood(struct net_bridge *br, str + case BR_PKT_MULTICAST: + if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) + continue; ++ if ((p->flags & BR_BPDU_FILTER) && ++ unlikely(is_link_local_ether_addr(dest) && ++ dest[5] == 0)) ++ continue; + break; + case BR_PKT_BROADCAST: + if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -305,6 +305,8 @@ static rx_handler_result_t br_handle_fra + fwd_mask |= p->group_fwd_mask; + switch (dest[5]) { + case 0x00: /* Bridge Group Address */ ++ if (p->flags & BR_BPDU_FILTER) ++ goto drop; + /* If STP is turned off, + then must forward to keep loop detection */ + if (p->br->stp_enabled == BR_NO_STP || +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -233,6 +233,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA + BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); + BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); + BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); ++BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER); + + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +@@ -285,6 +286,7 @@ static const struct brport_attribute *br + &brport_attr_group_fwd_mask, + &brport_attr_neigh_suppress, + &brport_attr_isolated, ++ &brport_attr_bpdu_filter, + &brport_attr_backup_port, + NULL + }; +--- a/net/bridge/br_stp_bpdu.c ++++ b/net/bridge/br_stp_bpdu.c +@@ -80,7 +80,8 @@ void br_send_config_bpdu(struct net_brid + { + unsigned char buf[35]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -127,7 +128,8 @@ void br_send_tcn_bpdu(struct net_bridge_ + { + unsigned char buf[4]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -172,6 +174,9 @@ void br_stp_rcv(const struct stp_proto * + if (!(br->dev->flags & IFF_UP)) + goto out; + ++ if (p->flags & BR_BPDU_FILTER) ++ goto out; ++ + if (p->state == BR_STATE_DISABLED) + goto out; + +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -524,6 +524,7 @@ enum { + IFLA_BRPORT_BACKUP_PORT, + IFLA_BRPORT_MRP_RING_OPEN, + IFLA_BRPORT_MRP_IN_OPEN, ++ IFLA_BRPORT_BPDU_FILTER, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -137,6 +137,7 @@ static inline size_t br_port_info_size(v + + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ + + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */ + + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ ++ + nla_total_size(1) /* IFLA_BRPORT_BPDU_FILTER */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ +@@ -220,7 +221,8 @@ static int br_port_fill_attrs(struct sk_ + BR_MRP_LOST_CONT)) || + nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN, + !!(p->flags & BR_MRP_LOST_IN_CONT)) || +- nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) ++ nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) || ++ nla_put_u8(skb, IFLA_BRPORT_BPDU_FILTER, !!(p->flags & BR_BPDU_FILTER))) + return -EMSGSIZE; + + timerval = br_timer_value(&p->message_age_timer); +@@ -728,6 +730,7 @@ static const struct nla_policy br_port_p + [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 }, + [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, + [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, ++ [IFLA_BRPORT_BPDU_FILTER] = { .type = NLA_U8 }, + }; + + /* Change the state of the port and notify spanning tree */ +@@ -826,6 +829,10 @@ static int br_setport(struct net_bridge_ + if (err) + return err; + ++ err = br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); ++ if (err) ++ return err; ++ + br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false; + err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); + if (err) +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -55,7 +55,7 @@ + #include + + #define RTNL_MAX_TYPE 50 +-#define RTNL_SLAVE_MAX_TYPE 36 ++#define RTNL_SLAVE_MAX_TYPE 37 + + struct rtnl_link { + rtnl_doit_func doit; +@@ -4680,7 +4680,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu + brport_nla_put_flag(skb, flags, mask, + IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) || + brport_nla_put_flag(skb, flags, mask, +- IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD)) { ++ IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD) || ++ brport_nla_put_flag(skb, flags, mask, ++ IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER)) { + nla_nest_cancel(skb, protinfo); + goto nla_put_failure; + } diff --git a/target/linux/generic/pending-5.4/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-5.4/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch new file mode 100644 index 0000000000..90e0d0de83 --- /dev/null +++ b/target/linux/generic/pending-5.4/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -0,0 +1,177 @@ +From: Felix Fietkau +Date: Fri, 27 Aug 2021 12:22:32 +0200 +Subject: [PATCH] bridge: add knob for filtering rx/tx BPDU packets on a port + +Some devices (e.g. wireless APs) can't have devices behind them be part of +a bridge topology with redundant links, due to address limitations. +Additionally, broadcast traffic on these devices is somewhat expensive, due to +the low data rate and wakeups of clients in powersave mode. +This knob can be used to ensure that BPDU packets are never sentor forwarded +to/from these devices + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -47,6 +47,7 @@ struct br_ip_list { + #define BR_BCAST_FLOOD BIT(14) + #define BR_NEIGH_SUPPRESS BIT(15) + #define BR_ISOLATED BIT(16) ++#define BR_BPDU_FILTER BIT(17) + + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -191,6 +191,7 @@ out: + void br_flood(struct net_bridge *br, struct sk_buff *skb, + enum br_pkt_type pkt_type, bool local_rcv, bool local_orig) + { ++ const unsigned char *dest = eth_hdr(skb)->h_dest; + struct net_bridge_port *prev = NULL; + struct net_bridge_port *p; + +@@ -206,6 +207,10 @@ void br_flood(struct net_bridge *br, str + case BR_PKT_MULTICAST: + if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) + continue; ++ if ((p->flags & BR_BPDU_FILTER) && ++ unlikely(is_link_local_ether_addr(dest) && ++ dest[5] == 0)) ++ continue; + break; + case BR_PKT_BROADCAST: + if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -300,6 +300,8 @@ rx_handler_result_t br_handle_frame(stru + fwd_mask |= p->group_fwd_mask; + switch (dest[5]) { + case 0x00: /* Bridge Group Address */ ++ if (p->flags & BR_BPDU_FILTER) ++ goto drop; + /* If STP is turned off, + then must forward to keep loop detection */ + if (p->br->stp_enabled == BR_NO_STP || +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -233,6 +233,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA + BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); + BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); + BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); ++BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER); + + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +@@ -285,6 +286,7 @@ static const struct brport_attribute *br + &brport_attr_group_fwd_mask, + &brport_attr_neigh_suppress, + &brport_attr_isolated, ++ &brport_attr_bpdu_filter, + &brport_attr_backup_port, + NULL + }; +--- a/net/bridge/br_stp_bpdu.c ++++ b/net/bridge/br_stp_bpdu.c +@@ -80,7 +80,8 @@ void br_send_config_bpdu(struct net_brid + { + unsigned char buf[35]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -125,7 +126,8 @@ void br_send_tcn_bpdu(struct net_bridge_ + { + unsigned char buf[4]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -168,6 +170,9 @@ void br_stp_rcv(const struct stp_proto * + if (!(br->dev->flags & IFF_UP)) + goto out; + ++ if (p->flags & BR_BPDU_FILTER) ++ goto out; ++ + if (p->state == BR_STATE_DISABLED) + goto out; + +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -340,6 +340,7 @@ enum { + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, + IFLA_BRPORT_BACKUP_PORT, ++ IFLA_BRPORT_BPDU_FILTER, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -137,6 +137,7 @@ static inline size_t br_port_info_size(v + + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ + + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */ + + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ ++ + nla_total_size(1) /* IFLA_BRPORT_BPDU_FILTER */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ +@@ -214,7 +215,8 @@ static int br_port_fill_attrs(struct sk_ + nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) || + nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS, + !!(p->flags & BR_NEIGH_SUPPRESS)) || +- nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) ++ nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) || ++ nla_put_u8(skb, IFLA_BRPORT_BPDU_FILTER, !!(p->flags & BR_BPDU_FILTER))) + return -EMSGSIZE; + + timerval = br_timer_value(&p->message_age_timer); +@@ -676,6 +678,7 @@ static const struct nla_policy br_port_p + [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 }, + [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, + [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, ++ [IFLA_BRPORT_BPDU_FILTER] = { .type = NLA_U8 }, + }; + + /* Change the state of the port and notify spanning tree */ +@@ -774,6 +777,10 @@ static int br_setport(struct net_bridge_ + if (err) + return err; + ++ err = br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); ++ if (err) ++ return err; ++ + br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false; + err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); + if (err) +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -55,7 +55,7 @@ + #include + + #define RTNL_MAX_TYPE 50 +-#define RTNL_SLAVE_MAX_TYPE 36 ++#define RTNL_SLAVE_MAX_TYPE 37 + + struct rtnl_link { + rtnl_doit_func doit; +@@ -4373,7 +4373,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu + brport_nla_put_flag(skb, flags, mask, + IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD) || + brport_nla_put_flag(skb, flags, mask, +- IFLA_BRPORT_PROXYARP, BR_PROXYARP)) { ++ IFLA_BRPORT_PROXYARP, BR_PROXYARP) || ++ brport_nla_put_flag(skb, flags, mask, ++ IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER)) { + nla_nest_cancel(skb, protinfo); + goto nla_put_failure; + } From c0d77852a783a688dd7ef1db00f1202fe4892723 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 27 Aug 2021 12:33:37 +0200 Subject: [PATCH 02/82] netifd: update to the latest version d590fbd255ce wireless: always enable bpdu filter for AP interfaces and VLANs f8ff6d820283 system-linux: remove copy&paste from /proc and /sys path names 300b1220fab3 wireless: improve reliability of proxyarp support 5ba9744aac6d device: add support for configuring bonding devices 6fa9b042ff4d wireless: only apply wireless device attributes to the base vif interface 06d11bbf1f2b wireless: only enable proxyarp/isolate for AP vifs 08e954e137ff bonding: claim the port device before creating the bonding device Signed-off-by: Felix Fietkau --- package/network/config/netifd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index c33e0c2134..f2ea7f5f43 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2021-08-24 -PKG_SOURCE_VERSION:=454e9c33c90691d5bea12263f1801a7dc38c20b1 -PKG_MIRROR_HASH:=b8c6d8a1d0cb60c353c0272b8a526d8e28e6ee7d385e96b18018d1bc13b54cc2 +PKG_SOURCE_DATE:=2021-09-21 +PKG_SOURCE_VERSION:=08e954e137ffcf7770200bbd6476dc36bbd326f5 +PKG_MIRROR_HASH:=2250b8adc892a7ce0b79ca34611fae0098b3a367272684f42891923717b47578 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 From ef244756584af9eb36d2050f0a21a0b8a1e2e8fe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 27 Aug 2021 12:38:12 +0200 Subject: [PATCH 03/82] ustp: update to the latest version c62d85cf7a0d bridge: check port bpdu filter status and apply it to the config 25555611be91 libnetlink: turn rtnetlink error answers into debug msgs 462b3a491347 build: use pthread cflags/ldflags Signed-off-by: Felix Fietkau --- package/network/services/ustp/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/ustp/Makefile b/package/network/services/ustp/Makefile index 682bd9f350..88bc993bb6 100644 --- a/package/network/services/ustp/Makefile +++ b/package/network/services/ustp/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=$(PROJECT_GIT)/project/ustp.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-08-25 -PKG_SOURCE_VERSION:=9622264cf92691f18ae9222b0a4c9db95af5d80d -PKG_MIRROR_HASH:=de4ed29eee21192b60e8683633d916d251bcccd5701bdac83b5ba435189297f1 +PKG_SOURCE_DATE:=2021-09-21 +PKG_SOURCE_VERSION:=462b3a491347e452c15220861949b1d6371fa59e +PKG_MIRROR_HASH:=0e96edc983cf437b95874e5715d743f30bb826d8757dc3771ff872ab9cf18f35 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 From 17d19a7d4398789ae8da3daf8e0db167d58b0782 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 1 Sep 2021 19:12:27 +0200 Subject: [PATCH 04/82] hostapd: let netifd set bridge port attributes for snooping Avoids race conditions on bridge member add/remove Signed-off-by: Felix Fietkau --- .../hostapd/patches/740-snoop_iface.patch | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/package/network/services/hostapd/patches/740-snoop_iface.patch b/package/network/services/hostapd/patches/740-snoop_iface.patch index 722d1e713a..8d928f8505 100644 --- a/package/network/services/hostapd/patches/740-snoop_iface.patch +++ b/package/network/services/hostapd/patches/740-snoop_iface.patch @@ -10,7 +10,36 @@ --- a/src/ap/x_snoop.c +++ b/src/ap/x_snoop.c -@@ -71,8 +71,12 @@ x_snoop_get_l2_packet(struct hostapd_dat +@@ -31,14 +31,16 @@ int x_snoop_init(struct hostapd_data *ha + return -1; + } + +- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, ++ if (!conf->snoop_iface[0] && ++ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, + 1)) { + wpa_printf(MSG_DEBUG, + "x_snoop: Failed to enable hairpin_mode on the bridge port"); + return -1; + } + +- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) { ++ if (!conf->snoop_iface[0] && ++ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) { + wpa_printf(MSG_DEBUG, + "x_snoop: Failed to enable proxyarp on the bridge port"); + return -1; +@@ -52,7 +54,8 @@ int x_snoop_init(struct hostapd_data *ha + } + + #ifdef CONFIG_IPV6 +- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) { ++ if (!conf->snoop_iface[0] && ++ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) { + wpa_printf(MSG_DEBUG, + "x_snoop: Failed to enable multicast snooping on the bridge"); + return -1; +@@ -71,8 +74,12 @@ x_snoop_get_l2_packet(struct hostapd_dat { struct hostapd_bss_config *conf = hapd->conf; struct l2_packet_data *l2; From b62a4cfc9330e9631a372a11fa9e09ac809080f5 Mon Sep 17 00:00:00 2001 From: Kuan-Yi Li Date: Fri, 17 Sep 2021 14:27:47 +0800 Subject: [PATCH 05/82] restool: fix compilation with GCC 10 GCC 10 defaults to `-fno-common` and complains about multiple definition of `mc_status` in restool. Backport a patch from upstream to fix compilation with host GCC 10. Signed-off-by: Kuan-Yi Li --- .../network/utils/layerscape/restool/Makefile | 2 +- ...restool-fix-get_device_file-function.patch | 13 +- .../0002-restool-yocto-build-issue.patch | 264 ++++++++++++++++++ 3 files changed, 269 insertions(+), 10 deletions(-) create mode 100644 package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch diff --git a/package/network/utils/layerscape/restool/Makefile b/package/network/utils/layerscape/restool/Makefile index 73fa8e4d9e..96ee7ef1cc 100644 --- a/package/network/utils/layerscape/restool/Makefile +++ b/package/network/utils/layerscape/restool/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=restool PKG_VERSION:=LSDK-20.04 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://source.codeaurora.org/external/qoriq/qoriq-components/restool diff --git a/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch b/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch index 2745fd02a0..65d381cbc5 100644 --- a/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch +++ b/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch @@ -16,11 +16,9 @@ Signed-off-by: Ioana Ciornei restool.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) -diff --git a/restool.c b/restool.c -index 7553659..78fd1bf 100644 --- a/restool.c +++ b/restool.c -@@ -1185,8 +1185,13 @@ out: +@@ -1193,8 +1193,13 @@ out: static int get_device_file(void) { @@ -34,7 +32,7 @@ index 7553659..78fd1bf 100644 memset(restool.device_file, '\0', DEV_FILE_SIZE); -@@ -1214,10 +1219,6 @@ static int get_device_file(void) +@@ -1222,10 +1227,6 @@ static int get_device_file(void) goto out; } } else { @@ -45,7 +43,7 @@ index 7553659..78fd1bf 100644 d = opendir("/dev"); if (!d) { -@@ -1227,26 +1228,34 @@ static int get_device_file(void) +@@ -1235,26 +1236,34 @@ static int get_device_file(void) } while ((dir = readdir(d)) != NULL) { if (strncmp(dir->d_name, "dprc.", 5) == 0) { @@ -92,7 +90,7 @@ index 7553659..78fd1bf 100644 } else { error = -1; if (num_dev_files == 0) -@@ -1255,6 +1264,9 @@ static int get_device_file(void) +@@ -1263,6 +1272,9 @@ static int get_device_file(void) ERROR_PRINTF("error: multiple root containers\n"); } } @@ -102,6 +100,3 @@ index 7553659..78fd1bf 100644 out: return error; } --- -2.17.1 - diff --git a/package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch b/package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch new file mode 100644 index 0000000000..d38db52dae --- /dev/null +++ b/package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch @@ -0,0 +1,264 @@ +From 802764f8ed76f927dff494558332b0b77de7ac65 Mon Sep 17 00:00:00 2001 +From: Ionut-robert Aron +Date: Fri, 16 Oct 2020 11:01:24 +0300 +Subject: [PATCH] restool: yocto build issue + +Prefix 'enum mc_cmd_status mc_status' with 'static' so restool can +compile. + +Signed-off-by: Ionut-robert Aron +--- + dpaiop_commands.c | 2 +- + dpbp_commands.c | 2 +- + dpci_commands.c | 2 +- + dpcon_commands.c | 2 +- + dpdbg_commands.c | 2 +- + dpdcei_commands.c | 2 +- + dpdmai_commands.c | 2 +- + dpdmux_commands.c | 2 +- + dpio_commands.c | 2 +- + dpmac_commands.c | 2 +- + dpmcp_commands.c | 2 +- + dpni_commands.c | 2 +- + dprc_commands.c | 2 +- + dprc_commands_generate_dpl.c | 4 ++-- + dprtc_commands.c | 2 +- + dpseci_commands.c | 2 +- + dpsw_commands.c | 2 +- + restool.c | 8 ++++---- + 18 files changed, 22 insertions(+), 22 deletions(-) + +--- a/dpaiop_commands.c ++++ b/dpaiop_commands.c +@@ -44,7 +44,7 @@ + #include "mc_v9/fsl_dpaiop.h" + #include "mc_v10/fsl_dpaiop.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpaiop info command options +--- a/dpbp_commands.c ++++ b/dpbp_commands.c +@@ -43,7 +43,7 @@ + #include "mc_v9/fsl_dpbp.h" + #include "mc_v10/fsl_dpbp.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpbp info command options +--- a/dpci_commands.c ++++ b/dpci_commands.c +@@ -44,7 +44,7 @@ + #include "mc_v9/fsl_dpci.h" + #include "mc_v10/fsl_dpci.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpci info command options +--- a/dpcon_commands.c ++++ b/dpcon_commands.c +@@ -44,7 +44,7 @@ + #include "mc_v9/fsl_dpcon.h" + #include "mc_v10/fsl_dpcon.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpcon info command options +--- a/dpdbg_commands.c ++++ b/dpdbg_commands.c +@@ -41,7 +41,7 @@ + #include "utils.h" + #include "mc_v10/fsl_dpdbg.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + enum dpdbg_info_options { + INFO_OPT_HELP = 0, +--- a/dpdcei_commands.c ++++ b/dpdcei_commands.c +@@ -43,7 +43,7 @@ + #include "mc_v9/fsl_dpdcei.h" + #include "mc_v10/fsl_dpdcei.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpdcei info command options +--- a/dpdmai_commands.c ++++ b/dpdmai_commands.c +@@ -42,7 +42,7 @@ + #include "mc_v9/fsl_dpdmai.h" + #include "mc_v10/fsl_dpdmai.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpdmai info command options +--- a/dpdmux_commands.c ++++ b/dpdmux_commands.c +@@ -47,7 +47,7 @@ + DPDMUX_OPT_BRIDGE_EN | \ + DPDMUX_OPT_CLS_MASK_SUPPORT) + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpdmux info command options +--- a/dpio_commands.c ++++ b/dpio_commands.c +@@ -43,7 +43,7 @@ + #include "mc_v9/fsl_dpio.h" + #include "mc_v10/fsl_dpio.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpio info command options +--- a/dpmac_commands.c ++++ b/dpmac_commands.c +@@ -43,7 +43,7 @@ + #include "mc_v9/fsl_dpmac.h" + #include "mc_v10/fsl_dpmac.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpmac info command options +--- a/dpmcp_commands.c ++++ b/dpmcp_commands.c +@@ -43,7 +43,7 @@ + #include "mc_v9/fsl_dpmcp.h" + #include "mc_v10/fsl_dpmcp.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpmcp info command options +--- a/dpni_commands.c ++++ b/dpni_commands.c +@@ -71,7 +71,7 @@ + DPNI_OPT_SINGLE_SENDER | \ + DPNI_OPT_CUSTOM_CG) + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * max_dist: Maximum distribution size for Rx traffic class; +--- a/dprc_commands.c ++++ b/dprc_commands.c +@@ -52,7 +52,7 @@ + DPRC_CFG_OPT_IRQ_CFG_ALLOWED | \ + DPRC_CFG_OPT_PL_ALLOWED) + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dprc sync command options +--- a/dprc_commands_generate_dpl.c ++++ b/dprc_commands_generate_dpl.c +@@ -189,7 +189,7 @@ static struct container_list *container_ + static struct obj_list *obj_head; + static struct conn_list *conn_head; + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * compare_insert_obj - compare the newly added object node with existing ones, +@@ -273,7 +273,7 @@ static int find_all_obj_desc(uint32_t dp + + int num_child_devices; + int error = 0; +- enum mc_cmd_status mc_status; ++ static enum mc_cmd_status mc_status; + struct container_list *prev_cont; + struct container_list *curr_cont; + struct dprc_attributes dprc_attr; +--- a/dprtc_commands.c ++++ b/dprtc_commands.c +@@ -42,7 +42,7 @@ + #include "mc_v9/fsl_dprtc.h" + #include "mc_v10/fsl_dprtc.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dprtc info command options +--- a/dpseci_commands.c ++++ b/dpseci_commands.c +@@ -43,7 +43,7 @@ + #include "mc_v9/fsl_dpseci.h" + #include "mc_v10/fsl_dpseci.h" + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpseci info command options +--- a/dpsw_commands.c ++++ b/dpsw_commands.c +@@ -50,7 +50,7 @@ + DPSW_OPT_FLOODING_METERING_DIS | \ + DPSW_OPT_METERING_EN) + +-enum mc_cmd_status mc_status; ++static enum mc_cmd_status mc_status; + + /** + * dpsw info command options +--- a/restool.c ++++ b/restool.c +@@ -360,7 +360,7 @@ int find_target_obj_desc(uint32_t dprc_i + { + int num_child_devices; + int error = 0; +- enum mc_cmd_status mc_status; ++ static enum mc_cmd_status mc_status; + + assert(nesting_level <= MAX_DPRC_NESTING); + +@@ -492,7 +492,7 @@ int print_obj_verbose(struct dprc_obj_de + uint16_t obj_handle; + uint32_t irq_mask; + uint32_t irq_status; +- enum mc_cmd_status mc_status; ++ static enum mc_cmd_status mc_status; + int error = 0; + + if (strcmp(target_obj_desc->type, "dprc") == 0 && +@@ -816,7 +816,7 @@ int parse_object_name(const char *obj_na + int open_dprc(uint32_t dprc_id, uint16_t *dprc_handle) + { + int error; +- enum mc_cmd_status mc_status; ++ static enum mc_cmd_status mc_status; + + error = dprc_open(&restool.mc_io, 0, + dprc_id, +@@ -1325,7 +1325,7 @@ int main(int argc, char *argv[]) + const char *cmd_name; + bool mc_io_initialized = false; + bool root_dprc_opened = false; +- enum mc_cmd_status mc_status; ++ static enum mc_cmd_status mc_status; + bool talk_to_mc = true; + + #ifdef DEBUG From 6a2f516d55a7782dd6882fa163e31a0ead70f70f Mon Sep 17 00:00:00 2001 From: David Lam Date: Sun, 19 Sep 2021 22:42:14 -0700 Subject: [PATCH 06/82] 6rd: delete tunnel on interface teardown Delete tunnel on 6rd interface teardown. Should solve problem related to tunnel stuck on restart loop with "Unknown Command" on tunnel restart due to wan connection drop. This patch is similar to the one written by Ansuel on Aug 2, 2021 but the 6rd teardown produces the same symptoms when the network service is restarted. Signed-off-by: David Lam --- package/network/ipv6/6rd/Makefile | 2 +- package/network/ipv6/6rd/files/6rd.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package/network/ipv6/6rd/Makefile b/package/network/ipv6/6rd/Makefile index 9836ae9361..f9c4c6f7a5 100644 --- a/package/network/ipv6/6rd/Makefile +++ b/package/network/ipv6/6rd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=6rd -PKG_RELEASE:=10 +PKG_RELEASE:=11 PKG_LICENSE:=GPL-2.0 include $(INCLUDE_DIR)/package.mk diff --git a/package/network/ipv6/6rd/files/6rd.sh b/package/network/ipv6/6rd/files/6rd.sh index 62a20314d9..3c913e54f1 100644 --- a/package/network/ipv6/6rd/files/6rd.sh +++ b/package/network/ipv6/6rd/files/6rd.sh @@ -82,6 +82,8 @@ proto_6rd_setup() { proto_6rd_teardown() { local cfg="$1" + local link="6rd-$cfg" + ip link del $link } proto_6rd_init_config() { From 753f2f1eaa3d9e3ceed4fb7580b8de7997c4c07b Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 21 Sep 2021 15:06:33 -1000 Subject: [PATCH 07/82] toolchain/gcc: cleanup gcc9 config option This line should have been removed in 244847da "build: remove GCC9 support" but stayed in tree after an incomplete rebase. Fix it. Signed-off-by: Paul Spooren --- toolchain/gcc/Config.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/toolchain/gcc/Config.in b/toolchain/gcc/Config.in index a0fa609172..813c3dfa3e 100644 --- a/toolchain/gcc/Config.in +++ b/toolchain/gcc/Config.in @@ -9,9 +9,6 @@ choice config GCC_USE_VERSION_8 bool "gcc 8.x" - config GCC_USE_VERSION_9 - bool "gcc 9.x" - config GCC_USE_VERSION_10 bool "gcc 10.x" From f9050f1c435bfc8593eeb689ebde5fd04ff41e66 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 20 Sep 2021 19:23:58 -0700 Subject: [PATCH 08/82] bcm63xx: remove memcpy from mac assignment With GCC11, memcpy doesn't work here as it assumes a size of 0. Use ioremap to avoid it. Fixed parameter type to match board_get_mac_address. Signed-off-by: Rosen Penev --- ...32-MIPS-BCM63XX-add-inventel-Livebox-support.patch | 11 ++++++++--- ...32-MIPS-BCM63XX-add-inventel-Livebox-support.patch | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/target/linux/bcm63xx/patches-5.10/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch b/target/linux/bcm63xx/patches-5.10/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch index 0035cee7e9..24b8f68807 100644 --- a/target/linux/bcm63xx/patches-5.10/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch +++ b/target/linux/bcm63xx/patches-5.10/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch @@ -58,7 +58,7 @@ Subject: [PATCH] MIPS: BCM63XX: add inventel Livebox support #endif /* __BOARD_COMMON_H */ --- /dev/null +++ b/arch/mips/bcm63xx/boards/board_livebox.c -@@ -0,0 +1,153 @@ +@@ -0,0 +1,158 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive @@ -130,12 +130,17 @@ Subject: [PATCH] MIPS: BCM63XX: add inventel Livebox support +/* + * register & return a new board mac address + */ -+static int livebox_get_mac_address(u8 *mac) ++static int livebox_get_mac_address(u8 mac[ETH_ALEN]) +{ + u8 *p; + int count; ++ void __iomem *volatile mmio; + -+ memcpy(mac, (u8 *)0xBEBFF377, ETH_ALEN); ++ mmio = ioremap(0x1ebff377, 0x8); ++ if (!mmio) ++ return -EIO; ++ memcpy_fromio(mac, mmio, ETH_ALEN); ++ iounmap(mmio); + + p = mac + ETH_ALEN - 1; + count = mac_addr_used; diff --git a/target/linux/bcm63xx/patches-5.4/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch b/target/linux/bcm63xx/patches-5.4/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch index 0035cee7e9..24b8f68807 100644 --- a/target/linux/bcm63xx/patches-5.4/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch +++ b/target/linux/bcm63xx/patches-5.4/532-MIPS-BCM63XX-add-inventel-Livebox-support.patch @@ -58,7 +58,7 @@ Subject: [PATCH] MIPS: BCM63XX: add inventel Livebox support #endif /* __BOARD_COMMON_H */ --- /dev/null +++ b/arch/mips/bcm63xx/boards/board_livebox.c -@@ -0,0 +1,153 @@ +@@ -0,0 +1,158 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive @@ -130,12 +130,17 @@ Subject: [PATCH] MIPS: BCM63XX: add inventel Livebox support +/* + * register & return a new board mac address + */ -+static int livebox_get_mac_address(u8 *mac) ++static int livebox_get_mac_address(u8 mac[ETH_ALEN]) +{ + u8 *p; + int count; ++ void __iomem *volatile mmio; + -+ memcpy(mac, (u8 *)0xBEBFF377, ETH_ALEN); ++ mmio = ioremap(0x1ebff377, 0x8); ++ if (!mmio) ++ return -EIO; ++ memcpy_fromio(mac, mmio, ETH_ALEN); ++ iounmap(mmio); + + p = mac + ETH_ALEN - 1; + count = mac_addr_used; From 96c7164acd80d07655c2d8dbb3dc4ce556a65e46 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 19 Sep 2021 19:43:41 -0700 Subject: [PATCH 09/82] restool: update to LSDK-20.12 Fixes compilation with both GCC 10 and 11. Switched to AUTORELEASE for simplicity. Removed PKG_VERSION as it's derived from PKG_SOURCE_VERSION. Removed all patches as they are upstream backports. Signed-off-by: Rosen Penev --- .../network/utils/layerscape/restool/Makefile | 5 +- ...restool-fix-get_device_file-function.patch | 102 ------- .../0002-restool-yocto-build-issue.patch | 264 ------------------ 3 files changed, 2 insertions(+), 369 deletions(-) delete mode 100644 package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch delete mode 100644 package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch diff --git a/package/network/utils/layerscape/restool/Makefile b/package/network/utils/layerscape/restool/Makefile index 96ee7ef1cc..b48c033464 100644 --- a/package/network/utils/layerscape/restool/Makefile +++ b/package/network/utils/layerscape/restool/Makefile @@ -8,12 +8,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=restool -PKG_VERSION:=LSDK-20.04 -PKG_RELEASE:=3 +PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://source.codeaurora.org/external/qoriq/qoriq-components/restool -PKG_SOURCE_VERSION:=f0cec094e4c6d1c975b377203a3bf994ba9325a9 +PKG_SOURCE_VERSION:=LSDK-20.12 PKG_MIRROR_HASH:=1863acfaef319e6b277671fead51df0a31bdddb59022080d86b7d81da0bc8490 PKG_FLAGS:=nonshared diff --git a/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch b/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch deleted file mode 100644 index 65d381cbc5..0000000000 --- a/package/network/utils/layerscape/restool/patches/0001-restool-fix-get_device_file-function.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 37f0f1550e7822584b858edde416a694fb902236 Mon Sep 17 00:00:00 2001 -From: Ioana Ciornei -Date: Tue, 31 Jul 2018 13:33:20 +0300 -Subject: [PATCH] restool: fix get_device_file() function - -This patch fixes multiple problems encountered in the -get_device_file() function: - - The deprecated atoi() function is replaced by strtoul - - An invalid memory access was being performed by using - memory from dir->d_name even after closedir(). This is - fixed by a strdup() on the device filename. - - Also, error prints now print any relevant error code. - -Signed-off-by: Ioana Ciornei ---- - restool.c | 44 ++++++++++++++++++++++++++++---------------- - 1 file changed, 28 insertions(+), 16 deletions(-) - ---- a/restool.c -+++ b/restool.c -@@ -1193,8 +1193,13 @@ out: - - static int get_device_file(void) - { -+ int num_dev_files = 0; -+ struct dirent *dir; - int error = 0; -+ char *device; - int num_char; -+ long val; -+ DIR *d; - - memset(restool.device_file, '\0', DEV_FILE_SIZE); - -@@ -1222,10 +1227,6 @@ static int get_device_file(void) - goto out; - } - } else { -- DIR *d; -- struct dirent *dir; -- int num_dev_files = 0; -- char *dprc_index; - - d = opendir("/dev"); - if (!d) { -@@ -1235,26 +1236,34 @@ static int get_device_file(void) - } - while ((dir = readdir(d)) != NULL) { - if (strncmp(dir->d_name, "dprc.", 5) == 0) { -- dprc_index = &dir->d_name[5]; -- num_dev_files += 1; -+ if (num_dev_files == 0) -+ device = strdup(dir->d_name); -+ num_dev_files++; - } - } - closedir(d); - - if (num_dev_files == 1) { -- int temp_len = strlen(dprc_index); -+ errno = 0; -+ val = strtoul(&device[5], NULL, 0); -+ if ((errno == ERANGE && val == LONG_MAX) || -+ ( errno != 0 && val == 0 )) { -+ ERROR_PRINTF("error: device file malformed\n"); -+ error = -1; -+ goto out_free_device;; -+ } -+ restool.root_dprc_id = val; - -- temp_len += 10; -- num_char = sprintf(restool.device_file, "/dev/dprc.%s", -- dprc_index); -- if (num_char != temp_len) { -- ERROR_PRINTF("sprintf error\n"); -+ num_char = snprintf(restool.device_file, DEV_FILE_SIZE, -+ "/dev/dprc.%d", restool.root_dprc_id); -+ if (num_char < 0 || num_char >= DEV_FILE_SIZE) { -+ ERROR_PRINTF("error: device file malformed\n"); - error = -1; -- goto out; -+ goto out_free_device; - } -- restool.root_dprc_id = atoi(dprc_index); -- if (access(restool.device_file, F_OK) != 0) -- printf("no such dev file\n"); -+ error = access(restool.device_file, F_OK); -+ if (error != 0) -+ ERROR_PRINTF("error: access(%s) = %d\n", restool.device_file, error); - } else { - error = -1; - if (num_dev_files == 0) -@@ -1263,6 +1272,9 @@ static int get_device_file(void) - ERROR_PRINTF("error: multiple root containers\n"); - } - } -+ -+out_free_device: -+ free(device); - out: - return error; - } diff --git a/package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch b/package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch deleted file mode 100644 index d38db52dae..0000000000 --- a/package/network/utils/layerscape/restool/patches/0002-restool-yocto-build-issue.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 802764f8ed76f927dff494558332b0b77de7ac65 Mon Sep 17 00:00:00 2001 -From: Ionut-robert Aron -Date: Fri, 16 Oct 2020 11:01:24 +0300 -Subject: [PATCH] restool: yocto build issue - -Prefix 'enum mc_cmd_status mc_status' with 'static' so restool can -compile. - -Signed-off-by: Ionut-robert Aron ---- - dpaiop_commands.c | 2 +- - dpbp_commands.c | 2 +- - dpci_commands.c | 2 +- - dpcon_commands.c | 2 +- - dpdbg_commands.c | 2 +- - dpdcei_commands.c | 2 +- - dpdmai_commands.c | 2 +- - dpdmux_commands.c | 2 +- - dpio_commands.c | 2 +- - dpmac_commands.c | 2 +- - dpmcp_commands.c | 2 +- - dpni_commands.c | 2 +- - dprc_commands.c | 2 +- - dprc_commands_generate_dpl.c | 4 ++-- - dprtc_commands.c | 2 +- - dpseci_commands.c | 2 +- - dpsw_commands.c | 2 +- - restool.c | 8 ++++---- - 18 files changed, 22 insertions(+), 22 deletions(-) - ---- a/dpaiop_commands.c -+++ b/dpaiop_commands.c -@@ -44,7 +44,7 @@ - #include "mc_v9/fsl_dpaiop.h" - #include "mc_v10/fsl_dpaiop.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpaiop info command options ---- a/dpbp_commands.c -+++ b/dpbp_commands.c -@@ -43,7 +43,7 @@ - #include "mc_v9/fsl_dpbp.h" - #include "mc_v10/fsl_dpbp.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpbp info command options ---- a/dpci_commands.c -+++ b/dpci_commands.c -@@ -44,7 +44,7 @@ - #include "mc_v9/fsl_dpci.h" - #include "mc_v10/fsl_dpci.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpci info command options ---- a/dpcon_commands.c -+++ b/dpcon_commands.c -@@ -44,7 +44,7 @@ - #include "mc_v9/fsl_dpcon.h" - #include "mc_v10/fsl_dpcon.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpcon info command options ---- a/dpdbg_commands.c -+++ b/dpdbg_commands.c -@@ -41,7 +41,7 @@ - #include "utils.h" - #include "mc_v10/fsl_dpdbg.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - enum dpdbg_info_options { - INFO_OPT_HELP = 0, ---- a/dpdcei_commands.c -+++ b/dpdcei_commands.c -@@ -43,7 +43,7 @@ - #include "mc_v9/fsl_dpdcei.h" - #include "mc_v10/fsl_dpdcei.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpdcei info command options ---- a/dpdmai_commands.c -+++ b/dpdmai_commands.c -@@ -42,7 +42,7 @@ - #include "mc_v9/fsl_dpdmai.h" - #include "mc_v10/fsl_dpdmai.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpdmai info command options ---- a/dpdmux_commands.c -+++ b/dpdmux_commands.c -@@ -47,7 +47,7 @@ - DPDMUX_OPT_BRIDGE_EN | \ - DPDMUX_OPT_CLS_MASK_SUPPORT) - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpdmux info command options ---- a/dpio_commands.c -+++ b/dpio_commands.c -@@ -43,7 +43,7 @@ - #include "mc_v9/fsl_dpio.h" - #include "mc_v10/fsl_dpio.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpio info command options ---- a/dpmac_commands.c -+++ b/dpmac_commands.c -@@ -43,7 +43,7 @@ - #include "mc_v9/fsl_dpmac.h" - #include "mc_v10/fsl_dpmac.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpmac info command options ---- a/dpmcp_commands.c -+++ b/dpmcp_commands.c -@@ -43,7 +43,7 @@ - #include "mc_v9/fsl_dpmcp.h" - #include "mc_v10/fsl_dpmcp.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpmcp info command options ---- a/dpni_commands.c -+++ b/dpni_commands.c -@@ -71,7 +71,7 @@ - DPNI_OPT_SINGLE_SENDER | \ - DPNI_OPT_CUSTOM_CG) - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * max_dist: Maximum distribution size for Rx traffic class; ---- a/dprc_commands.c -+++ b/dprc_commands.c -@@ -52,7 +52,7 @@ - DPRC_CFG_OPT_IRQ_CFG_ALLOWED | \ - DPRC_CFG_OPT_PL_ALLOWED) - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dprc sync command options ---- a/dprc_commands_generate_dpl.c -+++ b/dprc_commands_generate_dpl.c -@@ -189,7 +189,7 @@ static struct container_list *container_ - static struct obj_list *obj_head; - static struct conn_list *conn_head; - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * compare_insert_obj - compare the newly added object node with existing ones, -@@ -273,7 +273,7 @@ static int find_all_obj_desc(uint32_t dp - - int num_child_devices; - int error = 0; -- enum mc_cmd_status mc_status; -+ static enum mc_cmd_status mc_status; - struct container_list *prev_cont; - struct container_list *curr_cont; - struct dprc_attributes dprc_attr; ---- a/dprtc_commands.c -+++ b/dprtc_commands.c -@@ -42,7 +42,7 @@ - #include "mc_v9/fsl_dprtc.h" - #include "mc_v10/fsl_dprtc.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dprtc info command options ---- a/dpseci_commands.c -+++ b/dpseci_commands.c -@@ -43,7 +43,7 @@ - #include "mc_v9/fsl_dpseci.h" - #include "mc_v10/fsl_dpseci.h" - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpseci info command options ---- a/dpsw_commands.c -+++ b/dpsw_commands.c -@@ -50,7 +50,7 @@ - DPSW_OPT_FLOODING_METERING_DIS | \ - DPSW_OPT_METERING_EN) - --enum mc_cmd_status mc_status; -+static enum mc_cmd_status mc_status; - - /** - * dpsw info command options ---- a/restool.c -+++ b/restool.c -@@ -360,7 +360,7 @@ int find_target_obj_desc(uint32_t dprc_i - { - int num_child_devices; - int error = 0; -- enum mc_cmd_status mc_status; -+ static enum mc_cmd_status mc_status; - - assert(nesting_level <= MAX_DPRC_NESTING); - -@@ -492,7 +492,7 @@ int print_obj_verbose(struct dprc_obj_de - uint16_t obj_handle; - uint32_t irq_mask; - uint32_t irq_status; -- enum mc_cmd_status mc_status; -+ static enum mc_cmd_status mc_status; - int error = 0; - - if (strcmp(target_obj_desc->type, "dprc") == 0 && -@@ -816,7 +816,7 @@ int parse_object_name(const char *obj_na - int open_dprc(uint32_t dprc_id, uint16_t *dprc_handle) - { - int error; -- enum mc_cmd_status mc_status; -+ static enum mc_cmd_status mc_status; - - error = dprc_open(&restool.mc_io, 0, - dprc_id, -@@ -1325,7 +1325,7 @@ int main(int argc, char *argv[]) - const char *cmd_name; - bool mc_io_initialized = false; - bool root_dprc_opened = false; -- enum mc_cmd_status mc_status; -+ static enum mc_cmd_status mc_status; - bool talk_to_mc = true; - - #ifdef DEBUG From 50773c5c989dc921f9fc17bcc48d10293eaebe5a Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 19 Sep 2021 19:30:37 -0700 Subject: [PATCH 10/82] tfp-layerscape: update to LSDK-20.12 Fixes compilation with GCC11. Kept PKG_VERSION as there's some bug that chops off the 12 at the end. Refreshed other patch. Signed-off-by: Rosen Penev --- package/boot/tfa-layerscape/Makefile | 6 +++--- ...ix-create_pbl-and-byte_swap-host-bui.patch | 7 ------- .../tfa-layerscape/patches/010-gcc11.patch | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 package/boot/tfa-layerscape/patches/010-gcc11.patch diff --git a/package/boot/tfa-layerscape/Makefile b/package/boot/tfa-layerscape/Makefile index 6285da6a15..6f0e175885 100644 --- a/package/boot/tfa-layerscape/Makefile +++ b/package/boot/tfa-layerscape/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=tfa-layerscape -PKG_VERSION:=LSDK-20.04-update-290520 +PKG_VERSION:=LSDK-20.12 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://source.codeaurora.org/external/qoriq/qoriq-components/atf -PKG_SOURCE_VERSION:=7d748e6f0ec652ba7c43733dc67a3d0b0217390a -PKG_MIRROR_HASH:=d209c9ad18aac9f18375450b98b8dab00f0382ccb485df14623bf9b72ea1dd9b +PKG_SOURCE_VERSION:=LSDK-20.12 +PKG_MIRROR_HASH:=8e3a0bd33c00657beeb2df88a881b1831aeb790751cacd4c4fdf33ffa01e956e PKG_BUILD_DEPENDS:=tfa-layerscape/host include $(INCLUDE_DIR)/host-build.mk diff --git a/package/boot/tfa-layerscape/patches/003-plat-nxp-tools-fix-create_pbl-and-byte_swap-host-bui.patch b/package/boot/tfa-layerscape/patches/003-plat-nxp-tools-fix-create_pbl-and-byte_swap-host-bui.patch index ce4d9c48bf..2b19d53c71 100644 --- a/package/boot/tfa-layerscape/patches/003-plat-nxp-tools-fix-create_pbl-and-byte_swap-host-bui.patch +++ b/package/boot/tfa-layerscape/patches/003-plat-nxp-tools-fix-create_pbl-and-byte_swap-host-bui.patch @@ -11,8 +11,6 @@ Signed-off-by: Biwen Li plat/nxp/tools/pbl_ch3.mk | 5 ----- 2 files changed, 8 deletions(-) -diff --git a/plat/nxp/tools/pbl_ch2.mk b/plat/nxp/tools/pbl_ch2.mk -index afa43520..ff624dd9 100644 --- a/plat/nxp/tools/pbl_ch2.mk +++ b/plat/nxp/tools/pbl_ch2.mk @@ -20,8 +20,6 @@ ifeq ($(RCW),"") @@ -32,8 +30,6 @@ index afa43520..ff624dd9 100644 ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE} \ -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl ; # Swapping of RCW is required for QSPi Chassis 2 devices -diff --git a/plat/nxp/tools/pbl_ch3.mk b/plat/nxp/tools/pbl_ch3.mk -index 944ae3bb..9aa8f635 100644 --- a/plat/nxp/tools/pbl_ch3.mk +++ b/plat/nxp/tools/pbl_ch3.mk @@ -27,9 +27,6 @@ else @@ -55,6 +51,3 @@ index 944ae3bb..9aa8f635 100644 # Add Block Copy command and populate boot loc ptrfor bl2.bin to RCW ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE} \ -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -f ${BL2_SRC_OFFSET}; --- -2.17.1 - diff --git a/package/boot/tfa-layerscape/patches/010-gcc11.patch b/package/boot/tfa-layerscape/patches/010-gcc11.patch new file mode 100644 index 0000000000..1cdc21a493 --- /dev/null +++ b/package/boot/tfa-layerscape/patches/010-gcc11.patch @@ -0,0 +1,20 @@ +--- a/common/runtime_svc.c ++++ b/common/runtime_svc.c +@@ -38,7 +38,7 @@ uintptr_t handle_runtime_svc(uint32_t smc_fid, + u_register_t x1, x2, x3, x4; + int index; + unsigned int idx; +- const rt_svc_desc_t *rt_svc_descs; ++ rt_svc_desc_t *rt_svc_descs = NULL; + + assert(handle); + idx = get_unique_oen_from_smc_fid(smc_fid); +@@ -48,7 +48,7 @@ uintptr_t handle_runtime_svc(uint32_t smc_fid, + if (index < 0 || index >= (int)RT_SVC_DECS_NUM) + SMC_RET1(handle, SMC_UNK); + +- rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START; ++ memcpy(rt_svc_descs, (rt_svc_desc_t *)RT_SVC_DESCS_START, MAX_RT_SVCS); + + get_smc_params_from_ctx(handle, x1, x2, x3, x4); + From da5bb885e17cf77caea70adcf473f1fb95448553 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 18 Sep 2021 23:16:59 -1000 Subject: [PATCH 11/82] toolchain/gcc: switch to version 11 by default gcc10 seem to increase build size and gcc11 seem to fix that. Compile tests: * all Runtime tests: * ath79 * mpx85xx/p2020 * mvebu * x86/64 Special thanks to Rosen for fixing layerscape & bcm63xx Signed-off-by: Paul Spooren Reviewed-by: Rui Salvaterra Acked-by: Rui Salvaterra Acked-by: Stijn Tintel Acked-by: Aleksander Jan Bajkowski Tested-by: Pawel Dembicki Tested-by: Aleksander Jan Bajkowski --- toolchain/gcc/Config.in | 2 +- toolchain/gcc/Config.version | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/toolchain/gcc/Config.in b/toolchain/gcc/Config.in index 813c3dfa3e..357589e172 100644 --- a/toolchain/gcc/Config.in +++ b/toolchain/gcc/Config.in @@ -2,7 +2,7 @@ choice prompt "GCC compiler Version" if TOOLCHAINOPTS - default GCC_USE_VERSION_10 + default GCC_USE_VERSION_11 help Select the version of gcc you wish to use. diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version index 05cd8f031b..61506b670b 100644 --- a/toolchain/gcc/Config.version +++ b/toolchain/gcc/Config.version @@ -2,12 +2,12 @@ config GCC_VERSION_8 default y if GCC_USE_VERSION_8 bool -config GCC_VERSION_11 - default y if GCC_USE_VERSION_11 +config GCC_VERSION_10 + default y if GCC_USE_VERSION_10 bool config GCC_VERSION string default "8.4.0" if GCC_VERSION_8 - default "11.2.0" if GCC_VERSION_11 - default "10.3.0" + default "10.3.0" if GCC_VERSION_10 + default "11.2.0" From aaec2ad13b18086e2aaf9ca9152827c50e578bc0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 19 Mar 2020 18:31:17 -0700 Subject: [PATCH 12/82] toolchain/musl: update to 1.2.2 This release introduces 64-bit time_t, which is needed to avoid the year 2038 problem. Remove upstream patches. Refreshed others. Rebased features.h file based on latest musl. Signed-off-by: Rosen Penev --- toolchain/musl/common.mk | 6 +- toolchain/musl/include/features.h | 10 ++- .../patches/110-read_timezone_from_fs.patch | 4 +- .../patches/200-add_libssp_nonshared.patch | 8 +- toolchain/musl/patches/300-relative.patch | 2 +- ...ist-unlink-in-pthread_exit-after-all.patch | 51 ----------- ...hreads_minus_1-as-relaxed-atomic-for.patch | 69 -------------- ...own-size-of-some-libc-struct-members.patch | 25 ------ ...pping-for-processes-that-return-to-s.patch | 90 ------------------- ...00-nftw-support-common-gnu-extension.patch | 12 +-- .../700-wcsnrtombs-cve-2020-28928.diff | 63 ------------- .../musl/patches/901-crypt_size_hack.patch | 2 +- 12 files changed, 26 insertions(+), 316 deletions(-) delete mode 100644 toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch delete mode 100644 toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch delete mode 100644 toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch delete mode 100644 toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch delete mode 100644 toolchain/musl/patches/700-wcsnrtombs-cve-2020-28928.diff diff --git a/toolchain/musl/common.mk b/toolchain/musl/common.mk index 68098f5c6a..0f42a9eb60 100644 --- a/toolchain/musl/common.mk +++ b/toolchain/musl/common.mk @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/target.mk PKG_NAME:=musl -PKG_VERSION:=1.1.24 -PKG_RELEASE:=3 +PKG_VERSION:=1.2.2 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://musl.libc.org/releases/ -PKG_HASH:=1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3 +PKG_HASH:=9b969322012d796dc23dda27a35866034fa67d8fb67e0e2c45c913c3d43219dd LIBC_SO_VERSION:=$(PKG_VERSION) PATCH_DIR:=$(PATH_PREFIX)/patches diff --git a/toolchain/musl/include/features.h b/toolchain/musl/include/features.h index edb8cc72d4..e801e2299a 100644 --- a/toolchain/musl/include/features.h +++ b/toolchain/musl/include/features.h @@ -1,10 +1,14 @@ #ifndef _FEATURES_H #define _FEATURES_H -#ifdef _ALL_SOURCE +#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) #define _GNU_SOURCE 1 #endif +#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + #if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) @@ -20,6 +24,8 @@ #if __STDC_VERSION__ >= 199901L || defined(__cplusplus) #define __inline inline +#elif !defined(__GNUC__) +#define __inline #endif #if __STDC_VERSION__ >= 201112L @@ -29,6 +35,8 @@ #define _Noreturn #endif +#define __REDIR(x,y) __typeof__(x) x __asm__(#y) + /* Convenience macros to test the versions of glibc and gcc. Use them like this: #if __GNUC_PREREQ (2,8) diff --git a/toolchain/musl/patches/110-read_timezone_from_fs.patch b/toolchain/musl/patches/110-read_timezone_from_fs.patch index f92781f7ed..a1f54db551 100644 --- a/toolchain/musl/patches/110-read_timezone_from_fs.patch +++ b/toolchain/musl/patches/110-read_timezone_from_fs.patch @@ -1,6 +1,6 @@ --- a/src/time/__tz.c +++ b/src/time/__tz.c -@@ -25,6 +25,9 @@ static int r0[5], r1[5]; +@@ -31,6 +31,9 @@ static int r0[5], r1[5]; static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end; static size_t map_size; @@ -10,7 +10,7 @@ static char old_tz_buf[32]; static char *old_tz = old_tz_buf; static size_t old_tz_size = sizeof old_tz_buf; -@@ -125,6 +128,15 @@ static void do_tzset() +@@ -132,6 +135,15 @@ static void do_tzset() "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; s = getenv("TZ"); diff --git a/toolchain/musl/patches/200-add_libssp_nonshared.patch b/toolchain/musl/patches/200-add_libssp_nonshared.patch index 05bd2fe54a..26a9bfebea 100644 --- a/toolchain/musl/patches/200-add_libssp_nonshared.patch +++ b/toolchain/musl/patches/200-add_libssp_nonshared.patch @@ -7,7 +7,7 @@ Signed-off-by: Steven Barth --- a/Makefile +++ b/Makefile -@@ -66,7 +66,7 @@ CRT_LIBS = $(addprefix lib/,$(notdir $(C +@@ -67,7 +67,7 @@ CRT_LIBS = $(addprefix lib/,$(notdir $(C STATIC_LIBS = lib/libc.a SHARED_LIBS = lib/libc.so TOOL_LIBS = lib/musl-gcc.specs @@ -16,7 +16,7 @@ Signed-off-by: Steven Barth ALL_TOOLS = obj/musl-gcc WRAPCC_GCC = gcc -@@ -86,7 +86,7 @@ else +@@ -88,7 +88,7 @@ else all: $(ALL_LIBS) $(ALL_TOOLS) @@ -25,7 +25,7 @@ Signed-off-by: Steven Barth $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS) -@@ -113,6 +113,8 @@ obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart. +@@ -115,6 +115,8 @@ obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart. obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC @@ -34,7 +34,7 @@ Signed-off-by: Steven Barth OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%)) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3 -@@ -165,6 +167,11 @@ lib/libc.a: $(AOBJS) +@@ -167,6 +169,11 @@ lib/libc.a: $(AOBJS) $(AR) rc $@ $(AOBJS) $(RANLIB) $@ diff --git a/toolchain/musl/patches/300-relative.patch b/toolchain/musl/patches/300-relative.patch index e34e60a09d..7e1eb7d6bc 100644 --- a/toolchain/musl/patches/300-relative.patch +++ b/toolchain/musl/patches/300-relative.patch @@ -1,6 +1,6 @@ --- a/Makefile +++ b/Makefile -@@ -215,7 +215,7 @@ $(DESTDIR)$(includedir)/%: $(srcdir)/inc +@@ -217,7 +217,7 @@ $(DESTDIR)$(includedir)/%: $(srcdir)/inc $(INSTALL) -D -m 644 $< $@ $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so diff --git a/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch b/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch deleted file mode 100644 index d47f2f4108..0000000000 --- a/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 4d5aa20a94a2d3fae3e69289dc23ecafbd0c16c4 Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Fri, 22 May 2020 17:35:14 -0400 -Subject: [PATCH 1/4] reorder thread list unlink in pthread_exit after all - locks - -since the backend for LOCK() skips locking if single-threaded, it's -unsafe to make the process appear single-threaded before the last use -of lock. - -this fixes potential unsynchronized access to a linked list via -__dl_thread_cleanup. ---- - src/thread/pthread_create.c | 19 +++++++++++-------- - 1 file changed, 11 insertions(+), 8 deletions(-) - ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -90,14 +90,7 @@ _Noreturn void __pthread_exit(void *resu - exit(0); - } - -- /* At this point we are committed to thread termination. Unlink -- * the thread from the list. This change will not be visible -- * until the lock is released, which only happens after SYS_exit -- * has been called, via the exit futex address pointing at the lock. */ -- libc.threads_minus_1--; -- self->next->prev = self->prev; -- self->prev->next = self->next; -- self->prev = self->next = self; -+ /* At this point we are committed to thread termination. */ - - /* Process robust list in userspace to handle non-pshared mutexes - * and the detached thread case where the robust list head will -@@ -121,6 +114,16 @@ _Noreturn void __pthread_exit(void *resu - __do_orphaned_stdio_locks(); - __dl_thread_cleanup(); - -+ /* Last, unlink thread from the list. This change will not be visible -+ * until the lock is released, which only happens after SYS_exit -+ * has been called, via the exit futex address pointing at the lock. -+ * This needs to happen after any possible calls to LOCK() that might -+ * skip locking if libc.threads_minus_1 is zero. */ -+ libc.threads_minus_1--; -+ self->next->prev = self->prev; -+ self->prev->next = self->next; -+ self->prev = self->next = self; -+ - /* This atomic potentially competes with a concurrent pthread_detach - * call; the loser is responsible for freeing thread resources. */ - int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); diff --git a/toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch b/toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch deleted file mode 100644 index 4ca51b0be0..0000000000 --- a/toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e01b5939b38aea5ecbe41670643199825874b26c Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Thu, 21 May 2020 23:32:45 -0400 -Subject: [PATCH 2/4] don't use libc.threads_minus_1 as relaxed atomic for - skipping locks - -after all but the last thread exits, the next thread to observe -libc.threads_minus_1==0 and conclude that it can skip locking fails to -synchronize with any changes to memory that were made by the -last-exiting thread. this can produce data races. - -on some archs, at least x86, memory synchronization is unlikely to be -a problem; however, with the inline locks in malloc, skipping the lock -also eliminated the compiler barrier, and caused code that needed to -re-check chunk in-use bits after obtaining the lock to reuse a stale -value, possibly from before the process became single-threaded. this -in turn produced corruption of the heap state. - -some uses of libc.threads_minus_1 remain, especially for allocation of -new TLS in the dynamic linker; otherwise, it could be removed -entirely. it's made non-volatile to reflect that the remaining -accesses are only made under lock on the thread list. - -instead of libc.threads_minus_1, libc.threaded is now used for -skipping locks. the difference is that libc.threaded is permanently -true once an additional thread has been created. this will produce -some performance regression in processes that are mostly -single-threaded but occasionally creating threads. in the future it -may be possible to bring back the full lock-skipping, but more care -needs to be taken to produce a safe design. ---- - src/internal/libc.h | 2 +- - src/malloc/malloc.c | 2 +- - src/thread/__lock.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -21,7 +21,7 @@ struct __libc { - int can_do_threads; - int threaded; - int secure; -- volatile int threads_minus_1; -+ int threads_minus_1; - size_t *auxv; - struct tls_module *tls_head; - size_t tls_size, tls_align, tls_cnt; ---- a/src/malloc/malloc.c -+++ b/src/malloc/malloc.c -@@ -26,7 +26,7 @@ int __malloc_replaced; - - static inline void lock(volatile int *lk) - { -- if (libc.threads_minus_1) -+ if (libc.threaded) - while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1); - } - ---- a/src/thread/__lock.c -+++ b/src/thread/__lock.c -@@ -18,7 +18,7 @@ - - void __lock(volatile int *l) - { -- if (!libc.threads_minus_1) return; -+ if (!libc.threaded) return; - /* fast path: INT_MIN for the lock, +1 for the congestion */ - int current = a_cas(l, 0, INT_MIN + 1); - if (!current) return; diff --git a/toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch b/toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch deleted file mode 100644 index 6650434397..0000000000 --- a/toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch +++ /dev/null @@ -1,25 +0,0 @@ -From f12888e9eb9eed60cc266b899dcafecb4752964a Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Fri, 22 May 2020 17:25:38 -0400 -Subject: [PATCH 3/4] cut down size of some libc struct members - -these are all flags that can be single-byte values. ---- - src/internal/libc.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -18,9 +18,9 @@ struct tls_module { - }; - - struct __libc { -- int can_do_threads; -- int threaded; -- int secure; -+ char can_do_threads; -+ char threaded; -+ char secure; - int threads_minus_1; - size_t *auxv; - struct tls_module *tls_head; diff --git a/toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch b/toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch deleted file mode 100644 index 83a6d0247a..0000000000 --- a/toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 8d81ba8c0bc6fe31136cb15c9c82ef4c24965040 Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Fri, 22 May 2020 17:45:47 -0400 -Subject: [PATCH 4/4] restore lock-skipping for processes that return to - single-threaded state - -the design used here relies on the barrier provided by the first lock -operation after the process returns to single-threaded state to -synchronize with actions by the last thread that exited. by storing -the intent to change modes in the same object used to detect whether -locking is needed, it's possible to avoid an extra (possibly costly) -memory load after the lock is taken. ---- - src/internal/libc.h | 1 + - src/malloc/malloc.c | 5 ++++- - src/thread/__lock.c | 4 +++- - src/thread/pthread_create.c | 8 ++++---- - 4 files changed, 12 insertions(+), 6 deletions(-) - ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -21,6 +21,7 @@ struct __libc { - char can_do_threads; - char threaded; - char secure; -+ volatile signed char need_locks; - int threads_minus_1; - size_t *auxv; - struct tls_module *tls_head; ---- a/src/malloc/malloc.c -+++ b/src/malloc/malloc.c -@@ -26,8 +26,11 @@ int __malloc_replaced; - - static inline void lock(volatile int *lk) - { -- if (libc.threaded) -+ int need_locks = libc.need_locks; -+ if (need_locks) { - while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1); -+ if (need_locks < 0) libc.need_locks = 0; -+ } - } - - static inline void unlock(volatile int *lk) ---- a/src/thread/__lock.c -+++ b/src/thread/__lock.c -@@ -18,9 +18,11 @@ - - void __lock(volatile int *l) - { -- if (!libc.threaded) return; -+ int need_locks = libc.need_locks; -+ if (!need_locks) return; - /* fast path: INT_MIN for the lock, +1 for the congestion */ - int current = a_cas(l, 0, INT_MIN + 1); -+ if (need_locks < 0) libc.need_locks = 0; - if (!current) return; - /* A first spin loop, for medium congestion. */ - for (unsigned i = 0; i < 10; ++i) { ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -118,8 +118,8 @@ _Noreturn void __pthread_exit(void *resu - * until the lock is released, which only happens after SYS_exit - * has been called, via the exit futex address pointing at the lock. - * This needs to happen after any possible calls to LOCK() that might -- * skip locking if libc.threads_minus_1 is zero. */ -- libc.threads_minus_1--; -+ * skip locking if process appears single-threaded. */ -+ if (!--libc.threads_minus_1) libc.need_locks = -1; - self->next->prev = self->prev; - self->prev->next = self->next; - self->prev = self->next = self; -@@ -339,7 +339,7 @@ int __pthread_create(pthread_t *restrict - ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long)))); - - __tl_lock(); -- libc.threads_minus_1++; -+ if (!libc.threads_minus_1++) libc.need_locks = 1; - ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock); - - /* All clone failures translate to EAGAIN. If explicit scheduling -@@ -363,7 +363,7 @@ int __pthread_create(pthread_t *restrict - new->next->prev = new; - new->prev->next = new; - } else { -- libc.threads_minus_1--; -+ if (!--libc.threads_minus_1) libc.need_locks = 0; - } - __tl_unlock(); - __restore_sigs(&set); diff --git a/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch b/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch index 81c96ad76c..2a7436cf84 100644 --- a/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch +++ b/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch @@ -32,9 +32,9 @@ Signed-off-by: Tony Ambardar +#define _GNU_SOURCE #include #include - #include -@@ -63,8 +64,20 @@ static int do_nftw(char *path, int (*fn) - lev.base = k; + #include +@@ -72,8 +73,20 @@ static int do_nftw(char *path, int (*fn) + if (!fd_limit) close(dfd); } - if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) @@ -56,7 +56,7 @@ Signed-off-by: Tony Ambardar for (; h; h = h->chain) if (h->dev == st.st_dev && h->ino == st.st_ino) -@@ -88,7 +101,10 @@ static int do_nftw(char *path, int (*fn) +@@ -101,7 +114,10 @@ static int do_nftw(char *path, int (*fn) strcpy(path+j+1, de->d_name); if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) { closedir(d); @@ -68,7 +68,7 @@ Signed-off-by: Tony Ambardar } } closedir(d); -@@ -98,8 +114,16 @@ static int do_nftw(char *path, int (*fn) +@@ -112,8 +128,16 @@ static int do_nftw(char *path, int (*fn) } path[l] = 0; @@ -87,7 +87,7 @@ Signed-off-by: Tony Ambardar return 0; } -@@ -125,4 +149,5 @@ int nftw(const char *path, int (*fn)(con +@@ -139,4 +163,5 @@ int nftw(const char *path, int (*fn)(con return r; } diff --git a/toolchain/musl/patches/700-wcsnrtombs-cve-2020-28928.diff b/toolchain/musl/patches/700-wcsnrtombs-cve-2020-28928.diff deleted file mode 100644 index 5840dc1aac..0000000000 --- a/toolchain/musl/patches/700-wcsnrtombs-cve-2020-28928.diff +++ /dev/null @@ -1,63 +0,0 @@ ---- a/src/multibyte/wcsnrtombs.c -+++ b/src/multibyte/wcsnrtombs.c -@@ -1,41 +1,33 @@ - #include -+#include -+#include - - size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st) - { -- size_t l, cnt=0, n2; -- char *s, buf[256]; - const wchar_t *ws = *wcs; -- const wchar_t *tmp_ws; -- -- if (!dst) s = buf, n = sizeof buf; -- else s = dst; -- -- while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) { -- if (n2>=n) n2=n; -- tmp_ws = ws; -- l = wcsrtombs(s, &ws, n2, 0); -- if (!(l+1)) { -- cnt = l; -- n = 0; -+ size_t cnt = 0; -+ if (!dst) n=0; -+ while (ws && wn) { -+ char tmp[MB_LEN_MAX]; -+ size_t l = wcrtomb(nn) break; -+ memcpy(dst, tmp, l); -+ } -+ dst += l; - n -= l; - } -- wn = ws ? wn - (ws - tmp_ws) : 0; -- cnt += l; -- } -- if (ws) while (n && wn) { -- l = wcrtomb(s, *ws, 0); -- if ((l+1)<=1) { -- if (!l) ws = 0; -- else cnt = l; -+ if (!*ws) { -+ ws = 0; - break; - } -- ws++; wn--; -- /* safe - this loop runs fewer than sizeof(buf) times */ -- s+=l; n-=l; -+ ws++; -+ wn--; - cnt += l; - } - if (dst) *wcs = ws; diff --git a/toolchain/musl/patches/901-crypt_size_hack.patch b/toolchain/musl/patches/901-crypt_size_hack.patch index 75f196abca..667894a24f 100644 --- a/toolchain/musl/patches/901-crypt_size_hack.patch +++ b/toolchain/musl/patches/901-crypt_size_hack.patch @@ -43,7 +43,7 @@ typedef uint32_t BF_word; typedef int32_t BF_word_signed; -@@ -796,3 +807,4 @@ char *__crypt_blowfish(const char *key, +@@ -804,3 +815,4 @@ char *__crypt_blowfish(const char *key, return "*"; } From b519be1c522da3983277514a81dd83149737fbce Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 19 Mar 2020 18:31:17 -0700 Subject: [PATCH 13/82] toolchain/musl: remove several GNU headers Remove GLOB_ONLYDIR patch. Only fstools relies on it. fstools has been fixed separately. Remove woresize.h file. It seems to be for an old version of GCC. Remove features.h and glibc-types files. Same as above. Remove sys/cdefs.h. This is a deprecated header. Patches to fix packages that use it have already been patched. Tested with all packages in the base tree. They all compile. Signed-off-by: Rosen Penev --- toolchain/musl/include/bits/wordsize.h | 1 - toolchain/musl/include/features.h | 56 --- toolchain/musl/include/sgidefs.h | 73 ---- toolchain/musl/include/sys/cdefs.h | 378 ------------------ toolchain/musl/include/sys/glibc-types.h | 35 -- .../musl/patches/100-add_glob_onlydir.patch | 11 - 6 files changed, 554 deletions(-) delete mode 100644 toolchain/musl/include/bits/wordsize.h delete mode 100644 toolchain/musl/include/features.h delete mode 100644 toolchain/musl/include/sgidefs.h delete mode 100644 toolchain/musl/include/sys/cdefs.h delete mode 100644 toolchain/musl/include/sys/glibc-types.h delete mode 100644 toolchain/musl/patches/100-add_glob_onlydir.patch diff --git a/toolchain/musl/include/bits/wordsize.h b/toolchain/musl/include/bits/wordsize.h deleted file mode 100644 index 2d4cbe8317..0000000000 --- a/toolchain/musl/include/bits/wordsize.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/toolchain/musl/include/features.h b/toolchain/musl/include/features.h deleted file mode 100644 index e801e2299a..0000000000 --- a/toolchain/musl/include/features.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _FEATURES_H -#define _FEATURES_H - -#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ - && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ - && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 700 -#endif - -#if __STDC_VERSION__ >= 199901L -#define __restrict restrict -#elif !defined(__GNUC__) -#define __restrict -#endif - -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -#define __inline inline -#elif !defined(__GNUC__) -#define __inline -#endif - -#if __STDC_VERSION__ >= 201112L -#elif defined(__GNUC__) -#define _Noreturn __attribute__((__noreturn__)) -#else -#define _Noreturn -#endif - -#define __REDIR(x,y) __typeof__(x) x __asm__(#y) - -/* Convenience macros to test the versions of glibc and gcc. - Use them like this: - #if __GNUC_PREREQ (2,8) - ... code requiring gcc 2.8 or later ... - #endif - Note - they won't work for gcc1 or glibc1, since the _MINOR macros - were not defined then. */ -#if defined __GNUC__ && defined __GNUC_MINOR__ -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -# define __GNUC_PREREQ(maj, min) 0 -#endif - -#include - -#endif diff --git a/toolchain/musl/include/sgidefs.h b/toolchain/musl/include/sgidefs.h deleted file mode 100644 index 74509fdbd0..0000000000 --- a/toolchain/musl/include/sgidefs.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (C) 1996, 1997, 1998, 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ralf Baechle . - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _SGIDEFS_H -#define _SGIDEFS_H 1 - -/* - * A crude hack to stop - */ -#undef __ASM_SGIDEFS_H -#define __ASM_SGIDEFS_H - -/* - * And remove any damage it might have already done - */ -#undef _MIPS_ISA_MIPS1 -#undef _MIPS_ISA_MIPS2 -#undef _MIPS_ISA_MIPS3 -#undef _MIPS_ISA_MIPS4 -#undef _MIPS_ISA_MIPS5 -#undef _MIPS_ISA_MIPS32 -#undef _MIPS_ISA_MIPS64 - -#undef _MIPS_SIM_ABI32 -#undef _MIPS_SIM_NABI32 -#undef _MIPS_SIM_ABI64 - -/* - * Definitions for the ISA level - */ -#define _MIPS_ISA_MIPS1 1 -#define _MIPS_ISA_MIPS2 2 -#define _MIPS_ISA_MIPS3 3 -#define _MIPS_ISA_MIPS4 4 -#define _MIPS_ISA_MIPS5 5 -#define _MIPS_ISA_MIPS32 6 -#define _MIPS_ISA_MIPS64 7 - -/* - * Subprogram calling convention - */ -#ifndef _ABIO32 -# define _ABIO32 1 -#endif -#define _MIPS_SIM_ABI32 _ABIO32 - -#ifndef _ABIN32 -# define _ABIN32 2 -#endif -#define _MIPS_SIM_NABI32 _ABIN32 - -#ifndef _ABI64 -# define _ABI64 3 -#endif -#define _MIPS_SIM_ABI64 _ABI64 - -#endif /* sgidefs.h */ diff --git a/toolchain/musl/include/sys/cdefs.h b/toolchain/musl/include/sys/cdefs.h deleted file mode 100644 index e9866700d0..0000000000 --- a/toolchain/musl/include/sys/cdefs.h +++ /dev/null @@ -1,378 +0,0 @@ -/* Copyright (C) 1992-2002, 2004, 2005, 2006, 2007, 2009, 2011, 2012 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_CDEFS_H -#define _SYS_CDEFS_H 1 - -/* We are almost always included from features.h. */ -#ifndef _FEATURES_H -# include -#endif - -/* The GNU libc does not support any K&R compilers or the traditional mode - of ISO C compilers anymore. Check for some of the combinations not - anymore supported. */ -#if defined __GNUC__ && !defined __STDC__ -# error "You need a ISO C conforming compiler to use the glibc headers" -#endif - -/* Some user header file might have defined this before. */ -#undef __P -#undef __PMT - -#ifdef __GNUC__ - -/* All functions, except those with callbacks or those that - synchronize memory, are leaf functions. */ -# if __GNUC_PREREQ (4, 6) && !defined _LIBC -# define __LEAF , __leaf__ -# define __LEAF_ATTR __attribute__ ((__leaf__)) -# else -# define __LEAF -# define __LEAF_ATTR -# endif - -/* GCC can always grok prototypes. For C++ programs we add throw() - to help it optimize the function calls. But this works only with - gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions - as non-throwing using a function attribute since programs can use - the -fexceptions options for C code as well. */ -# if !defined __cplusplus && __GNUC_PREREQ (3, 3) -# define __THROW __attribute__ ((__nothrow__ __LEAF)) -# define __THROWNL __attribute__ ((__nothrow__)) -# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct -# else -# if defined __cplusplus && __GNUC_PREREQ (2,8) -# define __THROW throw () -# define __THROWNL throw () -# define __NTH(fct) __LEAF_ATTR fct throw () -# else -# define __THROW -# define __THROWNL -# define __NTH(fct) fct -# endif -# endif - -#else /* Not GCC. */ - -# define __inline /* No inline functions. */ - -# define __THROW -# define __THROWNL -# define __NTH(fct) fct - -#endif /* GCC. */ - -/* These two macros are not used in glibc anymore. They are kept here - only because some other projects expect the macros to be defined. */ -#define __P(args) args -#define __PMT(args) args - -/* For these things, GCC behaves the ANSI way normally, - and the non-ANSI way under -traditional. */ - -#define __CONCAT(x,y) x ## y -#define __STRING(x) #x - -/* This is not a typedef so `const __ptr_t' does the right thing. */ -#define __ptr_t void * -#define __long_double_t long double - - -/* C++ needs to know that types and declarations are C, not C++. */ -#ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# define __END_DECLS } -#else -# define __BEGIN_DECLS -# define __END_DECLS -#endif - - -/* The standard library needs the functions from the ISO C90 standard - in the std namespace. At the same time we want to be safe for - future changes and we include the ISO C99 code in the non-standard - namespace __c99. The C++ wrapper header take case of adding the - definitions to the global namespace. */ -#if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES -# define __BEGIN_NAMESPACE_STD namespace std { -# define __END_NAMESPACE_STD } -# define __USING_NAMESPACE_STD(name) using std::name; -# define __BEGIN_NAMESPACE_C99 namespace __c99 { -# define __END_NAMESPACE_C99 } -# define __USING_NAMESPACE_C99(name) using __c99::name; -#else -/* For compatibility we do not add the declarations into any - namespace. They will end up in the global namespace which is what - old code expects. */ -# define __BEGIN_NAMESPACE_STD -# define __END_NAMESPACE_STD -# define __USING_NAMESPACE_STD(name) -# define __BEGIN_NAMESPACE_C99 -# define __END_NAMESPACE_C99 -# define __USING_NAMESPACE_C99(name) -#endif - - -/* Support for bounded pointers. */ -#ifndef __BOUNDED_POINTERS__ -# define __bounded /* nothing */ -# define __unbounded /* nothing */ -# define __ptrvalue /* nothing */ -#endif - - -/* Fortify support. */ -#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) -#define __bos0(ptr) __builtin_object_size (ptr, 0) -#define __fortify_function __extern_always_inline __attribute_artificial__ - -#if __GNUC_PREREQ (4,3) -# define __warndecl(name, msg) \ - extern void name (void) __attribute__((__warning__ (msg))) -# define __warnattr(msg) __attribute__((__warning__ (msg))) -# define __errordecl(name, msg) \ - extern void name (void) __attribute__((__error__ (msg))) -#else -# define __warndecl(name, msg) extern void name (void) -# define __warnattr(msg) -# define __errordecl(name, msg) extern void name (void) -#endif - -/* Support for flexible arrays. */ -#if __GNUC_PREREQ (2,97) -/* GCC 2.97 supports C99 flexible array members. */ -# define __flexarr [] -#else -# ifdef __GNUC__ -# define __flexarr [0] -# else -# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -# define __flexarr [] -# else -/* Some other non-C99 compiler. Approximate with [1]. */ -# define __flexarr [1] -# endif -# endif -#endif - - -/* __asm__ ("xyz") is used throughout the headers to rename functions - at the assembly language level. This is wrapped by the __REDIRECT - macro, in order to support compilers that can do this some other - way. When compilers don't support asm-names at all, we have to do - preprocessor tricks instead (which don't have exactly the right - semantics, but it's the best we can do). - - Example: - int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ - -#if defined __GNUC__ && __GNUC__ >= 2 - -# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) -# ifdef __cplusplus -# define __REDIRECT_NTH(name, proto, alias) \ - name proto __THROW __asm__ (__ASMNAME (#alias)) -# define __REDIRECT_NTHNL(name, proto, alias) \ - name proto __THROWNL __asm__ (__ASMNAME (#alias)) -# else -# define __REDIRECT_NTH(name, proto, alias) \ - name proto __asm__ (__ASMNAME (#alias)) __THROW -# define __REDIRECT_NTHNL(name, proto, alias) \ - name proto __asm__ (__ASMNAME (#alias)) __THROWNL -# endif -# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) -# define __ASMNAME2(prefix, cname) __STRING (prefix) cname - -/* -#elif __SOME_OTHER_COMPILER__ - -# define __REDIRECT(name, proto, alias) name proto; \ - _Pragma("let " #name " = " #alias) -*/ -#endif - -/* GCC has various useful declarations that can be made with the - `__attribute__' syntax. All of the ways we use this do fine if - they are omitted for compilers that don't understand it. */ -#if !defined __GNUC__ || __GNUC__ < 2 -# define __attribute__(xyz) /* Ignore */ -#endif - -/* At some point during the gcc 2.96 development the `malloc' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. */ -#if __GNUC_PREREQ (2,96) -# define __attribute_malloc__ __attribute__ ((__malloc__)) -#else -# define __attribute_malloc__ /* Ignore */ -#endif - -/* At some point during the gcc 2.96 development the `pure' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. */ -#if __GNUC_PREREQ (2,96) -# define __attribute_pure__ __attribute__ ((__pure__)) -#else -# define __attribute_pure__ /* Ignore */ -#endif - -/* This declaration tells the compiler that the value is constant. */ -#if __GNUC_PREREQ (2,5) -# define __attribute_const__ __attribute__ ((__const__)) -#else -# define __attribute_const__ /* Ignore */ -#endif - -/* At some point during the gcc 3.1 development the `used' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. */ -#if __GNUC_PREREQ (3,1) -# define __attribute_used__ __attribute__ ((__used__)) -# define __attribute_noinline__ __attribute__ ((__noinline__)) -#else -# define __attribute_used__ __attribute__ ((__unused__)) -# define __attribute_noinline__ /* Ignore */ -#endif - -/* gcc allows marking deprecated functions. */ -#if __GNUC_PREREQ (3,2) -# define __attribute_deprecated__ __attribute__ ((__deprecated__)) -#else -# define __attribute_deprecated__ /* Ignore */ -#endif - -/* At some point during the gcc 2.8 development the `format_arg' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. - If several `format_arg' attributes are given for the same function, in - gcc-3.0 and older, all but the last one are ignored. In newer gccs, - all designated arguments are considered. */ -#if __GNUC_PREREQ (2,8) -# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) -#else -# define __attribute_format_arg__(x) /* Ignore */ -#endif - -/* At some point during the gcc 2.97 development the `strfmon' format - attribute for functions was introduced. We don't want to use it - unconditionally (although this would be possible) since it - generates warnings. */ -#if __GNUC_PREREQ (2,97) -# define __attribute_format_strfmon__(a,b) \ - __attribute__ ((__format__ (__strfmon__, a, b))) -#else -# define __attribute_format_strfmon__(a,b) /* Ignore */ -#endif - -/* The nonull function attribute allows to mark pointer parameters which - must not be NULL. */ -#if __GNUC_PREREQ (3,3) -# define __nonnull(params) __attribute__ ((__nonnull__ params)) -#else -# define __nonnull(params) -#endif - -/* If fortification mode, we warn about unused results of certain - function calls which can lead to problems. */ -#if __GNUC_PREREQ (3,4) -# define __attribute_warn_unused_result__ \ - __attribute__ ((__warn_unused_result__)) -# if __USE_FORTIFY_LEVEL > 0 -# define __wur __attribute_warn_unused_result__ -# endif -#else -# define __attribute_warn_unused_result__ /* empty */ -#endif -#ifndef __wur -# define __wur /* Ignore */ -#endif - -/* Forces a function to be always inlined. */ -#if __GNUC_PREREQ (3,2) -# define __always_inline __inline __attribute__ ((__always_inline__)) -#else -# define __always_inline __inline -#endif - -/* Associate error messages with the source location of the call site rather - than with the source location inside the function. */ -#if __GNUC_PREREQ (4,3) -# define __attribute_artificial__ __attribute__ ((__artificial__)) -#else -# define __attribute_artificial__ /* Ignore */ -#endif - -/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 - inline semantics, unless -fgnu89-inline is used. */ -#if !defined __cplusplus || __GNUC_PREREQ (4,3) -# if defined __GNUC_STDC_INLINE__ || defined __cplusplus -# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) -# define __extern_always_inline \ - extern __always_inline __attribute__ ((__gnu_inline__)) -# else -# define __extern_inline extern __inline -# define __extern_always_inline extern __always_inline -# endif -#endif - -/* GCC 4.3 and above allow passing all anonymous arguments of an - __extern_always_inline function to some other vararg function. */ -#if __GNUC_PREREQ (4,3) -# define __va_arg_pack() __builtin_va_arg_pack () -# define __va_arg_pack_len() __builtin_va_arg_pack_len () -#endif - -/* It is possible to compile containing GCC extensions even if GCC is - run in pedantic mode if the uses are carefully marked using the - `__extension__' keyword. But this is not generally available before - version 2.8. */ -#if !__GNUC_PREREQ (2,8) -# define __extension__ /* Ignore */ -#endif - -/* __restrict is known in EGCS 1.2 and above. */ -#if !__GNUC_PREREQ (2,92) -# define __restrict /* Ignore */ -#endif - -/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is - array_name[restrict] - GCC 3.1 supports this. */ -#if __GNUC_PREREQ (3,1) && !defined __GNUG__ -# define __restrict_arr __restrict -#else -# ifdef __GNUC__ -# define __restrict_arr /* Not supported in old GCC. */ -# else -# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -# define __restrict_arr restrict -# else -/* Some other non-C99 compiler. */ -# define __restrict_arr /* Not supported. */ -# endif -# endif -#endif - -#if __GNUC__ >= 3 -# define __glibc_unlikely(cond) __builtin_expect((cond), 0) -#else -# define __glibc_unlikely(cond) (cond) -#endif - -#endif /* sys/cdefs.h */ diff --git a/toolchain/musl/include/sys/glibc-types.h b/toolchain/musl/include/sys/glibc-types.h deleted file mode 100644 index fa0684ced2..0000000000 --- a/toolchain/musl/include/sys/glibc-types.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __MUSL_GLIBC_TYPES_H -#define __MUSL_GLIBC_TYPES_H - -#include - -/* Convenience types. */ -typedef unsigned char __u_char; -typedef unsigned short int __u_short; -typedef unsigned int __u_int; -typedef unsigned long int __u_long; - -/* Fixed-size types, underlying types depend on word size and compiler. */ -typedef signed char __int8_t; -typedef unsigned char __uint8_t; -typedef signed short int __int16_t; -typedef unsigned short int __uint16_t; -typedef signed int __int32_t; -typedef unsigned int __uint32_t; -#if __WORDSIZE == 64 -typedef signed long int __int64_t; -typedef unsigned long int __uint64_t; -#else -__extension__ typedef signed long long int __int64_t; -__extension__ typedef unsigned long long int __uint64_t; -#endif - -#define __off64_t off_t -#define __loff_t off_t -typedef char *__caddr_t; -#define __locale_t locale_t - -#define __gid_t gid_t -#define __uid_t uid_t - -#endif diff --git a/toolchain/musl/patches/100-add_glob_onlydir.patch b/toolchain/musl/patches/100-add_glob_onlydir.patch deleted file mode 100644 index a784e770df..0000000000 --- a/toolchain/musl/patches/100-add_glob_onlydir.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/include/glob.h -+++ b/include/glob.h -@@ -34,6 +34,8 @@ void globfree(glob_t *); - #define GLOB_TILDE 0x1000 - #define GLOB_TILDE_CHECK 0x4000 - -+#define GLOB_ONLYDIR 0x100 -+ - #define GLOB_NOSPACE 1 - #define GLOB_ABORTED 2 - #define GLOB_NOMATCH 3 From f84b5132660b2e3f2536ca777e59e3ce3dab13ab Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 24 Nov 2020 17:32:34 -0800 Subject: [PATCH 14/82] bpftools: fix compilation with musl 1.2.x A definition for __maybe_inline is needed. Refreshed patches. Signed-off-by: Rosen Penev --- .../utils/bpftools/patches/006-musl-120.patch | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 package/network/utils/bpftools/patches/006-musl-120.patch diff --git a/package/network/utils/bpftools/patches/006-musl-120.patch b/package/network/utils/bpftools/patches/006-musl-120.patch new file mode 100644 index 0000000000..53be466f0b --- /dev/null +++ b/package/network/utils/bpftools/patches/006-musl-120.patch @@ -0,0 +1,20 @@ +--- a/tools/bpf/bpftool/btf_dumper.c ++++ b/tools/bpf/bpftool/btf_dumper.c +@@ -5,6 +5,7 @@ + #include /* for (FILE *) used by json_writer */ + #include + #include ++#include + #include + #include + #include +--- a/tools/bpf/bpftool/map_perf_ring.c ++++ b/tools/bpf/bpftool/map_perf_ring.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include From 71e96532df211380b4d66b8cab709dea11d6dcf2 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 9 Sep 2021 20:36:51 +0200 Subject: [PATCH 15/82] toolchain/musl: Remove extra format attribute patch This patch never went upstream so remove it. GCC should already add such a check to the common functions. Signed-off-by: Hauke Mehrtens --- ...ribute-to-some-function-declarations.patch | 197 ------------------ 1 file changed, 197 deletions(-) delete mode 100644 toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch diff --git a/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch b/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch deleted file mode 100644 index 06aeb34ced..0000000000 --- a/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch +++ /dev/null @@ -1,197 +0,0 @@ -From e6683d001a95d7c3d4d992496f00f77e01fcd268 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 22 Nov 2015 15:04:23 +0100 -Subject: [PATCH v2] Add format attribute to some function declarations - -GCC and Clang are able to check the format arguments given to a -function and warn the user if there is a error in the format arguments -or if there is a potential uncontrolled format string security problem -in the code. GCC does this automatically for some functions like -printf(), but it is also possible to annotate other functions in a way -that it will check them too. This feature is used by glibc for many -functions. This patch adds the attribute to the some functions of musl -expect for these functions where gcc automatically adds it. - -GCC automatically adds checks for these functions: printf, fprintf, -sprintf, scanf, fscanf, sscanf, strftime, vprintf, vfprintf and -vsprintf. - -The documentation from gcc is here: -https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html - -The documentation from Clang is here: -http://clang.llvm.org/docs/AttributeReference.html#format-gnu-format - -Signed-off-by: Hauke Mehrtens ---- - include/err.h | 26 +++++++++++++++++--------- - include/monetary.h | 12 ++++++++++-- - include/stdio.h | 29 ++++++++++++++++++++--------- - include/syslog.h | 12 ++++++++++-- - 4 files changed, 57 insertions(+), 22 deletions(-) - ---- a/include/err.h -+++ b/include/err.h -@@ -8,15 +8,23 @@ - extern "C" { - #endif - --void warn(const char *, ...); --void vwarn(const char *, va_list); --void warnx(const char *, ...); --void vwarnx(const char *, va_list); -+#if __GNUC__ >= 3 -+#define __fp(x, y) __attribute__ ((__format__ (__printf__, x, y))) -+#else -+#define __fp(x, y) -+#endif -+ -+void warn(const char *, ...) __fp(1, 2); -+void vwarn(const char *, va_list) __fp(1, 0); -+void warnx(const char *, ...) __fp(1, 2); -+void vwarnx(const char *, va_list) __fp(1, 0); -+ -+_Noreturn void err(int, const char *, ...) __fp(2, 3); -+_Noreturn void verr(int, const char *, va_list) __fp(2, 0); -+_Noreturn void errx(int, const char *, ...) __fp(2, 3); -+_Noreturn void verrx(int, const char *, va_list) __fp(2, 0); - --_Noreturn void err(int, const char *, ...); --_Noreturn void verr(int, const char *, va_list); --_Noreturn void errx(int, const char *, ...); --_Noreturn void verrx(int, const char *, va_list); -+#undef __fp - - #ifdef __cplusplus - } ---- a/include/monetary.h -+++ b/include/monetary.h -@@ -13,8 +13,16 @@ extern "C" { - - #include - --ssize_t strfmon(char *__restrict, size_t, const char *__restrict, ...); --ssize_t strfmon_l(char *__restrict, size_t, locale_t, const char *__restrict, ...); -+#if __GNUC__ >= 3 -+#define __fsfm(x, y) __attribute__ ((__format__ (__strfmon__, x, y))) -+#else -+#define __fsfm(x, y) -+#endif -+ -+ssize_t strfmon(char *__restrict, size_t, const char *__restrict, ...) __fsfm(3, 4); -+ssize_t strfmon_l(char *__restrict, size_t, locale_t, const char *__restrict, ...) __fsfm(4, 5); -+ -+#undef __fsfm - - #ifdef __cplusplus - } ---- a/include/stdio.h -+++ b/include/stdio.h -@@ -25,6 +25,14 @@ extern "C" { - - #include - -+#if __GNUC__ >= 3 -+#define __fp(x, y) __attribute__ ((__format__ (__printf__, x, y))) -+#define __fs(x, y) __attribute__ ((__format__ (__scanf__, x, y))) -+#else -+#define __fp(x, y) -+#define __fs(x, y) -+#endif -+ - #ifdef __cplusplus - #define NULL 0L - #else -@@ -107,19 +115,19 @@ int puts(const char *); - int printf(const char *__restrict, ...); - int fprintf(FILE *__restrict, const char *__restrict, ...); - int sprintf(char *__restrict, const char *__restrict, ...); --int snprintf(char *__restrict, size_t, const char *__restrict, ...); -+int snprintf(char *__restrict, size_t, const char *__restrict, ...) __fp(3, 4); - - int vprintf(const char *__restrict, __isoc_va_list); - int vfprintf(FILE *__restrict, const char *__restrict, __isoc_va_list); - int vsprintf(char *__restrict, const char *__restrict, __isoc_va_list); --int vsnprintf(char *__restrict, size_t, const char *__restrict, __isoc_va_list); -+int vsnprintf(char *__restrict, size_t, const char *__restrict, __isoc_va_list) __fp(3, 0); - - int scanf(const char *__restrict, ...); - int fscanf(FILE *__restrict, const char *__restrict, ...); - int sscanf(const char *__restrict, const char *__restrict, ...); --int vscanf(const char *__restrict, __isoc_va_list); --int vfscanf(FILE *__restrict, const char *__restrict, __isoc_va_list); --int vsscanf(const char *__restrict, const char *__restrict, __isoc_va_list); -+int vscanf(const char *__restrict, __isoc_va_list) __fs(1, 0); -+int vfscanf(FILE *__restrict, const char *__restrict, __isoc_va_list) __fs(2, 0); -+int vsscanf(const char *__restrict, const char *__restrict, __isoc_va_list) __fs(2, 0); - - void perror(const char *); - -@@ -140,8 +148,8 @@ int pclose(FILE *); - int fileno(FILE *); - int fseeko(FILE *, off_t, int); - off_t ftello(FILE *); --int dprintf(int, const char *__restrict, ...); --int vdprintf(int, const char *__restrict, __isoc_va_list); -+int dprintf(int, const char *__restrict, ...) __fp(2, 3); -+int vdprintf(int, const char *__restrict, __isoc_va_list) __fp(2, 0); - void flockfile(FILE *); - int ftrylockfile(FILE *); - void funlockfile(FILE *); -@@ -180,8 +188,8 @@ int fileno_unlocked(FILE *); - int getw(FILE *); - int putw(int, FILE *); - char *fgetln(FILE *, size_t *); --int asprintf(char **, const char *, ...); --int vasprintf(char **, const char *, __isoc_va_list); -+int asprintf(char **, const char *, ...) __fp(2, 3); -+int vasprintf(char **, const char *, __isoc_va_list) __fp(2, 0); - #endif - - #ifdef _GNU_SOURCE -@@ -203,6 +211,9 @@ typedef struct _IO_cookie_io_functions_t - FILE *fopencookie(void *, const char *, cookie_io_functions_t); - #endif - -+#undef __fp -+#undef __fs -+ - #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) - #define tmpfile64 tmpfile - #define fopen64 fopen ---- a/include/syslog.h -+++ b/include/syslog.h -@@ -56,16 +56,22 @@ extern "C" { - #define LOG_NOWAIT 0x10 - #define LOG_PERROR 0x20 - -+#if __GNUC__ >= 3 -+#define __fp(x, y) __attribute__ ((__format__ (__printf__, x, y))) -+#else -+#define __fp(x, y) -+#endif -+ - void closelog (void); - void openlog (const char *, int, int); - int setlogmask (int); --void syslog (int, const char *, ...); -+void syslog (int, const char *, ...) __fp(2, 3); - - #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) - #define _PATH_LOG "/dev/log" - #define __NEED_va_list - #include --void vsyslog (int, const char *, va_list); -+void vsyslog (int, const char *, va_list) __fp(2, 0); - #if defined(SYSLOG_NAMES) - #define INTERNAL_NOPRI 0x10 - #define INTERNAL_MARK (LOG_NFACILITIES<<3) -@@ -93,6 +99,8 @@ typedef struct { - #endif - #endif - -+#undef __fp -+ - #ifdef __cplusplus - } - #endif From 97bc59a5c051a1ed1fbc40e394bc52e7604b6af0 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 14 Sep 2021 23:58:44 +0200 Subject: [PATCH 16/82] mac80211: Update to backports-5.10.68 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refresh all patches. The removed patches were integrated upstream. This contains fixes for CVE-2020-3702 1. These patches (ath, ath9k, mac80211) were included in kernel versions since 4.14.245 and 4.19.205. They fix security vulnerability CVE-2020-3702 [1] similar to KrØØk, which was found by ESET [2]. Thank you Josef Schlehofer for reporting this problem. [1] https://nvd.nist.gov/vuln/detail/CVE-2020-3702 [2] https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/ Signed-off-by: Hauke Mehrtens --- package/kernel/mac80211/Makefile | 6 +- .../patches/ath/400-ath_move_debug_code.patch | 2 +- .../patches/ath/402-ath_regd_optional.patch | 2 +- .../ath10k/080-ath10k_thermal_config.patch | 2 +- .../930-ath10k_add_tpt_led_trigger.patch | 4 +- ...rolling-support-for-various-chipsets.patch | 2 +- ...75-ath10k-use-tpt-trigger-by-default.patch | 2 +- ...h10k-Try-to-get-mac-address-from-dts.patch | 7 +- ...erpret-requested-txpower-in-EIRP-dom.patch | 4 +- ...power-reduction-for-US-regulatory-do.patch | 2 +- .../ath9k/410-ath9k_allow_adhoc_and_ap.patch | 2 +- ...abled-MFP-capability-unconditionally.patch | 4 +- .../patches/ath9k/501-ath9k_ahb_init.patch | 2 +- .../patches/ath9k/530-ath9k_extra_leds.patch | 2 +- .../ath9k/542-ath9k_debugfs_diag.patch | 8 +-- .../ath9k/543-ath9k_entropy_from_adc.patch | 6 +- ...544-ath9k-ar933x-usb-hang-workaround.patch | 4 +- .../550-ath9k-disable-bands-via-dt.patch | 2 +- .../ath9k/551-ath9k_ubnt_uap_plus_hsr.patch | 6 +- .../ath9k/553-ath9k_of_gpio_mask.patch | 4 +- ...62-brcmfmac-Disable-power-management.patch | 2 +- .../mac80211/patches/brcm/998-survey.patch | 8 +-- .../602-rt2x00-introduce-rt2x00eeprom.patch | 6 +- ...isabling_bands_through_platform_data.patch | 2 +- ...00-allow_disabling_bands_through_dts.patch | 2 +- .../611-rt2x00-add-AP+STA-support.patch | 2 +- .../612-rt2x00-led-tpt-trigger-support.patch | 4 +- ...ave-survey-for-every-channel-visited.patch | 4 +- .../110-mac80211_keep_keys_on_stop_ap.patch | 2 +- .../mac80211/patches/subsys/210-ap_scan.patch | 2 +- ...ort-immediate-reconnect-request-hint.patch | 14 ++-- ...-driver-based-disconnect-with-reconn.patch | 32 ++++----- ...port-to-configure-SAE-PWE-value-to-d.patch | 2 +- ...-get_default_func-move-default-flow-.patch | 2 +- ...ot-maintain-a-backlog-sorted-list-of.patch | 2 +- ...add-rx-decapsulation-offload-support.patch | 26 +++---- ...le-QoS-support-for-nl80211-ctrl-port.patch | 6 +- ...320-mac80211_hwsim-add-6GHz-channels.patch | 4 +- ...211_hwsim-make-6-GHz-channels-usable.patch | 8 +-- ...pply-flow-control-on-management-fram.patch | 2 +- ...set-sk_pacing_shift-for-802.3-txpath.patch | 2 +- ...MPDU-session-check-from-minstrel_ht-.patch | 12 ++-- ...eee80211_tx_h_rate_ctrl-when-dequeue.patch | 8 +-- ...te-control-support-for-encap-offload.patch | 4 +- ...11-minstrel_ht-fix-sample-time-check.patch | 2 +- ...iwlwifi-specific-workaround-that-bro.patch | 51 ------------- ...rting-aggregation-sessions-on-mesh-i.patch | 2 +- ...introduce-aql_enable-node-in-debugfs.patch | 4 +- ...to-a-virtual-time-based-airtime-sche.patch | 22 +++--- ...bling-4-address-mode-on-a-sta-vif-af.patch | 72 ------------------- ...on-API-to-configure-SAR-power-limita.patch | 4 +- ...eck-per-vif-offload_flags-in-Tx-path.patch | 2 +- 52 files changed, 131 insertions(+), 259 deletions(-) delete mode 100644 package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch delete mode 100644 package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index dd39c2d069..0cbcc03d64 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=5.10.42-1 +PKG_VERSION:=5.10.68-1 PKG_RELEASE:=1 -PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.10.42/ -PKG_HASH:=6876520105240844fdb32d1dcdf2bfdea291a37a96f16c892fda3776ba714fcb +PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.10.68/ +PKG_HASH:=bba161b0084590c677a84b80993709e388a3c478f29ed0c475d4fce1b9162968 PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) diff --git a/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch index db10c45104..eacc72776e 100644 --- a/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch +++ b/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch @@ -14,7 +14,7 @@ CFLAGS_trace.o := -I$(src) --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -316,14 +316,7 @@ void _ath_dbg(struct ath_common *common, +@@ -317,14 +317,7 @@ void _ath_dbg(struct ath_common *common, #endif /* CPTCFG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ diff --git a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch index 3c9180b113..bf87d3551a 100644 --- a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch @@ -82,7 +82,7 @@ help --- a/local-symbols +++ b/local-symbols -@@ -86,6 +86,7 @@ ADM8211= +@@ -85,6 +85,7 @@ ADM8211= ATH_COMMON= WLAN_VENDOR_ATH= ATH_DEBUG= diff --git a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch index 9ce44fd288..d183419a47 100644 --- a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch +++ b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch @@ -37,7 +37,7 @@ void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); --- a/local-symbols +++ b/local-symbols -@@ -145,6 +145,7 @@ ATH10K_SNOC= +@@ -144,6 +144,7 @@ ATH10K_SNOC= ATH10K_DEBUG= ATH10K_DEBUGFS= ATH10K_SPECTRAL= diff --git a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch index 74b3292e0c..517a98206d 100644 --- a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch +++ b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -9708,6 +9708,21 @@ static int ath10k_mac_init_rd(struct ath +@@ -9709,6 +9709,21 @@ static int ath10k_mac_init_rd(struct ath return 0; } @@ -22,7 +22,7 @@ int ath10k_mac_register(struct ath10k *ar) { static const u32 cipher_suites[] = { -@@ -10057,6 +10072,12 @@ int ath10k_mac_register(struct ath10k *a +@@ -10058,6 +10073,12 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; diff --git a/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch index fa007e73a1..ce8effe3c3 100644 --- a/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch +++ b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -114,7 +114,7 @@ v13: ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o --- a/local-symbols +++ b/local-symbols -@@ -146,6 +146,7 @@ ATH10K_DEBUG= +@@ -145,6 +145,7 @@ ATH10K_DEBUG= ATH10K_DEBUGFS= ATH10K_SPECTRAL= ATH10K_THERMAL= diff --git a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch index 6da7bfa725..975d9a88a8 100644 --- a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch +++ b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch @@ -42,7 +42,7 @@ Signed-off-by: Mathias Kresin if (ret) --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -10074,7 +10074,7 @@ int ath10k_mac_register(struct ath10k *a +@@ -10075,7 +10075,7 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; #ifdef CPTCFG_MAC80211_LEDS diff --git a/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch b/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch index 5f427f6b8f..2e3c5c30e3 100644 --- a/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch +++ b/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch @@ -16,8 +16,6 @@ Signed-off-by: Ansuel Smith drivers/net/wireless/ath/ath10k/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) -diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c -index 5f4e12196..9ed7b9883 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -8,6 +8,7 @@ @@ -28,7 +26,7 @@ index 5f4e12196..9ed7b9883 100644 #include #include #include -@@ -3062,6 +3068,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar) +@@ -3080,6 +3081,8 @@ static int ath10k_core_probe_fw(struct a device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr)); @@ -37,6 +35,3 @@ index 5f4e12196..9ed7b9883 100644 ret = ath10k_core_init_firmware_features(ar); if (ret) { ath10k_err(ar, "fatal problem with firmware features: %d\n", --- -2.27.0 - diff --git a/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch index 385eea0116..406d03e2fe 100644 --- a/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch +++ b/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch @@ -8,7 +8,7 @@ This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411. --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2977,7 +2977,8 @@ void ath9k_hw_apply_txpower(struct ath_h +@@ -2979,7 +2979,8 @@ void ath9k_hw_apply_txpower(struct ath_h { struct ath_regulatory *reg = ath9k_hw_regulatory(ah); struct ieee80211_channel *channel; @@ -18,7 +18,7 @@ This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411. u16 ctl = NO_CTL; if (!chan) -@@ -2989,9 +2990,14 @@ void ath9k_hw_apply_txpower(struct ath_h +@@ -2991,9 +2992,14 @@ void ath9k_hw_apply_txpower(struct ath_h channel = chan->chan; chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER); new_pwr = min_t(int, chan_pwr, reg->power_limit); diff --git a/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch index 0c3edc1260..12cbd27e1a 100644 --- a/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch +++ b/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2996,6 +2996,10 @@ void ath9k_hw_apply_txpower(struct ath_h +@@ -2998,6 +2998,10 @@ void ath9k_hw_apply_txpower(struct ath_h if (ant_gain > max_gain) ant_reduction = ant_gain - max_gain; diff --git a/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch index 17dd8f6597..0d06ed2434 100644 --- a/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -830,6 +830,7 @@ static const struct ieee80211_iface_limi +@@ -827,6 +827,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_AP) }, { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) }, diff --git a/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch b/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch index ea94b52385..fd17f13560 100644 --- a/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch +++ b/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch @@ -14,7 +14,7 @@ Signed-off-by: David Bauer --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -927,6 +927,7 @@ static void ath9k_set_hw_capab(struct at +@@ -924,6 +924,7 @@ static void ath9k_set_hw_capab(struct at ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); @@ -22,7 +22,7 @@ Signed-off-by: David Bauer if (ath9k_ps_enable) ieee80211_hw_set(hw, SUPPORTS_PS); -@@ -939,9 +940,6 @@ static void ath9k_set_hw_capab(struct at +@@ -936,9 +937,6 @@ static void ath9k_set_hw_capab(struct at IEEE80211_RADIOTAP_MCS_HAVE_STBC; } diff --git a/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch index b9c784eb25..f5c62e3baa 100644 --- a/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch +++ b/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1143,25 +1143,25 @@ static int __init ath9k_init(void) +@@ -1140,25 +1140,25 @@ static int __init ath9k_init(void) { int error; diff --git a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch index 5fd5c73a2f..884593e24a 100644 --- a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch @@ -181,7 +181,7 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1055,7 +1055,7 @@ int ath9k_init_device(u16 devid, struct +@@ -1052,7 +1052,7 @@ int ath9k_init_device(u16 devid, struct #ifdef CPTCFG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ diff --git a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch index f93a6fe5cd..0e75b86cbf 100644 --- a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -84,7 +84,7 @@ bool reset_power_on; bool htc_reset_init; -@@ -1076,6 +1084,7 @@ void ath9k_hw_check_nav(struct ath_hw *a +@@ -1077,6 +1085,7 @@ void ath9k_hw_check_nav(struct ath_hw *a bool ath9k_hw_check_alive(struct ath_hw *ah); bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); @@ -94,7 +94,7 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1883,6 +1883,20 @@ u32 ath9k_hw_get_tsf_offset(struct times +@@ -1882,6 +1882,20 @@ u32 ath9k_hw_get_tsf_offset(struct times } EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); @@ -115,7 +115,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata, bool fastcc) { -@@ -2091,6 +2105,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -2090,6 +2104,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ar9003_hw_disable_phy_restart(ah); ath9k_hw_apply_gpio_override(ah); @@ -125,7 +125,7 @@ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -531,6 +531,11 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -536,6 +536,11 @@ irqreturn_t ath_isr(int irq, void *dev) if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) return IRQ_HANDLED; diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch index 0d938a3730..0b0d4d30c4 100644 --- a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -818,7 +818,8 @@ static void ath9k_init_txpower_limits(st +@@ -815,7 +815,8 @@ static void ath9k_init_txpower_limits(st if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); @@ -65,7 +65,7 @@ } static const struct ieee80211_iface_limit if_limits[] = { -@@ -1015,6 +1016,18 @@ static void ath9k_set_hw_capab(struct at +@@ -1012,6 +1013,18 @@ static void ath9k_set_hw_capab(struct at wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); } @@ -84,7 +84,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -1060,6 +1073,8 @@ int ath9k_init_device(u16 devid, struct +@@ -1057,6 +1070,8 @@ int ath9k_init_device(u16 devid, struct ARRAY_SIZE(ath9k_tpt_blink)); #endif diff --git a/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch index 93eee34b64..2d2b837072 100644 --- a/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch +++ b/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch @@ -40,7 +40,7 @@ return true; } -@@ -1861,8 +1880,14 @@ static int ath9k_hw_do_fastcc(struct ath +@@ -1860,8 +1879,14 @@ static int ath9k_hw_do_fastcc(struct ath if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); @@ -55,7 +55,7 @@ return -EINVAL; } -@@ -2116,6 +2141,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -2115,6 +2140,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ath9k_hw_set_radar_params(ah); } diff --git a/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch b/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch index 7d3a334c42..db9a09c98b 100644 --- a/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch +++ b/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -627,6 +627,12 @@ static int ath9k_of_init(struct ath_soft +@@ -626,6 +626,12 @@ static int ath9k_of_init(struct ath_soft ath_dbg(common, CONFIG, "parsing configuration from OF node\n"); diff --git a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch index cd2bdbf1a0..c98222781d 100644 --- a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch +++ b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch @@ -339,7 +339,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); -@@ -652,6 +653,7 @@ void ath_reset_work(struct work_struct * +@@ -657,6 +658,7 @@ void ath_reset_work(struct work_struct * static int ath9k_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; @@ -347,7 +347,7 @@ struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; -@@ -730,6 +732,11 @@ static int ath9k_start(struct ieee80211_ +@@ -735,6 +737,11 @@ static int ath9k_start(struct ieee80211_ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } @@ -371,7 +371,7 @@ --- a/local-symbols +++ b/local-symbols -@@ -113,6 +113,7 @@ ATH9K_WOW= +@@ -112,6 +112,7 @@ ATH9K_WOW= ATH9K_RFKILL= ATH9K_CHANNEL_CONTEXT= ATH9K_PCOEM= diff --git a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch index 8e0041e3ef..f015913588 100644 --- a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch +++ b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -654,6 +654,12 @@ static int ath9k_of_init(struct ath_soft +@@ -651,6 +651,12 @@ static int ath9k_of_init(struct ath_soft return 0; } @@ -13,7 +13,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -757,6 +763,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -754,6 +760,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_hw; diff --git a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch index e640849e6a..774656f1fd 100644 --- a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2958,6 +2958,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2961,6 +2961,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */ diff --git a/package/kernel/mac80211/patches/brcm/998-survey.patch b/package/kernel/mac80211/patches/brcm/998-survey.patch index 9e9f4bbf8f..25a12c783e 100644 --- a/package/kernel/mac80211/patches/brcm/998-survey.patch +++ b/package/kernel/mac80211/patches/brcm/998-survey.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2910,6 +2910,63 @@ done: +@@ -2913,6 +2913,63 @@ done: } static int @@ -64,7 +64,7 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, int idx, u8 *mac, struct station_info *sinfo) { -@@ -3005,6 +3062,7 @@ static s32 brcmf_inform_single_bss(struc +@@ -3008,6 +3065,7 @@ static s32 brcmf_inform_single_bss(struc struct brcmu_chan ch; u16 channel; u32 freq; @@ -72,7 +72,7 @@ u16 notify_capability; u16 notify_interval; u8 *notify_ie; -@@ -3029,6 +3087,17 @@ static s32 brcmf_inform_single_bss(struc +@@ -3032,6 +3090,17 @@ static s32 brcmf_inform_single_bss(struc band = NL80211_BAND_5GHZ; freq = ieee80211_channel_to_frequency(channel, band); @@ -90,7 +90,7 @@ bss_data.chan = ieee80211_get_channel(wiphy, freq); bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20; bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime()); -@@ -5515,6 +5584,7 @@ static struct cfg80211_ops brcmf_cfg8021 +@@ -5518,6 +5587,7 @@ static struct cfg80211_ops brcmf_cfg8021 .leave_ibss = brcmf_cfg80211_leave_ibss, .get_station = brcmf_cfg80211_get_station, .dump_station = brcmf_cfg80211_dump_station, diff --git a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch index 1c52132da6..8628c1063a 100644 --- a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch @@ -1,6 +1,6 @@ --- a/local-symbols +++ b/local-symbols -@@ -333,6 +333,7 @@ RT2X00_LIB_FIRMWARE= +@@ -332,6 +332,7 @@ RT2X00_LIB_FIRMWARE= RT2X00_LIB_CRYPTO= RT2X00_LIB_LEDS= RT2X00_LIB_DEBUGFS= @@ -127,7 +127,7 @@ DECLARE_KFIFO_PTR(txstatus_fifo, u32); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1406,6 +1406,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de +@@ -1402,6 +1402,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep); @@ -138,7 +138,7 @@ /* * Let the driver probe the device to detect the capabilities. */ -@@ -1549,6 +1553,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ +@@ -1545,6 +1549,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ * Free the driver data. */ kfree(rt2x00dev->drv_data); diff --git a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch index 6a8e594d5e..e12f074669 100644 --- a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch +++ b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -12,7 +12,7 @@ #endif /* _RT2X00_PLATFORM_H */ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1012,6 +1012,22 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1008,6 +1008,22 @@ static int rt2x00lib_probe_hw_modes(stru unsigned int num_rates; unsigned int i; diff --git a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch index ff8b2c947b..31f2f0261f 100644 --- a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch +++ b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1016,6 +1016,16 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1013,6 +1013,16 @@ static int rt2x00lib_probe_hw_modes(stru struct ieee80211_rate *rates; unsigned int num_rates; unsigned int i; diff --git a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch index 88d6dd559b..01a3851fcc 100644 --- a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch +++ b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1344,7 +1344,7 @@ static inline void rt2x00lib_set_if_comb +@@ -1341,7 +1341,7 @@ static inline void rt2x00lib_set_if_comb */ if_limit = &rt2x00dev->if_limits_ap; if_limit->max = rt2x00dev->ops->max_ap_intf; diff --git a/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch index fca1fb2cd4..079c87e33c 100644 --- a/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch +++ b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch @@ -11,7 +11,7 @@ Tested-by: Christoph Krapp --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1129,6 +1129,19 @@ static void rt2x00lib_remove_hw(struct r +@@ -1126,6 +1126,19 @@ static void rt2x00lib_remove_hw(struct r kfree(rt2x00dev->spec.channels_info); } @@ -31,7 +31,7 @@ Tested-by: Christoph Krapp static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; -@@ -1210,6 +1223,10 @@ static int rt2x00lib_probe_hw(struct rt2 +@@ -1207,6 +1220,10 @@ static int rt2x00lib_probe_hw(struct rt2 #undef RT2X00_TASKLET_INIT diff --git a/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch index 31a7baeee7..80e2a2f6ae 100644 --- a/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch +++ b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch @@ -141,7 +141,7 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1057,6 +1057,12 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1054,6 +1054,12 @@ static int rt2x00lib_probe_hw_modes(stru if (!rates) goto exit_free_channels; @@ -154,7 +154,7 @@ /* * Initialize Rate list. */ -@@ -1108,6 +1114,8 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1105,6 +1111,8 @@ static int rt2x00lib_probe_hw_modes(stru return 0; diff --git a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch index 665231a040..c6fafb77b1 100644 --- a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch +++ b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch @@ -2,7 +2,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1288,7 +1288,6 @@ static int ieee80211_stop_ap(struct wiph +@@ -1307,7 +1307,6 @@ static int ieee80211_stop_ap(struct wiph sdata->vif.bss_conf.ftmr_params = NULL; __sta_info_flush(sdata, true); diff --git a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch index ee49942459..f8c3821c51 100644 --- a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch +++ b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch @@ -1,6 +1,6 @@ --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2444,7 +2444,7 @@ static int ieee80211_scan(struct wiphy * +@@ -2463,7 +2463,7 @@ static int ieee80211_scan(struct wiphy * * the frames sent while scanning on other channel will be * lost) */ diff --git a/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch b/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch index 8fe8723cfe..425b6895b1 100644 --- a/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch +++ b/package/kernel/mac80211/patches/subsys/300-cfg80211-support-immediate-reconnect-request-hint.patch @@ -33,7 +33,7 @@ Signed-off-by: Johannes Berg * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -2734,7 +2734,7 @@ static void ieee80211_report_disconnect( +@@ -2725,7 +2725,7 @@ static void ieee80211_report_disconnect( }; if (tx) @@ -42,7 +42,7 @@ Signed-off-by: Johannes Berg else cfg80211_rx_mlme_mgmt(sdata->dev, buf, len); -@@ -4724,7 +4724,8 @@ void ieee80211_mgd_quiesce(struct ieee80 +@@ -4719,7 +4719,8 @@ void ieee80211_mgd_quiesce(struct ieee80 if (ifmgd->auth_data) ieee80211_destroy_auth_data(sdata, false); cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, @@ -152,7 +152,7 @@ Signed-off-by: Johannes Berg }; /* policy for the key attributes */ -@@ -15903,7 +15904,7 @@ static void nl80211_send_mlme_event(stru +@@ -15902,7 +15903,7 @@ static void nl80211_send_mlme_event(stru const u8 *buf, size_t len, enum nl80211_commands cmd, gfp_t gfp, int uapsd_queues, const u8 *req_ies, @@ -161,7 +161,7 @@ Signed-off-by: Johannes Berg { struct sk_buff *msg; void *hdr; -@@ -15925,6 +15926,9 @@ static void nl80211_send_mlme_event(stru +@@ -15924,6 +15925,9 @@ static void nl80211_send_mlme_event(stru nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies))) goto nla_put_failure; @@ -171,7 +171,7 @@ Signed-off-by: Johannes Berg if (uapsd_queues >= 0) { struct nlattr *nla_wmm = nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME); -@@ -15953,7 +15957,8 @@ void nl80211_send_rx_auth(struct cfg8021 +@@ -15952,7 +15956,8 @@ void nl80211_send_rx_auth(struct cfg8021 size_t len, gfp_t gfp) { nl80211_send_mlme_event(rdev, netdev, buf, len, @@ -181,7 +181,7 @@ Signed-off-by: Johannes Berg } void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, -@@ -15963,23 +15968,25 @@ void nl80211_send_rx_assoc(struct cfg802 +@@ -15962,23 +15967,25 @@ void nl80211_send_rx_assoc(struct cfg802 { nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE, gfp, uapsd_queues, @@ -212,7 +212,7 @@ Signed-off-by: Johannes Berg } void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, -@@ -16010,7 +16017,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct +@@ -16009,7 +16016,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1, diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch index 31621ebf11..cc9602df71 100644 --- a/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch +++ b/package/kernel/mac80211/patches/subsys/301-mac80211-support-driver-based-disconnect-with-reconn.patch @@ -47,7 +47,7 @@ Signed-off-by: Johannes Berg struct ieee80211_mgd_auth_data *auth_data; --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -2725,7 +2725,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get) +@@ -2716,7 +2716,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get) static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata, const u8 *buf, size_t len, bool tx, @@ -56,7 +56,7 @@ Signed-off-by: Johannes Berg { struct ieee80211_event event = { .type = MLME_EVENT, -@@ -2734,7 +2734,7 @@ static void ieee80211_report_disconnect( +@@ -2725,7 +2725,7 @@ static void ieee80211_report_disconnect( }; if (tx) @@ -65,7 +65,7 @@ Signed-off-by: Johannes Berg else cfg80211_rx_mlme_mgmt(sdata->dev, buf, len); -@@ -2756,13 +2756,18 @@ static void __ieee80211_disconnect(struc +@@ -2747,13 +2747,18 @@ static void __ieee80211_disconnect(struc tx = !sdata->csa_block_tx; @@ -89,7 +89,7 @@ Signed-off-by: Johannes Berg tx, frame_buf); mutex_lock(&local->mtx); sdata->vif.csa_active = false; -@@ -2775,7 +2780,9 @@ static void __ieee80211_disconnect(struc +@@ -2766,7 +2771,9 @@ static void __ieee80211_disconnect(struc mutex_unlock(&local->mtx); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx, @@ -100,7 +100,7 @@ Signed-off-by: Johannes Berg sdata_unlock(sdata); } -@@ -2794,6 +2801,13 @@ static void ieee80211_beacon_connection_ +@@ -2785,6 +2792,13 @@ static void ieee80211_beacon_connection_ sdata_info(sdata, "Connection to AP %pM lost\n", ifmgd->bssid); __ieee80211_disconnect(sdata); @@ -114,7 +114,7 @@ Signed-off-by: Johannes Berg } else { ieee80211_mgd_probe_ap(sdata, true); } -@@ -2832,6 +2846,21 @@ void ieee80211_connection_loss(struct ie +@@ -2823,6 +2837,21 @@ void ieee80211_connection_loss(struct ie } EXPORT_SYMBOL(ieee80211_connection_loss); @@ -136,7 +136,7 @@ Signed-off-by: Johannes Berg static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, bool assoc) -@@ -3135,7 +3164,7 @@ static void ieee80211_rx_mgmt_deauth(str +@@ -3126,7 +3155,7 @@ static void ieee80211_rx_mgmt_deauth(str ieee80211_set_disassoc(sdata, 0, 0, false, NULL); ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, @@ -145,7 +145,7 @@ Signed-off-by: Johannes Berg return; } -@@ -3184,7 +3213,8 @@ static void ieee80211_rx_mgmt_disassoc(s +@@ -3175,7 +3204,8 @@ static void ieee80211_rx_mgmt_disassoc(s ieee80211_set_disassoc(sdata, 0, 0, false, NULL); @@ -155,7 +155,7 @@ Signed-off-by: Johannes Berg } static void ieee80211_get_rates(struct ieee80211_supported_band *sband, -@@ -4204,7 +4234,8 @@ static void ieee80211_rx_mgmt_beacon(str +@@ -4199,7 +4229,8 @@ static void ieee80211_rx_mgmt_beacon(str true, deauth_buf); ieee80211_report_disconnect(sdata, deauth_buf, sizeof(deauth_buf), true, @@ -165,7 +165,7 @@ Signed-off-by: Johannes Berg return; } -@@ -4349,7 +4380,7 @@ static void ieee80211_sta_connection_los +@@ -4344,7 +4375,7 @@ static void ieee80211_sta_connection_los tx, frame_buf); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, @@ -174,7 +174,7 @@ Signed-off-by: Johannes Berg } static int ieee80211_auth(struct ieee80211_sub_if_data *sdata) -@@ -5439,7 +5470,8 @@ int ieee80211_mgd_auth(struct ieee80211_ +@@ -5434,7 +5465,8 @@ int ieee80211_mgd_auth(struct ieee80211_ ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, @@ -184,7 +184,7 @@ Signed-off-by: Johannes Berg } sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); -@@ -5511,7 +5543,8 @@ int ieee80211_mgd_assoc(struct ieee80211 +@@ -5506,7 +5538,8 @@ int ieee80211_mgd_assoc(struct ieee80211 ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, @@ -194,7 +194,7 @@ Signed-off-by: Johannes Berg } if (ifmgd->auth_data && !ifmgd->auth_data->done) { -@@ -5810,7 +5843,7 @@ int ieee80211_mgd_deauth(struct ieee8021 +@@ -5809,7 +5842,7 @@ int ieee80211_mgd_deauth(struct ieee8021 ieee80211_destroy_auth_data(sdata, false); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, @@ -203,7 +203,7 @@ Signed-off-by: Johannes Berg return 0; } -@@ -5830,7 +5863,7 @@ int ieee80211_mgd_deauth(struct ieee8021 +@@ -5829,7 +5862,7 @@ int ieee80211_mgd_deauth(struct ieee8021 ieee80211_destroy_assoc_data(sdata, false, true); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, @@ -212,7 +212,7 @@ Signed-off-by: Johannes Berg return 0; } -@@ -5845,7 +5878,7 @@ int ieee80211_mgd_deauth(struct ieee8021 +@@ -5844,7 +5877,7 @@ int ieee80211_mgd_deauth(struct ieee8021 req->reason_code, tx, frame_buf); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, @@ -221,7 +221,7 @@ Signed-off-by: Johannes Berg return 0; } -@@ -5878,7 +5911,7 @@ int ieee80211_mgd_disassoc(struct ieee80 +@@ -5877,7 +5910,7 @@ int ieee80211_mgd_disassoc(struct ieee80 frame_buf); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true, diff --git a/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch b/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch index acfdae0f5b..da88d1413d 100644 --- a/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch +++ b/package/kernel/mac80211/patches/subsys/302-cfg80211-Add-support-to-configure-SAE-PWE-value-to-d.patch @@ -59,7 +59,7 @@ Signed-off-by: Johannes Berg [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, }; -@@ -9764,6 +9767,12 @@ static int nl80211_crypto_settings(struc +@@ -9763,6 +9766,12 @@ static int nl80211_crypto_settings(struc nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]); } diff --git a/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch b/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch index 33dbb5eb90..6adca7d70d 100644 --- a/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch +++ b/package/kernel/mac80211/patches/subsys/311-net-fq_impl-drop-get_default_func-move-default-flow-.patch @@ -132,7 +132,7 @@ Signed-off-by: Felix Fietkau codel_vars_init(&txqi->def_cvars); codel_stats_init(&txqi->cstats); __skb_queue_head_init(&txqi->frags); -@@ -3310,8 +3297,7 @@ static bool ieee80211_amsdu_aggregate(st +@@ -3332,8 +3319,7 @@ static bool ieee80211_amsdu_aggregate(st */ tin = &txqi->tin; diff --git a/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch b/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch index 08e5cbb5b9..793c76abec 100644 --- a/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch +++ b/package/kernel/mac80211/patches/subsys/312-net-fq_impl-do-not-maintain-a-backlog-sorted-list-of.patch @@ -306,7 +306,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -3364,8 +3364,6 @@ out_recalc: +@@ -3386,8 +3386,6 @@ out_recalc: if (head->len != orig_len) { flow->backlog += head->len - orig_len; tin->backlog_bytes += head->len - orig_len; diff --git a/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch b/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch index b8bb2930f5..49af25eb1d 100644 --- a/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch +++ b/package/kernel/mac80211/patches/subsys/315-mac80211-add-rx-decapsulation-offload-support.patch @@ -132,7 +132,7 @@ Signed-off-by: Felix Fietkau #endif /* __MAC80211_DRIVER_OPS */ --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -835,7 +835,7 @@ static const struct net_device_ops ieee8 +@@ -856,7 +856,7 @@ static const struct net_device_ops ieee8 }; @@ -141,7 +141,7 @@ Signed-off-by: Felix Fietkau { switch (iftype) { /* P2P GO and client are mapped to AP/STATION types */ -@@ -855,7 +855,7 @@ static bool ieee80211_set_sdata_offload_ +@@ -876,7 +876,7 @@ static bool ieee80211_set_sdata_offload_ flags = sdata->vif.offload_flags; if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && @@ -150,7 +150,7 @@ Signed-off-by: Felix Fietkau flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED; if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && -@@ -868,10 +868,21 @@ static bool ieee80211_set_sdata_offload_ +@@ -889,10 +889,21 @@ static bool ieee80211_set_sdata_offload_ flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; } @@ -172,7 +172,7 @@ Signed-off-by: Felix Fietkau return true; } -@@ -889,7 +900,7 @@ static void ieee80211_set_vif_encap_ops( +@@ -910,7 +921,7 @@ static void ieee80211_set_vif_encap_ops( } if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || @@ -183,7 +183,7 @@ Signed-off-by: Felix Fietkau enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -4198,7 +4198,9 @@ void ieee80211_check_fast_rx(struct sta_ +@@ -4195,7 +4195,9 @@ void ieee80211_check_fast_rx(struct sta_ .vif_type = sdata->vif.type, .control_port_protocol = sdata->control_port_protocol, }, *old, *new = NULL; @@ -193,7 +193,7 @@ Signed-off-by: Felix Fietkau /* use sparse to check that we don't return without updating */ __acquire(check_fast_rx); -@@ -4311,6 +4313,17 @@ void ieee80211_check_fast_rx(struct sta_ +@@ -4308,6 +4310,17 @@ void ieee80211_check_fast_rx(struct sta_ if (assign) new = kmemdup(&fastrx, sizeof(fastrx), GFP_KERNEL); @@ -211,7 +211,7 @@ Signed-off-by: Felix Fietkau spin_lock_bh(&sta->lock); old = rcu_dereference_protected(sta->fast_rx, true); rcu_assign_pointer(sta->fast_rx, new); -@@ -4357,6 +4370,108 @@ void ieee80211_check_fast_rx_iface(struc +@@ -4354,6 +4367,108 @@ void ieee80211_check_fast_rx_iface(struc mutex_unlock(&local->sta_mtx); } @@ -320,7 +320,7 @@ Signed-off-by: Felix Fietkau static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, struct ieee80211_fast_rx *fast_rx) { -@@ -4377,9 +4492,6 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4374,9 +4489,6 @@ static bool ieee80211_invoke_fast_rx(str } addrs __aligned(2); struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write * to a common data structure; drivers can implement that per queue * but we don't have that information in mac80211 -@@ -4453,32 +4565,6 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4450,32 +4562,6 @@ static bool ieee80211_invoke_fast_rx(str pskb_trim(skb, skb->len - fast_rx->icv_len)) goto drop; @@ -363,7 +363,7 @@ Signed-off-by: Felix Fietkau if (rx->key && !ieee80211_has_protected(hdr->frame_control)) goto drop; -@@ -4490,12 +4576,6 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4487,12 +4573,6 @@ static bool ieee80211_invoke_fast_rx(str return true; } @@ -376,7 +376,7 @@ Signed-off-by: Felix Fietkau /* do the header conversion - first grab the addresses */ ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs); ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); -@@ -4504,62 +4584,14 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4501,62 +4581,14 @@ static bool ieee80211_invoke_fast_rx(str /* push the addresses in front */ memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); @@ -443,7 +443,7 @@ Signed-off-by: Felix Fietkau stats->dropped++; return true; } -@@ -4613,6 +4645,47 @@ static bool ieee80211_prepare_and_rx_han +@@ -4610,6 +4642,47 @@ static bool ieee80211_prepare_and_rx_han return true; } @@ -491,7 +491,7 @@ Signed-off-by: Felix Fietkau /* * This is the actual Rx frames handler. as it belongs to Rx path it must * be called with rcu_read_lock protection. -@@ -4850,15 +4923,20 @@ void ieee80211_rx_list(struct ieee80211_ +@@ -4847,15 +4920,20 @@ void ieee80211_rx_list(struct ieee80211_ * if it was previously present. * Also, frames with less than 16 bytes are dropped. */ diff --git a/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch b/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch index 4be011ffec..43ac9a0cef 100644 --- a/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch +++ b/package/kernel/mac80211/patches/subsys/316-mac80211-enable-QoS-support-for-nl80211-ctrl-port.patch @@ -69,7 +69,7 @@ Signed-off-by: Johannes Berg tx->sta = sta_info_get_bss(sdata, hdr->addr1); } if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) -@@ -5421,6 +5419,7 @@ int ieee80211_tx_control_port(struct wip +@@ -5443,6 +5441,7 @@ int ieee80211_tx_control_port(struct wip { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; @@ -77,7 +77,7 @@ Signed-off-by: Johannes Berg struct sk_buff *skb; struct ethhdr *ehdr; u32 ctrl_flags = 0; -@@ -5443,8 +5442,7 @@ int ieee80211_tx_control_port(struct wip +@@ -5465,8 +5464,7 @@ int ieee80211_tx_control_port(struct wip if (cookie) ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; @@ -87,7 +87,7 @@ Signed-off-by: Johannes Berg skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(struct ethhdr) + len); -@@ -5461,10 +5459,25 @@ int ieee80211_tx_control_port(struct wip +@@ -5483,10 +5481,25 @@ int ieee80211_tx_control_port(struct wip ehdr->h_proto = proto; skb->dev = dev; diff --git a/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch b/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch index a7c09f00bc..cbc55c9381 100644 --- a/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch +++ b/package/kernel/mac80211/patches/subsys/320-mac80211_hwsim-add-6GHz-channels.patch @@ -102,7 +102,7 @@ Signed-off-by: Johannes Berg struct ieee80211_channel channels_s1g[ARRAY_SIZE(hwsim_channels_s1g)]; struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; struct ieee80211_iface_combination if_combination; -@@ -578,7 +647,8 @@ struct mac80211_hwsim_data { +@@ -579,7 +648,8 @@ struct mac80211_hwsim_data { struct ieee80211_channel *channel; unsigned long next_start, start, end; } survey_data[ARRAY_SIZE(hwsim_channels_2ghz) + @@ -112,7 +112,7 @@ Signed-off-by: Johannes Berg struct ieee80211_channel *channel; u64 beacon_int /* beacon interval in us */; -@@ -3149,6 +3219,8 @@ static int mac80211_hwsim_new_radio(stru +@@ -3172,6 +3242,8 @@ static int mac80211_hwsim_new_radio(stru sizeof(hwsim_channels_2ghz)); memcpy(data->channels_5ghz, hwsim_channels_5ghz, sizeof(hwsim_channels_5ghz)); diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch b/package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch index 4bac10eefe..c21d4446ab 100644 --- a/package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch +++ b/package/kernel/mac80211/patches/subsys/321-mac80211_hwsim-make-6-GHz-channels-usable.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -2968,15 +2968,19 @@ static void mac80211_hwsim_he_capab(stru +@@ -2990,15 +2990,19 @@ static void mac80211_hwsim_he_capab(stru { u16 n_iftype_data; @@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau return; } -@@ -3265,6 +3269,12 @@ static int mac80211_hwsim_new_radio(stru +@@ -3288,6 +3292,12 @@ static int mac80211_hwsim_new_radio(stru sband->vht_cap.vht_mcs.tx_mcs_map = sband->vht_cap.vht_mcs.rx_mcs_map; break; @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau case NL80211_BAND_S1GHZ: memcpy(&sband->s1g_cap, &hwsim_s1g_cap, sizeof(sband->s1g_cap)); -@@ -3275,6 +3285,13 @@ static int mac80211_hwsim_new_radio(stru +@@ -3298,6 +3308,13 @@ static int mac80211_hwsim_new_radio(stru continue; } @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau sband->ht_cap.ht_supported = true; sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD | -@@ -3288,10 +3305,6 @@ static int mac80211_hwsim_new_radio(stru +@@ -3311,10 +3328,6 @@ static int mac80211_hwsim_new_radio(stru sband->ht_cap.mcs.rx_mask[0] = 0xff; sband->ht_cap.mcs.rx_mask[1] = 0xff; sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; diff --git a/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch b/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch index 8d094a3632..3ce6ceacd5 100644 --- a/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch +++ b/package/kernel/mac80211/patches/subsys/371-mac80211-don-t-apply-flow-control-on-management-fram.patch @@ -48,7 +48,7 @@ Signed-off-by: Johannes Berg spin_unlock_bh(&fq->lock); } -@@ -3844,6 +3853,9 @@ bool ieee80211_txq_airtime_check(struct +@@ -3866,6 +3875,9 @@ bool ieee80211_txq_airtime_check(struct if (!txq->sta) return true; diff --git a/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch b/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch index 5bc1469a3f..c8f3047a34 100644 --- a/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch +++ b/package/kernel/mac80211/patches/subsys/372-mac80211-set-sk_pacing_shift-for-802.3-txpath.patch @@ -9,7 +9,7 @@ Signed-off-by: Lorenzo Bianconi --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4171,6 +4171,9 @@ static bool ieee80211_tx_8023(struct iee +@@ -4193,6 +4193,9 @@ static bool ieee80211_tx_8023(struct iee unsigned long flags; int q = info->hw_queue; diff --git a/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch b/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch index 031f8e1636..07f5bb5263 100644 --- a/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch +++ b/package/kernel/mac80211/patches/subsys/374-mac80211-move-A-MPDU-session-check-from-minstrel_ht-.patch @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau struct rate_control_ops { --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1153,29 +1153,6 @@ minstrel_downgrade_prob_rate(struct mins +@@ -1144,29 +1144,6 @@ minstrel_downgrade_prob_rate(struct mins } static void @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, void *priv_sta, struct ieee80211_tx_status *st) { -@@ -1477,10 +1454,6 @@ minstrel_ht_get_rate(void *priv, struct +@@ -1461,10 +1438,6 @@ minstrel_ht_get_rate(void *priv, struct struct minstrel_priv *mp = priv; u16 sample_idx; @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau info->flags |= mi->tx_flags; #ifdef CPTCFG_MAC80211_DEBUGFS -@@ -1894,6 +1867,7 @@ static u32 minstrel_ht_get_expected_thro +@@ -1870,6 +1843,7 @@ static u32 minstrel_ht_get_expected_thro static const struct rate_control_ops mac80211_minstrel_ht = { .name = "minstrel_ht", @@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau .rate_init = minstrel_ht_rate_init, --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -3931,6 +3931,29 @@ void ieee80211_txq_schedule_start(struct +@@ -3953,6 +3953,29 @@ void ieee80211_txq_schedule_start(struct } EXPORT_SYMBOL(ieee80211_txq_schedule_start); @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau void __ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev, u32 info_flags, -@@ -3961,6 +3984,8 @@ void __ieee80211_subif_start_xmit(struct +@@ -3983,6 +4006,8 @@ void __ieee80211_subif_start_xmit(struct skb_get_hash(skb); } @@ -115,7 +115,7 @@ Signed-off-by: Felix Fietkau if (sta) { struct ieee80211_fast_tx *fast_tx; -@@ -4224,6 +4249,8 @@ static void ieee80211_8023_xmit(struct i +@@ -4246,6 +4271,8 @@ static void ieee80211_8023_xmit(struct i memset(info, 0, sizeof(*info)); diff --git a/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch b/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch index cf84fca68a..26f7f59296 100644 --- a/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch +++ b/package/kernel/mac80211/patches/subsys/375-mac80211-call-ieee80211_tx_h_rate_ctrl-when-dequeue.patch @@ -29,7 +29,7 @@ Signed-off-by: Ryder Lee CALL_TXH(ieee80211_tx_h_michael_mic_add); CALL_TXH(ieee80211_tx_h_sequence); CALL_TXH(ieee80211_tx_h_fragment); -@@ -3382,15 +3383,21 @@ out: +@@ -3404,15 +3405,21 @@ out: * Can be called while the sta lock is held. Anything that can cause packets to * be generated will cause deadlock! */ @@ -55,7 +55,7 @@ Signed-off-by: Ryder Lee if (key) info->control.hw_key = &key->conf; -@@ -3439,6 +3446,8 @@ static void ieee80211_xmit_fast_finish(s +@@ -3461,6 +3468,8 @@ static void ieee80211_xmit_fast_finish(s break; } } @@ -64,7 +64,7 @@ Signed-off-by: Ryder Lee } static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, -@@ -3542,24 +3551,17 @@ static bool ieee80211_xmit_fast(struct i +@@ -3564,24 +3573,17 @@ static bool ieee80211_xmit_fast(struct i tx.sta = sta; tx.key = fast_tx->key; @@ -97,7 +97,7 @@ Signed-off-by: Ryder Lee if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, -@@ -3670,8 +3672,12 @@ begin: +@@ -3692,8 +3694,12 @@ begin: (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) pn_offs = ieee80211_hdrlen(hdr->frame_control); diff --git a/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch b/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch index f22b0d9849..5d390990cd 100644 --- a/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch +++ b/package/kernel/mac80211/patches/subsys/376-mac80211-add-rate-control-support-for-encap-offload.patch @@ -81,7 +81,7 @@ Signed-off-by: Ryder Lee tx->sta->tx_stats.last_rate = txrc.reported_rate; } else if (tx->sta) tx->sta->tx_stats.last_rate = txrc.reported_rate; -@@ -3660,8 +3662,16 @@ begin: +@@ -3682,8 +3684,16 @@ begin: else info->flags &= ~IEEE80211_TX_CTL_AMPDU; @@ -101,7 +101,7 @@ Signed-off-by: Ryder Lee struct sta_info *sta = container_of(txq->sta, struct sta_info, --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -6728,4 +6728,22 @@ struct sk_buff *ieee80211_get_fils_disco +@@ -6733,4 +6733,22 @@ struct sk_buff *ieee80211_get_fils_disco struct sk_buff * ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw, struct ieee80211_vif *vif); diff --git a/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch b/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch index d4b327c69c..054662f3ef 100644 --- a/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch +++ b/package/kernel/mac80211/patches/subsys/377-mac80211-minstrel_ht-fix-sample-time-check.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -1466,7 +1466,7 @@ minstrel_ht_get_rate(void *priv, struct +@@ -1450,7 +1450,7 @@ minstrel_ht_get_rate(void *priv, struct (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) return; diff --git a/package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch b/package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch deleted file mode 100644 index a5ad377e6f..0000000000 --- a/package/kernel/mac80211/patches/subsys/378-mac80211-remove-iwlwifi-specific-workaround-that-bro.patch +++ /dev/null @@ -1,51 +0,0 @@ -From: Felix Fietkau -Date: Sat, 19 Jun 2021 12:10:14 +0200 -Subject: [PATCH] mac80211: remove iwlwifi specific workaround that broke sta - NDP tx - -Sending nulldata packets is important for sw AP link probing and detecting -4-address mode links. The checks that dropped these packets were apparently -added to work around an iwlwifi firmware bug with multi-TID aggregation. - -Fixes: 41cbb0f5a295 ("mac80211: add support for HE") -Cc: stable@vger.kernel.org -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -@@ -1085,6 +1085,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv - if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA)) - return -1; - -+ if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->he_cap.has_he) -+ return -1; -+ - if (unlikely(ieee80211_is_probe_resp(fc))) - iwl_mvm_probe_resp_set_noa(mvm, skb); - ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1094,11 +1094,6 @@ void ieee80211_send_nullfunc(struct ieee - struct ieee80211_hdr_3addr *nullfunc; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - -- /* Don't send NDPs when STA is connected HE */ -- if (sdata->vif.type == NL80211_IFTYPE_STATION && -- !(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) -- return; -- - skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, - !ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP)); - if (!skb) -@@ -1130,10 +1125,6 @@ static void ieee80211_send_4addr_nullfun - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) - return; - -- /* Don't send NDPs when connected HE */ -- if (!(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) -- return; -- - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); - if (!skb) - return; diff --git a/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch index 2ad083f150..c7902d6542 100644 --- a/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch +++ b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch @@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau if (tid_tx) { bool queued; -@@ -3947,29 +3977,6 @@ void ieee80211_txq_schedule_start(struct +@@ -3969,29 +3999,6 @@ void ieee80211_txq_schedule_start(struct } EXPORT_SYMBOL(ieee80211_txq_schedule_start); diff --git a/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch b/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch index b21b671c10..073782188a 100644 --- a/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch +++ b/package/kernel/mac80211/patches/subsys/380-mac80211-introduce-aql_enable-node-in-debugfs.patch @@ -90,7 +90,7 @@ Signed-off-by: Johannes Berg * don't cast (use the static inlines below), but we keep --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -3887,6 +3887,8 @@ void __ieee80211_schedule_txq(struct iee +@@ -3909,6 +3909,8 @@ void __ieee80211_schedule_txq(struct iee } EXPORT_SYMBOL(__ieee80211_schedule_txq); @@ -99,7 +99,7 @@ Signed-off-by: Johannes Berg bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { -@@ -3896,6 +3898,9 @@ bool ieee80211_txq_airtime_check(struct +@@ -3918,6 +3920,9 @@ bool ieee80211_txq_airtime_check(struct if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) return true; diff --git a/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch b/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch index ba78f7a142..2fe12771c0 100644 --- a/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch +++ b/package/kernel/mac80211/patches/subsys/382-mac80211-Switch-to-a-virtual-time-based-airtime-sche.patch @@ -50,7 +50,7 @@ Signed-off-by: Johannes Berg --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -6552,9 +6552,6 @@ static inline void ieee80211_txq_schedul +@@ -6557,9 +6557,6 @@ static inline void ieee80211_txq_schedul { } @@ -60,7 +60,7 @@ Signed-off-by: Johannes Berg /** * ieee80211_schedule_txq - schedule a TXQ for transmission * -@@ -6567,11 +6564,7 @@ void __ieee80211_schedule_txq(struct iee +@@ -6572,11 +6569,7 @@ void __ieee80211_schedule_txq(struct iee * The driver may call this function if it has buffered packets for * this TXQ internally. */ @@ -73,7 +73,7 @@ Signed-off-by: Johannes Berg /** * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq() -@@ -6583,12 +6576,8 @@ ieee80211_schedule_txq(struct ieee80211_ +@@ -6588,12 +6581,8 @@ ieee80211_schedule_txq(struct ieee80211_ * The driver may set force=true if it has buffered packets for this TXQ * internally. */ @@ -90,7 +90,7 @@ Signed-off-by: Johannes Berg * ieee80211_txq_may_transmit - check whether TXQ is allowed to transmit --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1442,6 +1442,38 @@ static void sta_apply_mesh_params(struct +@@ -1461,6 +1461,38 @@ static void sta_apply_mesh_params(struct #endif } @@ -129,7 +129,7 @@ Signed-off-by: Johannes Berg static int sta_apply_parameters(struct ieee80211_local *local, struct sta_info *sta, struct station_parameters *params) -@@ -1629,7 +1661,8 @@ static int sta_apply_parameters(struct i +@@ -1648,7 +1680,8 @@ static int sta_apply_parameters(struct i sta_apply_mesh_params(local, sta, params); if (params->airtime_weight) @@ -590,7 +590,7 @@ Signed-off-by: Johannes Berg void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -2067,6 +2067,9 @@ int ieee80211_if_add(struct ieee80211_lo +@@ -2088,6 +2088,9 @@ int ieee80211_if_add(struct ieee80211_lo } } @@ -655,7 +655,7 @@ Signed-off-by: Johannes Berg } for (i = 0; i < IEEE80211_NUM_TIDS; i++) -@@ -1898,24 +1894,59 @@ void ieee80211_sta_set_buffered(struct i +@@ -1893,24 +1889,59 @@ void ieee80211_sta_set_buffered(struct i } EXPORT_SYMBOL(ieee80211_sta_set_buffered); @@ -727,7 +727,7 @@ Signed-off-by: Johannes Berg } EXPORT_SYMBOL(ieee80211_sta_register_airtime); -@@ -2364,7 +2395,7 @@ void sta_set_sinfo(struct sta_info *sta, +@@ -2354,7 +2385,7 @@ void sta_set_sinfo(struct sta_info *sta, } if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT))) { @@ -839,7 +839,7 @@ Signed-off-by: Johannes Berg } void ieee80211_txq_set_params(struct ieee80211_local *local) -@@ -3797,102 +3796,259 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue); +@@ -3819,102 +3818,259 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue); struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac) { struct ieee80211_local *local = hw_to_local(hw); @@ -1161,7 +1161,7 @@ Signed-off-by: Johannes Berg struct ieee80211_local *local = hw_to_local(hw); if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) -@@ -3907,15 +4063,12 @@ bool ieee80211_txq_airtime_check(struct +@@ -3929,15 +4085,12 @@ bool ieee80211_txq_airtime_check(struct if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) return true; @@ -1179,7 +1179,7 @@ Signed-off-by: Johannes Berg return true; return false; -@@ -3925,60 +4078,59 @@ EXPORT_SYMBOL(ieee80211_txq_airtime_chec +@@ -3947,60 +4100,59 @@ EXPORT_SYMBOL(ieee80211_txq_airtime_chec bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { diff --git a/package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch b/package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch deleted file mode 100644 index c1f77ff5d9..0000000000 --- a/package/kernel/mac80211/patches/subsys/383-mac80211-fix-enabling-4-address-mode-on-a-sta-vif-af.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Felix Fietkau -Date: Fri, 2 Jul 2021 06:57:53 +0200 -Subject: [PATCH] mac80211: fix enabling 4-address mode on a sta vif after - assoc - -Notify the driver about the 4-address mode change and also send a nulldata -packet to the AP to notify it about the change - -Fixes: 1ff4e8f2dec8 ("mac80211: notify the driver when a sta uses 4-address mode") -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -152,6 +152,8 @@ static int ieee80211_change_iface(struct - struct vif_params *params) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct ieee80211_local *local = sdata->local; -+ struct sta_info *sta; - int ret; - - ret = ieee80211_if_change_type(sdata, type); -@@ -162,7 +164,24 @@ static int ieee80211_change_iface(struct - RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); - ieee80211_check_fast_rx_iface(sdata); - } else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) { -+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -+ -+ if (params->use_4addr == ifmgd->use_4addr) -+ return 0; -+ - sdata->u.mgd.use_4addr = params->use_4addr; -+ if (!ifmgd->associated) -+ return 0; -+ -+ mutex_lock(&local->sta_mtx); -+ sta = sta_info_get(sdata, ifmgd->bssid); -+ if (sta) -+ drv_sta_set_4addr(local, sdata, &sta->sta, -+ params->use_4addr); -+ mutex_unlock(&local->sta_mtx); -+ -+ if (params->use_4addr) -+ ieee80211_send_4addr_nullfunc(local, sdata); - } - - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2215,6 +2215,8 @@ void ieee80211_dynamic_ps_timer(struct t - void ieee80211_send_nullfunc(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - bool powersave); -+void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata); - void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, - struct ieee80211_hdr *hdr, bool ack, u16 tx_time); - ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1115,8 +1115,8 @@ void ieee80211_send_nullfunc(struct ieee - ieee80211_tx_skb(sdata, skb); - } - --static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, -- struct ieee80211_sub_if_data *sdata) -+void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata) - { - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; diff --git a/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch b/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch index 0c9ae3595d..a47e29794c 100644 --- a/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch +++ b/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch @@ -222,7 +222,7 @@ Signed-off-by: Johannes Berg /* done */ state->split_start = 0; -@@ -14713,6 +14783,111 @@ static void nl80211_post_doit(__genl_con +@@ -14712,6 +14782,111 @@ static void nl80211_post_doit(__genl_con } } @@ -334,7 +334,7 @@ Signed-off-by: Johannes Berg static __genl_const struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, -@@ -15576,6 +15751,14 @@ static const struct genl_small_ops nl802 +@@ -15575,6 +15750,14 @@ static const struct genl_small_ops nl802 .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, diff --git a/package/kernel/mac80211/patches/subsys/386-mac80211-check-per-vif-offload_flags-in-Tx-path.patch b/package/kernel/mac80211/patches/subsys/386-mac80211-check-per-vif-offload_flags-in-Tx-path.patch index cfad1c3927..c2cc16cd48 100644 --- a/package/kernel/mac80211/patches/subsys/386-mac80211-check-per-vif-offload_flags-in-Tx-path.patch +++ b/package/kernel/mac80211/patches/subsys/386-mac80211-check-per-vif-offload_flags-in-Tx-path.patch @@ -14,7 +14,7 @@ Signed-off-by: Johannes Berg --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -3309,6 +3309,9 @@ static bool ieee80211_amsdu_aggregate(st +@@ -3331,6 +3331,9 @@ static bool ieee80211_amsdu_aggregate(st if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) return false; From f83e927b8744c0642fd61245935c4bb20e0b6f33 Mon Sep 17 00:00:00 2001 From: Timo Sigurdsson Date: Sat, 26 Jun 2021 13:04:49 +0200 Subject: [PATCH 17/82] fstools: ensure filesystems are mounted before log service starts Currently, the fstab service starts after the log service which breaks the ability to write a persistent log file to a filesystem mounted by the fstab service. Thus, change the start order of the fstab service so it starts right before the log service. Fixes: b131853 ("ubox: update to latest git revision") Signed-off-by: Timo Sigurdsson [set to 11 to be explicitly before log, not only alphabetically, SPDX] Signed-off-by: Paul Spooren --- package/system/fstools/files/fstab.init | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package/system/fstools/files/fstab.init b/package/system/fstools/files/fstab.init index 08d5601bee..03a3993494 100644 --- a/package/system/fstools/files/fstab.init +++ b/package/system/fstools/files/fstab.init @@ -1,7 +1,9 @@ #!/bin/sh /etc/rc.common -# (C) 2013 openwrt.org +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2013-2020 OpenWrt.org -START=40 +START=11 boot() { /sbin/block mount From f48ced582dd33b6d0921f5851c1ea2cef2ff730c Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 21 Sep 2021 15:14:40 -1000 Subject: [PATCH 18/82] toolchain/binutils: switch to version 2.37 by default Compile tests: * all Runtime tests: * ipq806x/generic * lantiq/mt7621 * lantiq/xrx200 * x86/64 Signed-off-by: Paul Spooren Tested-by: Paul Spooren Tested-by: Rosen Penev Tested-by: Andre Heider Tested-by: Ansuel Smith Tested-by: Rui Salvaterra Signed-off-by: Paul Spooren --- toolchain/binutils/Config.in | 2 +- toolchain/binutils/Config.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in index 0f69a003d3..493b6e4f5a 100644 --- a/toolchain/binutils/Config.in +++ b/toolchain/binutils/Config.in @@ -2,7 +2,7 @@ choice prompt "Binutils Version" if TOOLCHAINOPTS - default BINUTILS_USE_VERSION_2_36_1 + default BINUTILS_USE_VERSION_2_37 help Select the version of binutils you wish to use. diff --git a/toolchain/binutils/Config.version b/toolchain/binutils/Config.version index a1622abd96..db727b78bc 100644 --- a/toolchain/binutils/Config.version +++ b/toolchain/binutils/Config.version @@ -8,10 +8,10 @@ config BINUTILS_VERSION_2_35_2 bool config BINUTILS_VERSION_2_36_1 - default y if !TOOLCHAINOPTS bool config BINUTILS_VERSION_2_37 + default y if !TOOLCHAINOPTS bool config BINUTILS_VERSION From 4eb4c3c469a7b38266957d8a14d27e894e4da494 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Tue, 6 Jul 2021 00:56:21 +0200 Subject: [PATCH 19/82] scripts: add missing regex for dl_cleanup script Regex xxx-YYYY-MM-DD-GIT_SHASUM was missing. Add the new regex to improve and better find outdated package. This also fix a bug where some bug were incorrectly detected as packagename-yyyy-mm-dd instead of packagename due to them be parsed by the wrong parser Example: openwrt-keyring-2021-02-20-49283916.tar.xz Signed-off-by: Ansuel Smith [added example in commit message] Signed-off-by: Paul Spooren --- scripts/dl_cleanup.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/dl_cleanup.py b/scripts/dl_cleanup.py index 1acb049582..83269e68e5 100755 --- a/scripts/dl_cleanup.py +++ b/scripts/dl_cleanup.py @@ -62,6 +62,13 @@ def parseVer_r(match, filepath): progversion = (int(match.group(2)) << 64) return (progname, progversion) +def parseVer_ymd_GIT_SHASUM(match, filepath): + progname = match.group(1) + progversion = (int(match.group(2)) << 64) |\ + (int(match.group(3)) << 48) |\ + (int(match.group(4)) << 32) + return (progname, progversion) + def parseVer_ymd(match, filepath): progname = match.group(1) progversion = (int(match.group(2)) << 64) |\ @@ -90,6 +97,7 @@ extensions = ( versionRegex = ( (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)\.(\d+)"), parseVer_1234), # xxx-1.2.3.4 + (re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)-"), parseVer_ymd_GIT_SHASUM), # xxx-YYYY-MM-DD-GIT_SHASUM (re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)"), parseVer_ymd), # xxx-YYYY-MM-DD (re.compile(r"(.+)[-_]([0-9a-fA-F]{40,40})"), parseVer_GIT), # xxx-GIT_SHASUM (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)(\w?)"), parseVer_123), # xxx-1.2.3a From ff875876daf9e28102d74f73cd83e26a69c78b19 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Tue, 6 Jul 2021 03:20:40 +0200 Subject: [PATCH 20/82] scripts: format dl_cleanup to black format python style Forma dl_cleanup python script to black style. Signed-off-by: Ansuel Smith --- scripts/dl_cleanup.py | 407 +++++++++++++++++++++++------------------- 1 file changed, 219 insertions(+), 188 deletions(-) diff --git a/scripts/dl_cleanup.py b/scripts/dl_cleanup.py index 83269e68e5..3c26dc8eb5 100755 --- a/scripts/dl_cleanup.py +++ b/scripts/dl_cleanup.py @@ -19,232 +19,263 @@ opt_dryrun = False def parseVer_1234(match, filepath): - progname = match.group(1) - progversion = (int(match.group(2)) << 64) |\ - (int(match.group(3)) << 48) |\ - (int(match.group(4)) << 32) |\ - (int(match.group(5)) << 16) - return (progname, progversion) + progname = match.group(1) + progversion = ( + (int(match.group(2)) << 64) + | (int(match.group(3)) << 48) + | (int(match.group(4)) << 32) + | (int(match.group(5)) << 16) + ) + return (progname, progversion) + def parseVer_123(match, filepath): - progname = match.group(1) - try: - patchlevel = match.group(5) - except IndexError as e: - patchlevel = None - if patchlevel: - patchlevel = ord(patchlevel[0]) - else: - patchlevel = 0 - progversion = (int(match.group(2)) << 64) |\ - (int(match.group(3)) << 48) |\ - (int(match.group(4)) << 32) |\ - patchlevel - return (progname, progversion) + progname = match.group(1) + try: + patchlevel = match.group(5) + except IndexError as e: + patchlevel = None + if patchlevel: + patchlevel = ord(patchlevel[0]) + else: + patchlevel = 0 + progversion = ( + (int(match.group(2)) << 64) + | (int(match.group(3)) << 48) + | (int(match.group(4)) << 32) + | patchlevel + ) + return (progname, progversion) + def parseVer_12(match, filepath): - progname = match.group(1) - try: - patchlevel = match.group(4) - except IndexError as e: - patchlevel = None - if patchlevel: - patchlevel = ord(patchlevel[0]) - else: - patchlevel = 0 - progversion = (int(match.group(2)) << 64) |\ - (int(match.group(3)) << 48) |\ - patchlevel - return (progname, progversion) + progname = match.group(1) + try: + patchlevel = match.group(4) + except IndexError as e: + patchlevel = None + if patchlevel: + patchlevel = ord(patchlevel[0]) + else: + patchlevel = 0 + progversion = (int(match.group(2)) << 64) | (int(match.group(3)) << 48) | patchlevel + return (progname, progversion) + def parseVer_r(match, filepath): - progname = match.group(1) - progversion = (int(match.group(2)) << 64) - return (progname, progversion) + progname = match.group(1) + progversion = int(match.group(2)) << 64 + return (progname, progversion) + def parseVer_ymd_GIT_SHASUM(match, filepath): - progname = match.group(1) - progversion = (int(match.group(2)) << 64) |\ - (int(match.group(3)) << 48) |\ - (int(match.group(4)) << 32) - return (progname, progversion) + progname = match.group(1) + progversion = ( + (int(match.group(2)) << 64) + | (int(match.group(3)) << 48) + | (int(match.group(4)) << 32) + ) + return (progname, progversion) + def parseVer_ymd(match, filepath): - progname = match.group(1) - progversion = (int(match.group(2)) << 64) |\ - (int(match.group(3)) << 48) |\ - (int(match.group(4)) << 32) - return (progname, progversion) + progname = match.group(1) + progversion = ( + (int(match.group(2)) << 64) + | (int(match.group(3)) << 48) + | (int(match.group(4)) << 32) + ) + return (progname, progversion) + def parseVer_GIT(match, filepath): - progname = match.group(1) - st = os.stat(filepath) - progversion = int(st.st_mtime) << 64 - return (progname, progversion) + progname = match.group(1) + st = os.stat(filepath) + progversion = int(st.st_mtime) << 64 + return (progname, progversion) + extensions = ( - ".tar.gz", - ".tar.bz2", - ".tar.xz", - ".orig.tar.gz", - ".orig.tar.bz2", - ".orig.tar.xz", - ".zip", - ".tgz", - ".tbz", - ".txz", + ".tar.gz", + ".tar.bz2", + ".tar.xz", + ".orig.tar.gz", + ".orig.tar.bz2", + ".orig.tar.xz", + ".zip", + ".tgz", + ".tbz", + ".txz", ) versionRegex = ( - (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)\.(\d+)"), parseVer_1234), # xxx-1.2.3.4 - (re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)-"), parseVer_ymd_GIT_SHASUM), # xxx-YYYY-MM-DD-GIT_SHASUM - (re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)"), parseVer_ymd), # xxx-YYYY-MM-DD - (re.compile(r"(.+)[-_]([0-9a-fA-F]{40,40})"), parseVer_GIT), # xxx-GIT_SHASUM - (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)(\w?)"), parseVer_123), # xxx-1.2.3a - (re.compile(r"(.+)[-_](\d+)_(\d+)_(\d+)"), parseVer_123), # xxx-1_2_3 - (re.compile(r"(.+)[-_](\d+)\.(\d+)(\w?)"), parseVer_12), # xxx-1.2a - (re.compile(r"(.+)[-_]r?(\d+)"), parseVer_r), # xxx-r1111 + (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)\.(\d+)"), parseVer_1234), # xxx-1.2.3.4 + ( + re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)-"), + parseVer_ymd_GIT_SHASUM, + ), # xxx-YYYY-MM-DD-GIT_SHASUM + (re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)"), parseVer_ymd), # xxx-YYYY-MM-DD + (re.compile(r"(.+)[-_]([0-9a-fA-F]{40,40})"), parseVer_GIT), # xxx-GIT_SHASUM + (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)(\w?)"), parseVer_123), # xxx-1.2.3a + (re.compile(r"(.+)[-_](\d+)_(\d+)_(\d+)"), parseVer_123), # xxx-1_2_3 + (re.compile(r"(.+)[-_](\d+)\.(\d+)(\w?)"), parseVer_12), # xxx-1.2a + (re.compile(r"(.+)[-_]r?(\d+)"), parseVer_r), # xxx-r1111 ) blacklist = [ - ("linux", re.compile(r"linux-\d.*")), - ("gcc", re.compile(r"gcc-.*")), - ("wl_apsta", re.compile(r"wl_apsta.*")), - (".fw", re.compile(r".*\.fw")), - (".arm", re.compile(r".*\.arm")), - (".bin", re.compile(r".*\.bin")), - ("rt-firmware", re.compile(r"RT[\d\w]+_Firmware.*")), + ("linux", re.compile(r"linux-\d.*")), + ("gcc", re.compile(r"gcc-.*")), + ("wl_apsta", re.compile(r"wl_apsta.*")), + (".fw", re.compile(r".*\.fw")), + (".arm", re.compile(r".*\.arm")), + (".bin", re.compile(r".*\.bin")), + ("rt-firmware", re.compile(r"RT[\d\w]+_Firmware.*")), ] -class EntryParseError(Exception): pass + +class EntryParseError(Exception): + pass + class Entry: - def __init__(self, directory, filename): - self.directory = directory - self.filename = filename - self.progname = "" - self.fileext = "" + def __init__(self, directory, filename): + self.directory = directory + self.filename = filename + self.progname = "" + self.fileext = "" - for ext in extensions: - if filename.endswith(ext): - filename = filename[0:0-len(ext)] - self.fileext = ext - break - else: - print(self.filename, "has an unknown file-extension") - raise EntryParseError("ext") - for (regex, parseVersion) in versionRegex: - match = regex.match(filename) - if match: - (self.progname, self.version) = parseVersion( - match, directory + "/" + filename + self.fileext) - break - else: - print(self.filename, "has an unknown version pattern") - raise EntryParseError("ver") + for ext in extensions: + if filename.endswith(ext): + filename = filename[0 : 0 - len(ext)] + self.fileext = ext + break + else: + print(self.filename, "has an unknown file-extension") + raise EntryParseError("ext") + for (regex, parseVersion) in versionRegex: + match = regex.match(filename) + if match: + (self.progname, self.version) = parseVersion( + match, directory + "/" + filename + self.fileext + ) + break + else: + print(self.filename, "has an unknown version pattern") + raise EntryParseError("ver") - def getPath(self): - return (self.directory + "/" + self.filename).replace("//", "/") + def getPath(self): + return (self.directory + "/" + self.filename).replace("//", "/") - def deleteFile(self): - path = self.getPath() - print("Deleting", path) - if not opt_dryrun: - os.unlink(path) + def deleteFile(self): + path = self.getPath() + print("Deleting", path) + if not opt_dryrun: + os.unlink(path) + + def __ge__(self, y): + return self.version >= y.version - def __ge__(self, y): - return self.version >= y.version def usage(): - print("OpenWrt download directory cleanup utility") - print("Usage: " + sys.argv[0] + " [OPTIONS] ") - print("") - print(" -d|--dry-run Do a dry-run. Don't delete any files") - print(" -B|--show-blacklist Show the blacklist and exit") - print(" -w|--whitelist ITEM Remove ITEM from blacklist") + print("OpenWrt download directory cleanup utility") + print("Usage: " + sys.argv[0] + " [OPTIONS] ") + print("") + print(" -d|--dry-run Do a dry-run. Don't delete any files") + print(" -B|--show-blacklist Show the blacklist and exit") + print(" -w|--whitelist ITEM Remove ITEM from blacklist") + def main(argv): - global opt_dryrun + global opt_dryrun - try: - (opts, args) = getopt.getopt(argv[1:], - "hdBw:", - [ "help", "dry-run", "show-blacklist", "whitelist=", ]) - if len(args) != 1: - usage() - return 1 - except getopt.GetoptError as e: - usage() - return 1 - directory = args[0] + try: + (opts, args) = getopt.getopt( + argv[1:], + "hdBw:", + [ + "help", + "dry-run", + "show-blacklist", + "whitelist=", + ], + ) + if len(args) != 1: + usage() + return 1 + except getopt.GetoptError as e: + usage() + return 1 + directory = args[0] - if not os.path.exists(directory): - print("Can't find dl path", directory) - return 1 + if not os.path.exists(directory): + print("Can't find dl path", directory) + return 1 - for (o, v) in opts: - if o in ("-h", "--help"): - usage() - return 0 - if o in ("-d", "--dry-run"): - opt_dryrun = True - if o in ("-w", "--whitelist"): - for i in range(0, len(blacklist)): - (name, regex) = blacklist[i] - if name == v: - del blacklist[i] - break - else: - print("Whitelist error: Item", v,\ - "is not in blacklist") - return 1 - if o in ("-B", "--show-blacklist"): - for (name, regex) in blacklist: - sep = "\t\t" - if len(name) >= 8: - sep = "\t" - print("%s%s(%s)" % (name, sep, regex.pattern)) - return 0 + for (o, v) in opts: + if o in ("-h", "--help"): + usage() + return 0 + if o in ("-d", "--dry-run"): + opt_dryrun = True + if o in ("-w", "--whitelist"): + for i in range(0, len(blacklist)): + (name, regex) = blacklist[i] + if name == v: + del blacklist[i] + break + else: + print("Whitelist error: Item", v, "is not in blacklist") + return 1 + if o in ("-B", "--show-blacklist"): + for (name, regex) in blacklist: + sep = "\t\t" + if len(name) >= 8: + sep = "\t" + print("%s%s(%s)" % (name, sep, regex.pattern)) + return 0 - # Create a directory listing and parse the file names. - entries = [] - for filename in os.listdir(directory): - if filename == "." or filename == "..": - continue - for (name, regex) in blacklist: - if regex.match(filename): - if opt_dryrun: - print(filename, "is blacklisted") - break - else: - try: - entries.append(Entry(directory, filename)) - except EntryParseError as e: - pass + # Create a directory listing and parse the file names. + entries = [] + for filename in os.listdir(directory): + if filename == "." or filename == "..": + continue + for (name, regex) in blacklist: + if regex.match(filename): + if opt_dryrun: + print(filename, "is blacklisted") + break + else: + try: + entries.append(Entry(directory, filename)) + except EntryParseError as e: + pass - # Create a map of programs - progmap = {} - for entry in entries: - if entry.progname in progmap.keys(): - progmap[entry.progname].append(entry) - else: - progmap[entry.progname] = [entry,] + # Create a map of programs + progmap = {} + for entry in entries: + if entry.progname in progmap.keys(): + progmap[entry.progname].append(entry) + else: + progmap[entry.progname] = [ + entry, + ] - # Traverse the program map and delete everything but the last version - for prog in progmap: - lastVersion = None - versions = progmap[prog] - for version in versions: - if lastVersion is None or version >= lastVersion: - lastVersion = version - if lastVersion: - for version in versions: - if version is not lastVersion: - version.deleteFile() - if opt_dryrun: - print("Keeping", lastVersion.getPath()) + # Traverse the program map and delete everything but the last version + for prog in progmap: + lastVersion = None + versions = progmap[prog] + for version in versions: + if lastVersion is None or version >= lastVersion: + lastVersion = version + if lastVersion: + for version in versions: + if version is not lastVersion: + version.deleteFile() + if opt_dryrun: + print("Keeping", lastVersion.getPath()) + + return 0 - return 0 if __name__ == "__main__": - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv)) From 366be2183e90b6ea8110d7236f8a93c8028573f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 22 Sep 2021 22:01:10 +0200 Subject: [PATCH 21/82] bcm53xx: backport early DT patches queued for 5.16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- ...SP-Add-bcm958623hr-board-name-to-dts.patch | 27 ++ ...RM-dts-NSP-Fix-mpcore-mmc-node-names.patch | 40 +++ ...-ARM-dts-NSP-Fix-MDIO-mux-node-names.patch | 47 ++++ ...s-NSP-Fix-MX64-MX65-eeprom-node-name.patch | 28 ++ ...M-dts-NSP-Fix-MX65-MDIO-mux-warnings.patch | 52 ++++ ...Specify-switch-ports-for-more-devic.patch} | 7 +- ...-Describe-on-SoC-BCM53125-rev-4-swit.patch | 44 ++++ ...-BCM53573-Add-Tenda-AC9-switch-ports.patch | 59 +++++ ...Specify-switch-ports-for-Meraki-MR32.patch | 57 +++++ ...3016-MR32-get-mac-address-from-nvmem.patch | 41 +++ ...ts-BCM5301X-Add-DT-for-Asus-RT-AC88U.patch | 242 ++++++++++++++++++ ...RM-BCM5301X-Add-DT-for-Netgear-R7900.patch | 2 +- 12 files changed, 642 insertions(+), 4 deletions(-) create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0013-ARM-dts-NSP-Add-bcm958623hr-board-name-to-dts.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0014-ARM-dts-NSP-Fix-mpcore-mmc-node-names.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0015-ARM-dts-NSP-Fix-MDIO-mux-node-names.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0016-ARM-dts-NSP-Fix-MX64-MX65-eeprom-node-name.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0017-ARM-dts-NSP-Fix-MX65-MDIO-mux-warnings.patch rename target/linux/bcm53xx/patches-5.10/{130-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch => 033-v5.16-0018-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch} (94%) create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0019-ARM-dts-BCM53573-Describe-on-SoC-BCM53125-rev-4-swit.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0020-ARM-dts-BCM53573-Add-Tenda-AC9-switch-ports.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0021-ARM-BCM53016-Specify-switch-ports-for-Meraki-MR32.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0022-ARM-BCM53016-MR32-get-mac-address-from-nvmem.patch create mode 100644 target/linux/bcm53xx/patches-5.10/033-v5.16-0023-ARM-dts-BCM5301X-Add-DT-for-Asus-RT-AC88U.patch diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0013-ARM-dts-NSP-Add-bcm958623hr-board-name-to-dts.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0013-ARM-dts-NSP-Add-bcm958623hr-board-name-to-dts.patch new file mode 100644 index 0000000000..c5f28474e3 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0013-ARM-dts-NSP-Add-bcm958623hr-board-name-to-dts.patch @@ -0,0 +1,27 @@ +From 695717eb4c61173d05a277e37132b5e2c6531bf1 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sun, 29 Aug 2021 22:37:47 +0000 +Subject: [PATCH] ARM: dts: NSP: Add bcm958623hr board name to dts + +This board was previously added to +Documentation/devicetree/bindings/arm/bcm/brcm,nsp.yaml +however the dts file was not updated to reflect this change. This patch +corrects bcm958623hr.dts by adding the board name to the compatible. + +Signed-off-by: Matthew Hagan +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm958623hr.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm958623hr.dts ++++ b/arch/arm/boot/dts/bcm958623hr.dts +@@ -37,7 +37,7 @@ + + / { + model = "NorthStar Plus SVK (BCM958623HR)"; +- compatible = "brcm,bcm58623", "brcm,nsp"; ++ compatible = "brcm,bcm958623hr", "brcm,bcm58623", "brcm,nsp"; + + chosen { + stdout-path = "serial0:115200n8"; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0014-ARM-dts-NSP-Fix-mpcore-mmc-node-names.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0014-ARM-dts-NSP-Fix-mpcore-mmc-node-names.patch new file mode 100644 index 0000000000..eab3fd3cae --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0014-ARM-dts-NSP-Fix-mpcore-mmc-node-names.patch @@ -0,0 +1,40 @@ +From 15a563d008ef9d04df525f0c476cd7d7127bb883 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sun, 29 Aug 2021 22:37:48 +0000 +Subject: [PATCH] ARM: dts: NSP: Fix mpcore, mmc node names + +Running dtbs_check yielded the issues with bcm-nsp.dtsi. + +Firstly this patch fixes the following message by appending "-bus" to +the mpcore node name: +mpcore@19000000: $nodename:0: 'mpcore@19000000' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$' + +Secondly mmc node name. The label name can remain as is. +sdhci@21000: $nodename:0: 'sdhci@21000' does not match '^mmc(@.*)?$' + +Signed-off-by: Matthew Hagan +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm-nsp.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/bcm-nsp.dtsi ++++ b/arch/arm/boot/dts/bcm-nsp.dtsi +@@ -77,7 +77,7 @@ + interrupt-affinity = <&cpu0>, <&cpu1>; + }; + +- mpcore@19000000 { ++ mpcore-bus@19000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x19000000 0x00023000>; + #address-cells = <1>; +@@ -219,7 +219,7 @@ + status = "disabled"; + }; + +- sdio: sdhci@21000 { ++ sdio: mmc@21000 { + compatible = "brcm,sdhci-iproc-cygnus"; + reg = <0x21000 0x100>; + interrupts = ; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0015-ARM-dts-NSP-Fix-MDIO-mux-node-names.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0015-ARM-dts-NSP-Fix-MDIO-mux-node-names.patch new file mode 100644 index 0000000000..a7c0f16719 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0015-ARM-dts-NSP-Fix-MDIO-mux-node-names.patch @@ -0,0 +1,47 @@ +From 38f8111369f318a538e9d4d89d8e48030c22fb40 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sun, 29 Aug 2021 22:37:49 +0000 +Subject: [PATCH] ARM: dts: NSP: Fix MDIO mux node names + +While functional, the mdio-mux-mmioreg binding does not conform to +Documentation/devicetree/bindings/net/mdio-mux-mmioreg.yaml in that an +mdio-mux compatible is also required. Without this the following output +is observed when running dtbs_check: + +mdio-mux@32000: compatible: ['mdio-mux-mmioreg'] is too short + +This change brings conformance to this requirement and corresponds +likewise to Rafal Milecki's change to the BCM5301x platform[1]. + +[1] https://lore.kernel.org/linux-arm-kernel/20210822191256.3715003-1-f.fainelli@gmail.com/T/ + +Signed-off-by: Matthew Hagan +Reviewed-by: Andrew Lunn +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm-nsp.dtsi | 2 +- + arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/bcm-nsp.dtsi ++++ b/arch/arm/boot/dts/bcm-nsp.dtsi +@@ -371,7 +371,7 @@ + }; + + mdio-mux@32000 { +- compatible = "mdio-mux-mmioreg"; ++ compatible = "mdio-mux-mmioreg", "mdio-mux"; + reg = <0x32000 0x4>; + mux-mask = <0x200>; + #address-cells = <1>; +--- a/arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi ++++ b/arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi +@@ -72,7 +72,7 @@ + }; + + mdio-mii-mux { +- compatible = "mdio-mux-mmioreg"; ++ compatible = "mdio-mux-mmioreg", "mdio-mux"; + reg = <0x1803f1c0 0x4>; + mux-mask = <0x2000>; + mdio-parent-bus = <&mdio_ext>; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0016-ARM-dts-NSP-Fix-MX64-MX65-eeprom-node-name.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0016-ARM-dts-NSP-Fix-MX64-MX65-eeprom-node-name.patch new file mode 100644 index 0000000000..4cffad1f4e --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0016-ARM-dts-NSP-Fix-MX64-MX65-eeprom-node-name.patch @@ -0,0 +1,28 @@ +From 56e4e548427240d85fd220460d0ab5987e1dec00 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sun, 29 Aug 2021 22:37:50 +0000 +Subject: [PATCH] ARM: dts: NSP: Fix MX64/MX65 eeprom node name + +Running dtbs_check yields the following message when checking the +MX64/MX65 devicetree: +at24@50: $nodename:0: 'at24@50' does not match '^eeprom@[0-9a-f]{1,2}$' + +This patch fixes the issue by renaming the at24 node appropriately. + +Signed-off-by: Matthew Hagan +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm958625-meraki-mx6x-common.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/bcm958625-meraki-mx6x-common.dtsi +@@ -48,7 +48,7 @@ + &i2c0 { + status = "okay"; + +- at24@50 { ++ eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + pagesize = <32>; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0017-ARM-dts-NSP-Fix-MX65-MDIO-mux-warnings.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0017-ARM-dts-NSP-Fix-MX65-MDIO-mux-warnings.patch new file mode 100644 index 0000000000..cad7388685 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0017-ARM-dts-NSP-Fix-MX65-MDIO-mux-warnings.patch @@ -0,0 +1,52 @@ +From f5fc9044e5d45a4d97b5240c8723f4677f647c9f Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sun, 29 Aug 2021 22:37:51 +0000 +Subject: [PATCH] ARM: dts: NSP: Fix MX65 MDIO mux warnings + +The naming of this node is based upon that of the initial EA9500 dts[1]. +However this does not conform with the mdio-mux format, yielding the +following message when running dtbs_check: +mdio-mii-mux: $nodename:0: 'mdio-mii-mux' does not match '^mdio-mux[\\-@]?' + +Secondly, this node should be moved to within the axi node and given the +appropriate unit address. This also requires exposing the axi node via a +label in bcm-nsp.dtsi. This fixes the following warning: +Warning (unit_address_vs_reg): /mdio-mii-mux: node has a reg or ranges property, but no unit name + +[1]https://patchwork.ozlabs.org/project/linux-imx/patch/20180618174159.86150-1-npcomplete13@gmail.com/#1941353 + +Signed-off-by: Matthew Hagan +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm-nsp.dtsi | 2 +- + arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi | 6 ++++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/bcm-nsp.dtsi ++++ b/arch/arm/boot/dts/bcm-nsp.dtsi +@@ -166,7 +166,7 @@ + }; + }; + +- axi@18000000 { ++ axi: axi@18000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x18000000 0x0011c40c>; + #address-cells = <1>; +--- a/arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi ++++ b/arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi +@@ -70,10 +70,12 @@ + gpios = <&gpioa 31 GPIO_ACTIVE_HIGH>; + }; + }; ++}; + +- mdio-mii-mux { ++&axi { ++ mdio-mux@3f1c0 { + compatible = "mdio-mux-mmioreg", "mdio-mux"; +- reg = <0x1803f1c0 0x4>; ++ reg = <0x3f1c0 0x4>; + mux-mask = <0x2000>; + mdio-parent-bus = <&mdio_ext>; + #address-cells = <1>; diff --git a/target/linux/bcm53xx/patches-5.10/130-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0018-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch similarity index 94% rename from target/linux/bcm53xx/patches-5.10/130-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch rename to target/linux/bcm53xx/patches-5.10/033-v5.16-0018-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch index 211de34af7..b309771369 100644 --- a/target/linux/bcm53xx/patches-5.10/130-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0018-ARM-dts-BCM5301X-Specify-switch-ports-for-more-devic.patch @@ -1,7 +1,7 @@ +From 225ffaf3d0e00daa2d0c7b68e8fd731ebbde3c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 7 Sep 2021 07:51:17 +0200 -Subject: [PATCH next] ARM: dts: BCM5301X: Specify switch ports for more - devices +Date: Tue, 7 Sep 2021 08:00:48 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Specify switch ports for more devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -10,6 +10,7 @@ Those are remaining models I have that didn't have ports yet. All tested. Signed-off-by: Rafał Miłecki +Signed-off-by: Florian Fainelli --- arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 37 ++++++++++++++++ .../boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 37 ++++++++++++++++ diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0019-ARM-dts-BCM53573-Describe-on-SoC-BCM53125-rev-4-swit.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0019-ARM-dts-BCM53573-Describe-on-SoC-BCM53125-rev-4-swit.patch new file mode 100644 index 0000000000..3a5438c228 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0019-ARM-dts-BCM53573-Describe-on-SoC-BCM53125-rev-4-swit.patch @@ -0,0 +1,44 @@ +From 9fb90ae6cae7f8fe4fbf626945f32cd9da2c3892 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 20 Sep 2021 16:10:23 +0200 +Subject: [PATCH] ARM: dts: BCM53573: Describe on-SoC BCM53125 rev 4 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM53573 family SoC have Ethernet switch connected to the first Ethernet +controller (accessible over MDIO). + +Signed-off-by: Rafał Miłecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm53573.dtsi | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/arch/arm/boot/dts/bcm53573.dtsi ++++ b/arch/arm/boot/dts/bcm53573.dtsi +@@ -180,6 +180,24 @@ + + gmac0: ethernet@5000 { + reg = <0x5000 0x1000>; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch: switch@1e { ++ compatible = "brcm,bcm53125"; ++ reg = <0x1e>; ++ ++ status = "disabled"; ++ ++ /* ports are defined in board DTS */ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; + }; + + gmac1: ethernet@b000 { diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0020-ARM-dts-BCM53573-Add-Tenda-AC9-switch-ports.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0020-ARM-dts-BCM53573-Add-Tenda-AC9-switch-ports.patch new file mode 100644 index 0000000000..c6d995723c --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0020-ARM-dts-BCM53573-Add-Tenda-AC9-switch-ports.patch @@ -0,0 +1,59 @@ +From 64612828628cca6e3992e421f45c242dc6625647 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 20 Sep 2021 16:10:24 +0200 +Subject: [PATCH] ARM: dts: BCM53573: Add Tenda AC9 switch ports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This router has 1 WAN and 4 LAN ports. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm47189-tenda-ac9.dts | 37 ++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +--- a/arch/arm/boot/dts/bcm47189-tenda-ac9.dts ++++ b/arch/arm/boot/dts/bcm47189-tenda-ac9.dts +@@ -105,3 +105,40 @@ + }; + }; + }; ++ ++&switch { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ label = "wan"; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0021-ARM-BCM53016-Specify-switch-ports-for-Meraki-MR32.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0021-ARM-BCM53016-Specify-switch-ports-for-Meraki-MR32.patch new file mode 100644 index 0000000000..a65b1992ea --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0021-ARM-BCM53016-Specify-switch-ports-for-Meraki-MR32.patch @@ -0,0 +1,57 @@ +From 6abc4ca5a28070945e0d68cb4160b309bfbf4b8b Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 18 Sep 2021 19:29:30 +0200 +Subject: [PATCH] ARM: BCM53016: Specify switch ports for Meraki MR32 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +the switch identifies itself as a BCM53012 (rev 5)... +This patch has been tested & verified on OpenWrt's +snapshot with Linux 5.10 (didn't test any older kernels). +The MR32 is able to "talk to the network" as before with +OpenWrt's SWITCHDEV b53 driver. + +| b53-srab-switch 18007000.ethernet-switch: found switch: BCM53012, rev 5 +| libphy: dsa slave smi: probed +| b53-srab-switch 18007000.ethernet-switch poe (uninitialized): +| PHY [dsa-0.0:00] driver [Generic PHY] (irq=POLL) +| b53-srab-switch 18007000.ethernet-switch: Using legacy PHYLIB callbacks. +| Please migrate to PHYLINK! +| DSA: tree 0 setup + +Reported-by: Rafał Miłecki +Signed-off-by: Christian Lamparter +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts ++++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +@@ -195,3 +195,25 @@ + }; + }; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ label = "poe"; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ ++ fixed-link { ++ speed = <1000>; ++ duplex-full; ++ }; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0022-ARM-BCM53016-MR32-get-mac-address-from-nvmem.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0022-ARM-BCM53016-MR32-get-mac-address-from-nvmem.patch new file mode 100644 index 0000000000..70a18822a9 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0022-ARM-BCM53016-MR32-get-mac-address-from-nvmem.patch @@ -0,0 +1,41 @@ +From 477ffdbdf389cc91294d66e251cc6f856da5820c Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 18 Sep 2021 19:29:31 +0200 +Subject: [PATCH] ARM: BCM53016: MR32: get mac-address from nvmem + +The MAC-Address of the MR32's sole ethernet port is +located in offset 0x66 of the attached AT24C64 eeprom. + +Signed-off-by: Christian Lamparter +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts ++++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +@@ -110,6 +110,12 @@ + reg = <0x50>; + pagesize = <32>; + read-only; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mac_address: mac-address@66 { ++ reg = <0x66 0x6>; ++ }; + }; + }; + }; +@@ -133,6 +139,11 @@ + */ + }; + ++&gmac0 { ++ nvmem-cell-names = "mac-address"; ++ nvmem-cells = <&mac_address>; ++}; ++ + &gmac1 { + status = "disabled"; + }; diff --git a/target/linux/bcm53xx/patches-5.10/033-v5.16-0023-ARM-dts-BCM5301X-Add-DT-for-Asus-RT-AC88U.patch b/target/linux/bcm53xx/patches-5.10/033-v5.16-0023-ARM-dts-BCM5301X-Add-DT-for-Asus-RT-AC88U.patch new file mode 100644 index 0000000000..70955269f6 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/033-v5.16-0023-ARM-dts-BCM5301X-Add-DT-for-Asus-RT-AC88U.patch @@ -0,0 +1,242 @@ +From beff77b93452cd2057c859694709dd34a181488f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 21 Sep 2021 20:19:01 +0800 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Asus RT-AC88U +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hardware Info +------------- + +Processor - Broadcom BCM4709C0KFEBG dual-core @ 1.4 GHz +Switch - BCM53012 in BCM4709C0KFEBG & external RTL8365MB +DDR3 RAM - 512 MB +Flash - 128 MB (ESMT F59L1G81LA-25T) +2.4GHz - BCM4366 4×4 2.4/5G single chip 802.11ac SoC +5GHz - BCM4366 4×4 2.4/5G single chip 802.11ac SoC +Ports - 8 Ports, 1 WAN Ports + +Tested on OpenWrt on kernel 5.10 built with DSA driver. + +Signed-off-by: Arınç ÜNAL +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts | 200 +++++++++++++++++++ + 2 files changed, 201 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -118,6 +118,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-netgear-r7000.dtb \ + bcm4709-netgear-r8000.dtb \ + bcm4709-tplink-archer-c9-v1.dtb \ ++ bcm47094-asus-rt-ac88u.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ + bcm47094-luxul-abr-4500.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts +@@ -0,0 +1,200 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright (C) 2021 Arınç ÜNAL ++ */ ++ ++/dts-v1/; ++ ++#include "bcm47094.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "asus,rt-ac88u", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Asus RT-AC88U"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x00000000 0x08000000>, ++ <0x88000000 0x18000000>; ++ }; ++ ++ nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x00180000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power { ++ label = "white:power"; ++ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ wan-red { ++ label = "red:wan"; ++ gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ lan { ++ label = "white:lan"; ++ gpios = <&chipcommon 21 GPIO_ACTIVE_LOW>; ++ }; ++ ++ usb2 { ++ label = "white:usb2"; ++ gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>; ++ trigger-sources = <&ehci_port2>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ usb3 { ++ label = "white:usb3"; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ trigger-sources = <&ehci_port1>, <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ wps { ++ label = "white:wps"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wps { ++ label = "WPS"; ++ linux,code = ; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>; ++ }; ++ ++ reset { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wifi { ++ label = "Wi-Fi"; ++ linux,code = ; ++ gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led { ++ label = "Backlight"; ++ linux,code = ; ++ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&srab { ++ compatible = "brcm,bcm53012-srab", "brcm,bcm5301x-srab"; ++ status = "okay"; ++ dsa,member = <0 0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "lan4"; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan3"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan1"; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "wan"; ++ }; ++ ++ sw0_p5: port@5 { ++ reg = <5>; ++ label = "extsw"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ port@7 { ++ reg = <7>; ++ ethernet = <&gmac1>; ++ label = "cpu"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ port@8 { ++ reg = <8>; ++ ethernet = <&gmac2>; ++ label = "cpu"; ++ status = "disabled"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++}; ++ ++&usb2 { ++ vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>; ++}; ++ ++&usb3_phy { ++ status = "okay"; ++}; ++ ++&nandcs { ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "boot"; ++ reg = <0x00000000 0x00080000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "nvram"; ++ reg = <0x00080000 0x00180000>; ++ }; ++ ++ partition@200000 { ++ label = "firmware"; ++ reg = <0x00200000 0x07e00000>; ++ compatible = "brcm,trx"; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-5.10/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch b/target/linux/bcm53xx/patches-5.10/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch index e67d36a4e2..7c2dad6ae2 100644 --- a/target/linux/bcm53xx/patches-5.10/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch +++ b/target/linux/bcm53xx/patches-5.10/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch @@ -16,7 +16,7 @@ Signed-off-by: Rafał Miłecki + bcm4709-netgear-r7900.dtb \ bcm4709-netgear-r8000.dtb \ bcm4709-tplink-archer-c9-v1.dtb \ - bcm47094-dlink-dir-885l.dtb \ + bcm47094-asus-rt-ac88u.dtb \ --- /dev/null +++ b/arch/arm/boot/dts/bcm4709-netgear-r7900.dts @@ -0,0 +1,42 @@ From 93f488fc37d6cd1f54eaf69385fe9011fe6d3c59 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Tue, 6 Jul 2021 03:53:58 +0200 Subject: [PATCH 22/82] scripts: handle gcc and linux in dl_cleanup script Handle gcc and linux with a special regex that set their progname with their major version. This way every minor version can be cleared. The build cleanup logic can be tweaked later to clean the entire toolchain and target dir with a different gcc version. Signed-off-by: Ansuel Smith [reformat commit message] Signed-off-by: Paul Spooren --- scripts/dl_cleanup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dl_cleanup.py b/scripts/dl_cleanup.py index 3c26dc8eb5..ad1b88c8b9 100755 --- a/scripts/dl_cleanup.py +++ b/scripts/dl_cleanup.py @@ -109,6 +109,8 @@ extensions = ( ) versionRegex = ( + (re.compile(r"(gcc[-_]\d+)\.(\d+)\.(\d+)"), parseVer_12), # gcc.1.2 + (re.compile(r"(linux[-_]\d+\.\d+)\.(\d+)"), parseVer_r), # linux.1 (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)\.(\d+)"), parseVer_1234), # xxx-1.2.3.4 ( re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)-"), @@ -123,8 +125,6 @@ versionRegex = ( ) blacklist = [ - ("linux", re.compile(r"linux-\d.*")), - ("gcc", re.compile(r"gcc-.*")), ("wl_apsta", re.compile(r"wl_apsta.*")), (".fw", re.compile(r".*\.fw")), (".arm", re.compile(r".*\.arm")), From 96e05e2e36fc3d0a893702a7c445aac0348320a4 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 23 Sep 2021 13:36:45 +0200 Subject: [PATCH 23/82] libtool: Revert "libtool: bump to 2.4.6" This breaks the package builds using the SDK. The targets all build fine, but the package builder fails on many packages. The package builder uses the OpenWrt SDK. This reverts commit c377d874bededfad971530aeb7d7e1b43cd3e61a. Signed-off-by: Hauke Mehrtens --- tools/libtool/Makefile | 11 +- tools/libtool/patches/000-relocatable.patch | 114 +++++++-- tools/libtool/patches/100-libdir-fixes.patch | 97 +++++--- ...10-dont-use-target-dir-for-relinking.patch | 51 ++-- .../120-strip-unsafe-dirs-for-relinking.patch | 36 ++- ...140-don-t-quote-SHELL-in-Makefile.am.patch | 72 ------ ...itigate-the-sed_quote_subst-slowdown.patch | 224 ------------------ ...ingslash.patch => 150-trailingslash.patch} | 33 ++- .../libtool/patches/160-passthrough-ssp.patch | 12 + .../patches/200-openwrt-branding.patch | 134 +++++++++-- 10 files changed, 337 insertions(+), 447 deletions(-) delete mode 100644 tools/libtool/patches/140-don-t-quote-SHELL-in-Makefile.am.patch delete mode 100644 tools/libtool/patches/150-libtool-mitigate-the-sed_quote_subst-slowdown.patch rename tools/libtool/patches/{130-trailingslash.patch => 150-trailingslash.patch} (57%) create mode 100644 tools/libtool/patches/160-passthrough-ssp.patch diff --git a/tools/libtool/Makefile b/tools/libtool/Makefile index b237884b64..2bc9db7d0d 100644 --- a/tools/libtool/Makefile +++ b/tools/libtool/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtool PKG_CPE_ID:=cpe:/a:gnu:libtool -PKG_VERSION:=2.4.6 +PKG_VERSION:=2.4.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNU/$(PKG_NAME) -PKG_HASH:=7c87a8c2c8c0fc9cd5019e402bed4292462d00a718a7cd5f11218153bf28b26f +PKG_HASH:=1d7b6862c1ed162e327f083a6f78f40eae29218f0db8c38393d61dab764c4407 HOST_BUILD_PARALLEL:=1 @@ -24,12 +24,7 @@ HOST_CONFIGURE_VARS += \ define Host/Prepare $(call Host/Prepare/Default) (cd $(STAGING_DIR_HOST)/share/aclocal/ && rm -f libtool.m4 ltdl.m4 lt~obsolete.m4 ltoptions.m4 ltsugar.m4 ltversion.m4) - $(if $(QUILT),,(cd $(HOST_BUILD_DIR); touch README-release; $(AM_TOOL_PATHS) ./bootstrap --skip-git --skip-po --force)) -endef - -define Host/Configure - $(if $(QUILT),(cd $(HOST_BUILD_DIR); touch README-release; $(AM_TOOL_PATHS) ./bootstrap --skip-git --skip-po --force)) - $(call Host/Configure/Default) + (cd $(HOST_BUILD_DIR); $(AM_TOOL_PATHS) ./bootstrap) endef define Host/Install diff --git a/tools/libtool/patches/000-relocatable.patch b/tools/libtool/patches/000-relocatable.patch index 88d1eaed02..6d1651be31 100644 --- a/tools/libtool/patches/000-relocatable.patch +++ b/tools/libtool/patches/000-relocatable.patch @@ -1,24 +1,17 @@ -From ca10caa502f971f90d8c041aa2476de54ef0ce2b Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Tue, 20 Jul 2021 16:41:11 -0300 -Subject: openwrt: make relocatable, search resources relative to STAGING_DIR - -This was originally commited to openwrt by Jo-Philipp Wich -. - -(adjusted to v2.4.6) -Signed-off-by: Eneas U de Queiroz - ---- a/libtoolize.in -+++ b/libtoolize.in -@@ -40,11 +40,18 @@ - - : ${AUTOCONF="autoconf"} - : ${AUTOMAKE="automake"} +--- a/libltdl/config/general.m4sh ++++ b/libltdl/config/general.m4sh +@@ -45,15 +45,22 @@ progpath="$0" + M4SH_VERBATIM([[ + : ${CP="cp -f"} + test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${EGREP="@EGREP@"} -: ${FGREP="@FGREP@"} -: ${GREP="@GREP@"} : ${LN_S="@LN_S@"} + : ${MAKE="make"} + : ${MKDIR="mkdir"} + : ${MV="mv -f"} + : ${RM="rm -f"} -: ${SED="@SED@"} +if test -n "$STAGING_DIR"; then + : ${EGREP="$STAGING_DIR/../host/bin/grep -E"} @@ -31,12 +24,87 @@ Signed-off-by: Eneas U de Queiroz + : ${GREP="@GREP@"} + : ${SED="@SED@"} +fi + : ${SHELL="${CONFIG_SHELL-/bin/sh}"} + : ${Xsed="$SED -e 1s/^X//"} +--- a/libtoolize.in ++++ b/libtoolize.in +@@ -334,15 +334,22 @@ as_unset=as_fn_unset - ## -------------------------- ## ---- a/m4/libtool.m4 -+++ b/m4/libtool.m4 -@@ -929,9 +929,8 @@ dnl AC_DEFUN([AC_LIBTOOL_RC], []) + : ${CP="cp -f"} + test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +-: ${EGREP="@EGREP@"} +-: ${FGREP="@FGREP@"} +-: ${GREP="@GREP@"} + : ${LN_S="@LN_S@"} + : ${MAKE="make"} + : ${MKDIR="mkdir"} + : ${MV="mv -f"} + : ${RM="rm -f"} +-: ${SED="@SED@"} ++if test -n "$STAGING_DIR"; then ++ : ${EGREP="$STAGING_DIR/../host/bin/grep -E"} ++ : ${FGREP="$STAGING_DIR/../host/bin/grep -F"} ++ : ${GREP="$STAGING_DIR/../host/bin/grep"} ++ : ${SED="$STAGING_DIR/../host/bin/sed"} ++else ++ : ${EGREP="@EGREP@"} ++ : ${FGREP="@FGREP@"} ++ : ${GREP="@GREP@"} ++ : ${SED="@SED@"} ++fi + : ${SHELL="${CONFIG_SHELL-/bin/sh}"} + : ${Xsed="$SED -e 1s/^X//"} + +@@ -2487,10 +2494,17 @@ func_check_macros () + + # Locations for important files: + prefix=@prefix@ +- datadir=@datadir@ +- pkgdatadir=@pkgdatadir@ +- pkgltdldir=@pkgdatadir@ +- aclocaldir=@aclocaldir@ ++ if test -n "$STAGING_DIR"; then ++ datadir="$STAGING_DIR/../host/share" ++ pkgdatadir="$STAGING_DIR/../host/share/libtool" ++ pkgltdldir="$STAGING_DIR/../host/share/libtool" ++ aclocaldir="$STAGING_DIR/../host/share/aclocal" ++ else ++ datadir=@datadir@ ++ pkgdatadir=@pkgdatadir@ ++ pkgltdldir=@pkgdatadir@ ++ aclocaldir=@aclocaldir@ ++ fi + auxdir= + macrodir= + configure_ac=configure.in +--- a/libtoolize.m4sh ++++ b/libtoolize.m4sh +@@ -1453,10 +1453,17 @@ func_check_macros () + + # Locations for important files: + prefix=@prefix@ +- datadir=@datadir@ +- pkgdatadir=@pkgdatadir@ +- pkgltdldir=@pkgdatadir@ +- aclocaldir=@aclocaldir@ ++ if test -n "$STAGING_DIR"; then ++ datadir="$STAGING_DIR/../host/share" ++ pkgdatadir="$STAGING_DIR/../host/share/libtool" ++ pkgltdldir="$STAGING_DIR/../host/share/libtool" ++ aclocaldir="$STAGING_DIR/../host/share/aclocal" ++ else ++ datadir=@datadir@ ++ pkgdatadir=@pkgdatadir@ ++ pkgltdldir=@pkgdatadir@ ++ aclocaldir=@aclocaldir@ ++ fi + auxdir= + macrodir= + configure_ac=configure.in +--- a/libltdl/m4/libtool.m4 ++++ b/libltdl/m4/libtool.m4 +@@ -907,9 +907,8 @@ dnl AC_DEFUN([AC_LIBTOOL_RC], []) # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl @@ -47,7 +115,7 @@ Signed-off-by: Eneas U de Queiroz _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl -@@ -8160,9 +8159,9 @@ m4_defun([_LT_DECL_EGREP], +@@ -7660,9 +7659,9 @@ m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep @@ -60,7 +128,7 @@ Signed-off-by: Eneas U de Queiroz dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) -@@ -8195,9 +8194,8 @@ AC_SUBST([DLLTOOL]) +@@ -7695,9 +7694,8 @@ AC_SUBST([DLLTOOL]) # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED diff --git a/tools/libtool/patches/100-libdir-fixes.patch b/tools/libtool/patches/100-libdir-fixes.patch index dd17dd97e5..3df2b14b60 100644 --- a/tools/libtool/patches/100-libdir-fixes.patch +++ b/tools/libtool/patches/100-libdir-fixes.patch @@ -1,56 +1,83 @@ -From 67ffe8e8582a7ba1f1d1307a419098e6dd88bdaf Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Tue, 20 Jul 2021 16:41:11 -0300 -Subject: openwrt: cross-compilation path adjustments - -Comments from the patch: - -Adding 'libdir' from the .la file to our library search paths -breaks crosscompilation horribly. We cheat here and don't add -it, instead adding the path where we found the .la. -CL - -OE sets installed=no in staging. We need to look in $objdir and $absdir, -preferring $objdir. RP 31/04/2008 - -This was originally commited to openwrt by Jo-Philipp Wich -. - -(adjusted to v2.4.6) -Signed-off-by: Eneas U de Queiroz - ---- a/build-aux/ltmain.in -+++ b/build-aux/ltmain.in -@@ -6049,8 +6049,14 @@ func_mode_link () - absdir=$abs_ladir - libdir=$abs_ladir +--- a/libltdl/config/ltmain.m4sh ++++ b/libltdl/config/ltmain.m4sh +@@ -5731,8 +5731,14 @@ func_mode_link () + absdir="$abs_ladir" + libdir="$abs_ladir" else -- dir=$lt_sysroot$libdir -- absdir=$lt_sysroot$libdir +- dir="$lt_sysroot$libdir" +- absdir="$lt_sysroot$libdir" + # Adding 'libdir' from the .la file to our library search paths + # breaks crosscompilation horribly. We cheat here and don't add + # it, instead adding the path where we found the .la. -CL + dir="$lt_sysroot$abs_ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" -+ #dir=$lt_sysroot$libdir -+ #absdir=$lt_sysroot$libdir ++ #dir="$libdir" ++ #absdir="$lt_sysroot$libdir" fi - test yes = "$hardcode_automatic" && avoidtemprpath=yes + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else -@@ -6448,8 +6454,6 @@ func_mode_link () - add=$libdir/$linklib +@@ -6130,8 +6136,6 @@ func_mode_link () + add="$libdir/$linklib" fi else - # We cannot seem to hardcode it, guess we'll fake it. -- add_dir=-L$libdir +- add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in -@@ -6604,7 +6608,17 @@ func_mode_link () +@@ -6286,7 +6290,17 @@ func_mode_link () fi ;; *) -- path=-L$absdir/$objdir +- path="-L$absdir/$objdir" ++ # OE sets installed=no in staging. We need to look in $objdir and $absdir, ++ # preferring $objdir. RP 31/04/2008 ++ if test -f "$absdir/$objdir/$depdepl" ; then ++ depdepl="$absdir/$objdir/$depdepl" ++ path="-L$absdir/$objdir" ++ elif test -f "$absdir/$depdepl" ; then ++ depdepl="$absdir/$depdepl" ++ path="-L$absdir" ++ else ++ path="-L$absdir/$objdir" ++ fi + ;; + esac + else +--- a/libltdl/config/ltmain.sh ++++ b/libltdl/config/ltmain.sh +@@ -6518,8 +6518,14 @@ func_mode_link () + absdir="$abs_ladir" + libdir="$abs_ladir" + else +- dir="$lt_sysroot$libdir" +- absdir="$lt_sysroot$libdir" ++ # Adding 'libdir' from the .la file to our library search paths ++ # breaks crosscompilation horribly. We cheat here and don't add ++ # it, instead adding the path where we found the .la. -CL ++ dir="$lt_sysroot$abs_ladir" ++ absdir="$abs_ladir" ++ libdir="$abs_ladir" ++ #dir="$libdir" ++ #absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else +@@ -6917,8 +6923,6 @@ func_mode_link () + add="$libdir/$linklib" + fi + else +- # We cannot seem to hardcode it, guess we'll fake it. +- add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in +@@ -7073,7 +7077,17 @@ func_mode_link () + fi + ;; + *) +- path="-L$absdir/$objdir" + # OE sets installed=no in staging. We need to look in $objdir and $absdir, + # preferring $objdir. RP 31/04/2008 + if test -f "$absdir/$objdir/$depdepl" ; then diff --git a/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch b/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch index d613440167..bbfd125003 100644 --- a/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch +++ b/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch @@ -1,33 +1,20 @@ -From 375833af93999f8b0a747c8a1dfa3ec8d347743d Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Tue, 20 Jul 2021 16:52:37 -0300 -Subject: openwrt: don't use target dir for relinking - -This was originally commited to openwrt by Jo-Philipp Wich -. - -(adjusted to v2.4.6) -Signed-off-by: Eneas U de Queiroz - ---- a/build-aux/ltmain.in -+++ b/build-aux/ltmain.in -@@ -6434,13 +6434,13 @@ func_mode_link () - add_dir= - add= - # Finalize command for both is simple: just hardcode it. -- if test yes = "$hardcode_direct" && -- test no = "$hardcode_direct_absolute"; then -- add=$libdir/$linklib -- elif test yes = "$hardcode_minus_L"; then -+ if test "$hardcode_direct" = yes && -+ test "$hardcode_direct_absolute" = no; then -+ add="$libdir/$linklib" -+ elif test "$hardcode_minus_L" = yes; then - add_dir=-L$libdir -- add=-l$name -- elif test yes = "$hardcode_shlibpath_var"; then -+ add="-l$name" -+ elif test "$hardcode_shlibpath_var" = yes; then +--- a/libltdl/config/ltmain.m4sh ++++ b/libltdl/config/ltmain.m4sh +@@ -6120,7 +6120,6 @@ func_mode_link () + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then +- add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in +--- a/libltdl/config/ltmain.sh ++++ b/libltdl/config/ltmain.sh +@@ -6907,7 +6907,6 @@ func_mode_link () + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then +- add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; diff --git a/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch b/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch index 715c254999..8840ee0569 100644 --- a/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch +++ b/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch @@ -1,26 +1,24 @@ -From 7f2b8a1ab4fa1475eeeddfb84eb5b92594bfce43 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Tue, 20 Jul 2021 16:54:12 -0300 -Subject: openwrt: strip unsave directories from relink command - -strip unsave directories from relink command, nuke every -L that looks -like /usr/lib or /lib - -This was originally commited to openwrt by Jo-Philipp Wich -. - -(adjusted to v2.4.6) -Signed-off-by: Eneas U de Queiroz - ---- a/build-aux/ltmain.in -+++ b/build-aux/ltmain.in -@@ -2382,6 +2382,9 @@ func_mode_install () +--- a/libltdl/config/ltmain.m4sh ++++ b/libltdl/config/ltmain.m4sh +@@ -2183,6 +2183,9 @@ func_mode_install () relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi + relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"` + relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"` + - func_warning "relinking '$file'" + func_warning "relinking \`$file'" func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' +--- a/libltdl/config/ltmain.sh ++++ b/libltdl/config/ltmain.sh +@@ -2973,6 +2973,9 @@ func_mode_install () + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + ++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"` ++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"` ++ + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' diff --git a/tools/libtool/patches/140-don-t-quote-SHELL-in-Makefile.am.patch b/tools/libtool/patches/140-don-t-quote-SHELL-in-Makefile.am.patch deleted file mode 100644 index 513b521834..0000000000 --- a/tools/libtool/patches/140-don-t-quote-SHELL-in-Makefile.am.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 879578d3f4dc9bc42aa433b1fb6b584564f83617 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Wed, 21 Jul 2021 13:38:24 -0300 -Subject: openwrt: don't quote $(SHELL) in Makefile.am - -This allows to use SHELL="env bash" to get a controlled enviroment. - -Signed-off-by: Eneas U de Queiroz - ---- a/Makefile.am -+++ b/Makefile.am -@@ -46,7 +46,7 @@ EXTRA_LTLIBRARIES = - # Using 'cd' in backquotes may print the directory name, use this instead: - lt__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd - --git_version_gen = '$(SHELL)' '$(aux_dir)/git-version-gen' '--fallback' '$(VERSION)' '.tarball-version' -+git_version_gen = $(SHELL) '$(aux_dir)/git-version-gen' '--fallback' '$(VERSION)' '.tarball-version' - rebuild = rebuild=:; revision=`$(lt__cd) $(srcdir) && $(git_version_gen) | $(SED) 's|-.*$$||'` - - -@@ -301,7 +301,7 @@ libtool: $(ltmain_sh) $(config_status) $ - if test 0 = '$(AM_DEFAULT_VERBOSITY)' && test 1 != '$(V)'; \ - then echo " GEN " $@; \ - else echo '$(SHELL) $(top_builddir)/config.status "$@"'; fi; \ -- cd '$(top_builddir)' && '$(SHELL)' ./config.status '$@'; \ -+ cd '$(top_builddir)' && $(SHELL) ./config.status '$@'; \ - fi - - -@@ -788,13 +788,13 @@ testsuite_deps_uninstalled = $(testsuite - # Hook the test suite into the check rule - check-local: $(testsuite_deps_uninstalled) - $(AM_V_at)$(CD_TESTDIR); \ -- CONFIG_SHELL='$(SHELL)' '$(SHELL)' "$$abs_srcdir/$(TESTSUITE)" \ -+ CONFIG_SHELL=$(SHELL) $(SHELL) "$$abs_srcdir/$(TESTSUITE)" \ - $(TESTS_ENVIRONMENT) $(BUILDCHECK_ENVIRONMENT) $(TESTSUITEFLAGS) - - # Run the test suite on the *installed* tree. - installcheck-local: $(testsuite_deps) - $(AM_V_at)$(CD_TESTDIR); \ -- CONFIG_SHELL='$(SHELL)' '$(SHELL)' "$$abs_srcdir/$(TESTSUITE)" \ -+ CONFIG_SHELL=$(SHELL) $(SHELL) "$$abs_srcdir/$(TESTSUITE)" \ - $(TESTS_ENVIRONMENT) $(INSTALLCHECK_ENVIRONMENT) $(TESTSUITEFLAGS) \ - AUTOTEST_PATH='$(exec_prefix)/bin' - -@@ -806,7 +806,7 @@ check-noninteractive-old: - .PHONY: check-noninteractive-new - check-noninteractive-new: $(testsuite_deps_uninstalled) - $(AM_V_at)$(CD_TESTDIR); \ -- CONFIG_SHELL='$(SHELL)' '$(SHELL)' "$$abs_srcdir/$(TESTSUITE)" \ -+ CONFIG_SHELL=$(SHELL) $(SHELL) "$$abs_srcdir/$(TESTSUITE)" \ - $(TESTS_ENVIRONMENT) $(BUILDCHECK_ENVIRONMENT) \ - -k '!interactive' INNER_TESTSUITEFLAGS=',!interactive' \ - $(TESTSUITEFLAGS) -@@ -815,7 +815,7 @@ check-noninteractive-new: $(testsuite_de - .PHONY: check-interactive - check-interactive: $(testsuite_deps_uninstalled) - $(AM_V_at)$(CD_TESTDIR); \ -- CONFIG_SHELL='$(SHELL)' '$(SHELL)' "$$abs_srcdir/$(TESTSUITE)" \ -+ CONFIG_SHELL=$(SHELL) $(SHELL) "$$abs_srcdir/$(TESTSUITE)" \ - $(TESTS_ENVIRONMENT) $(BUILDCHECK_ENVIRONMENT) \ - -k interactive -k recursive INNER_TESTSUITEFLAGS=',interactive' \ - $(TESTSUITEFLAGS) -@@ -827,7 +827,7 @@ check-noninteractive: check-noninteracti - clean-local: - -$(CD_TESTDIR); \ - test -f "$$abs_srcdir/$(TESTSUITE)" && \ -- '$(SHELL)' "$$abs_srcdir/$(TESTSUITE)" --clean -+ $(SHELL) "$$abs_srcdir/$(TESTSUITE)" --clean - - ## An empty target to depend on when a rule needs to always run - ## whenever it is visited. diff --git a/tools/libtool/patches/150-libtool-mitigate-the-sed_quote_subst-slowdown.patch b/tools/libtool/patches/150-libtool-mitigate-the-sed_quote_subst-slowdown.patch deleted file mode 100644 index 27ea6a1d53..0000000000 --- a/tools/libtool/patches/150-libtool-mitigate-the-sed_quote_subst-slowdown.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 3adadb568fbf15d952bd25a005b6a9afb7e59dc7 Mon Sep 17 00:00:00 2001 -From: Pavel Raiskup -Date: Sun, 4 Oct 2015 21:55:03 +0200 -Subject: libtool: mitigate the $sed_quote_subst slowdown - -When it is reasonably possible, use shell implementation for -quoting. - -References: -http://lists.gnu.org/archive/html/libtool/2015-03/msg00005.html -http://lists.gnu.org/archive/html/libtool/2015-02/msg00000.html -https://debbugs.gnu.org/cgi/bugreport.cgi?bug=20006 - -* gl/build-aux/funclib.sh (func_quote): New function that can be -used as substitution for '$SED $sed_quote_subst' call. -* build-aux/ltmain.in (func_emit_wrapper): Use func_quote instead -of '$SED $sed_quote_subst'. -(func_mode_link): Likewise. -* NEWS: Document. -* bootstrap: Sync with funclib.sh. - -(cherry picked from commit 32f0df9835ac15ac17e04be57c368172c3ad1d19) -(skipping NEWS change) -Signed-off-by: Eneas U de Queiroz - ---- a/bootstrap -+++ b/bootstrap -@@ -230,7 +230,7 @@ vc_ignore= - - # Source required external libraries: - # Set a version string for this script. --scriptversion=2015-01-20.17; # UTC -+scriptversion=2015-10-04.22; # UTC - - # General shell script boiler plate, and helper functions. - # Written by Gary V. Vaughan, 2004 -@@ -1257,6 +1257,57 @@ func_relative_path () - } - - -+# func_quote ARG -+# -------------- -+# Aesthetically quote one ARG, store the result into $func_quote_result. Note -+# that we keep attention to performance here (so far O(N) complexity as long as -+# func_append is O(1)). -+func_quote () -+{ -+ $debug_cmd -+ -+ func_quote_result=$1 -+ -+ case $func_quote_result in -+ *[\\\`\"\$]*) -+ case $func_quote_result in -+ *'*'*|*'['*) -+ func_quote_result=`$ECHO "$func_quote_result" | $SED "$sed_quote_subst"` -+ return 0 -+ ;; -+ esac -+ -+ func_quote_old_IFS=$IFS -+ for _G_char in '\' '`' '"' '$' -+ do -+ # STATE($1) PREV($2) SEPARATOR($3) -+ set start "" "" -+ func_quote_result=dummy"$_G_char$func_quote_result$_G_char"dummy -+ IFS=$_G_char -+ for _G_part in $func_quote_result -+ do -+ case $1 in -+ quote) -+ func_append func_quote_result "$3$2" -+ set quote "$_G_part" "\\$_G_char" -+ ;; -+ start) -+ set first "" "" -+ func_quote_result= -+ ;; -+ first) -+ set quote "$_G_part" "" -+ ;; -+ esac -+ done -+ IFS=$func_quote_old_IFS -+ done -+ ;; -+ *) ;; -+ esac -+} -+ -+ - # func_quote_for_eval ARG... - # -------------------------- - # Aesthetically quote ARGs to be evaled later. -@@ -1273,12 +1324,8 @@ func_quote_for_eval () - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do -- case $1 in -- *[\\\`\"\$]*) -- _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; -- *) -- _G_unquoted_arg=$1 ;; -- esac -+ func_quote "$1" -+ _G_unquoted_arg=$func_quote_result - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else ---- a/build-aux/ltmain.in -+++ b/build-aux/ltmain.in -@@ -3356,7 +3356,8 @@ else - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - -- qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` -+ func_quote "$ECHO" -+ qECHO=$func_quote_result - $ECHO "\ - - # A function that is used when there is no print builtin or printf. -@@ -8618,8 +8619,8 @@ EOF - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done -- relink_command="(cd `pwd`; $relink_command)" -- relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` -+ func_quote "(cd `pwd`; $relink_command)" -+ relink_command=$func_quote_result - fi - - # Only actually do things if not in dry run mode. -@@ -8865,7 +8866,8 @@ EOF - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" -- relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` -+ func_quote "$relink_command" -+ relink_command=$func_quote_result - if test yes = "$hardcode_automatic"; then - relink_command= - fi ---- a/build-aux/funclib.sh -+++ b/build-aux/funclib.sh -@@ -1,5 +1,5 @@ - # Set a version string for this script. --scriptversion=2015-01-20.17; # UTC -+scriptversion=2015-10-04.22; # UTC - - # General shell script boiler plate, and helper functions. - # Written by Gary V. Vaughan, 2004 -@@ -1026,6 +1026,57 @@ func_relative_path () - } - - -+# func_quote ARG -+# -------------- -+# Aesthetically quote one ARG, store the result into $func_quote_result. Note -+# that we keep attention to performance here (so far O(N) complexity as long as -+# func_append is O(1)). -+func_quote () -+{ -+ $debug_cmd -+ -+ func_quote_result=$1 -+ -+ case $func_quote_result in -+ *[\\\`\"\$]*) -+ case $func_quote_result in -+ *[\[\*\?]*) -+ func_quote_result=`$ECHO "$func_quote_result" | $SED "$sed_quote_subst"` -+ return 0 -+ ;; -+ esac -+ -+ func_quote_old_IFS=$IFS -+ for _G_char in '\' '`' '"' '$' -+ do -+ # STATE($1) PREV($2) SEPARATOR($3) -+ set start "" "" -+ func_quote_result=dummy"$_G_char$func_quote_result$_G_char"dummy -+ IFS=$_G_char -+ for _G_part in $func_quote_result -+ do -+ case $1 in -+ quote) -+ func_append func_quote_result "$3$2" -+ set quote "$_G_part" "\\$_G_char" -+ ;; -+ start) -+ set first "" "" -+ func_quote_result= -+ ;; -+ first) -+ set quote "$_G_part" "" -+ ;; -+ esac -+ done -+ IFS=$func_quote_old_IFS -+ done -+ ;; -+ *) ;; -+ esac -+} -+ -+ - # func_quote_for_eval ARG... - # -------------------------- - # Aesthetically quote ARGs to be evaled later. -@@ -1042,12 +1093,8 @@ func_quote_for_eval () - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do -- case $1 in -- *[\\\`\"\$]*) -- _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; -- *) -- _G_unquoted_arg=$1 ;; -- esac -+ func_quote "$1" -+ _G_unquoted_arg=$func_quote_result - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else diff --git a/tools/libtool/patches/130-trailingslash.patch b/tools/libtool/patches/150-trailingslash.patch similarity index 57% rename from tools/libtool/patches/130-trailingslash.patch rename to tools/libtool/patches/150-trailingslash.patch index fc28027a05..423911cf4b 100644 --- a/tools/libtool/patches/130-trailingslash.patch +++ b/tools/libtool/patches/150-trailingslash.patch @@ -1,8 +1,3 @@ -From 1b45c3c0d6682be7f4876b620780ee246a5acbaa Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Tue, 20 Jul 2021 16:56:16 -0300 -Subject: openwrt: remove trailing slash in install destdir - A command like /bin/sh ../../i586-poky-linux-libtool --mode=install /usr/bin/install -c gck-roots-store-standalone.la '/media/data1/builds/poky1/tmp/work/core2-poky-linux/gnome-keyring-2.26.1-r1/image/usr/lib/gnome-keyring/standalone/' fails (e.g. gnome-keyring or pulseaudio) This is because libdir has a trailing slash which breaks the comparision. @@ -14,12 +9,28 @@ Merged a patch received from Gary Thomas Date: 2010/07/12 Nitin A Kamble -(adjusted to v2.4.6) -Signed-off-by: Eneas U de Queiroz - ---- a/build-aux/ltmain.in -+++ b/build-aux/ltmain.in -@@ -2363,8 +2363,15 @@ func_mode_install () +--- a/libltdl/config/ltmain.m4sh ++++ b/libltdl/config/ltmain.m4sh +@@ -2167,8 +2167,15 @@ func_mode_install () + func_append dir "$objdir" + + if test -n "$relink_command"; then ++ # Strip any trailing slash from the destination. ++ func_stripname '' '/' "$libdir" ++ destlibdir=$func_stripname_result ++ ++ func_stripname '' '/' "$destdir" ++ s_destdir=$func_stripname_result ++ + # Determine the prefix the user has applied to our future dir. +- inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` ++ inst_prefix_dir=`$ECHO "X$s_destdir" | $Xsed -e "s%$destlibdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that +--- a/libltdl/config/ltmain.sh ++++ b/libltdl/config/ltmain.sh +@@ -2954,8 +2954,15 @@ func_mode_install () func_append dir "$objdir" if test -n "$relink_command"; then diff --git a/tools/libtool/patches/160-passthrough-ssp.patch b/tools/libtool/patches/160-passthrough-ssp.patch new file mode 100644 index 0000000000..da44c614e3 --- /dev/null +++ b/tools/libtool/patches/160-passthrough-ssp.patch @@ -0,0 +1,12 @@ +diff -ur libtool-2.4.orig/libltdl/config/ltmain.m4sh libtool-2.4/libltdl/config/ltmain.m4sh +--- libtool-2.4.orig/libltdl/config/ltmain.m4sh 2015-06-18 10:46:15.499996979 +0200 ++++ libtool-2.4/libltdl/config/ltmain.m4sh 2015-06-18 10:48:24.686882213 +0200 +@@ -5076,7 +5076,7 @@ + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ +- -O*|-flto*|-fwhopr*|-fuse-linker-plugin) ++ -O*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" diff --git a/tools/libtool/patches/200-openwrt-branding.patch b/tools/libtool/patches/200-openwrt-branding.patch index 95fa8c0f37..3fc0afb866 100644 --- a/tools/libtool/patches/200-openwrt-branding.patch +++ b/tools/libtool/patches/200-openwrt-branding.patch @@ -1,24 +1,112 @@ -From 90707200efadc8e230635c7c204c9c272cbc8631 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Tue, 20 Jul 2021 17:01:03 -0300 -Subject: openwrt: add openwrt branding - -This prepends program name with "OpenWrt-". - -This was originally commited to openwrt by Jo-Philipp Wich -. - -(adjusted to v2.4.6) -Signed-off-by: Eneas U de Queiroz - ---- a/build-aux/ltmain.in -+++ b/build-aux/ltmain.in -@@ -82,7 +82,7 @@ func_echo () - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS -- $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" -+ $ECHO "OpenWrt-$progname${opt_mode+: $opt_mode}: $_G_line" - done - IFS=$func_echo_IFS +--- a/libltdl/config/general.m4sh ++++ b/libltdl/config/general.m4sh +@@ -359,7 +359,7 @@ opt_warning=: + # name if it has been set yet. + func_echo () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }$*" ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*" } + + # func_verbose arg... +@@ -385,14 +385,14 @@ func_echo_all () + # Echo program name prefixed message to standard error. + func_error () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 + } + + # func_warning arg... + # Echo program name prefixed warning message to standard error. + func_warning () + { +- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 ++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +--- a/libltdl/config/ltmain.sh ++++ b/libltdl/config/ltmain.sh +@@ -439,7 +439,7 @@ opt_warning=: + # name if it has been set yet. + func_echo () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }$*" ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*" + } + + # func_verbose arg... +@@ -465,14 +465,14 @@ func_echo_all () + # Echo program name prefixed message to standard error. + func_error () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 + } + + # func_warning arg... + # Echo program name prefixed warning message to standard error. + func_warning () + { +- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 ++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +--- a/libtoolize.in ++++ b/libtoolize.in +@@ -648,7 +648,7 @@ opt_warning=: + # name if it has been set yet. + func_echo () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }$*" ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*" + } + + # func_verbose arg... +@@ -674,14 +674,14 @@ func_echo_all () + # Echo program name prefixed message to standard error. + func_error () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 + } + + # func_warning arg... + # Echo program name prefixed warning message to standard error. + func_warning () + { +- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 ++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +--- a/tests/defs.in ++++ b/tests/defs.in +@@ -596,7 +596,7 @@ opt_warning=: + # name if it has been set yet. + func_echo () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }$*" ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*" + } + + # func_verbose arg... +@@ -622,14 +622,14 @@ func_echo_all () + # Echo program name prefixed message to standard error. + func_error () + { +- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 ++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 + } + + # func_warning arg... + # Echo program name prefixed warning message to standard error. + func_warning () + { +- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 ++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : From fd67908647390b916470501c88b4f5258123da95 Mon Sep 17 00:00:00 2001 From: Damien Mascord Date: Mon, 19 Jul 2021 14:21:44 +1000 Subject: [PATCH 24/82] scripts: mkits.sh: Allow legacy @ mode for dts creation commit 5ec60cbe9d94 ("scripts: mkits.sh: replace @ with - in nodes") broke support for Meraki MR32 and this patch makes the replacement configurable allowing for specifying the @ or - or whatever character that is desired to retain backwards compatibility with existing devices. For example, this patch includes the fix for the Meraki MR32 in target/linux/bcm53xx/image for meraki_mr32: DEVICE_DTS_DELIMITER := @ DEVICE_DTS_CONFIG := config@1 Fixes: 5ec60cbe9d94 ("scripts: mkits.sh: replace @ with - in nodes") Signed-off-by: Damien Mascord [Added tags, checkpatch.pl fixes, noted that this is for old stuff] Signed-off-by: Christian Lamparter --- include/image-commands.mk | 1 + scripts/mkits.sh | 23 +++++++++++++---------- target/linux/bcm53xx/image/Makefile | 8 +++++--- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/image-commands.mk b/include/image-commands.mk index fa36885038..1c9e8c12bb 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -232,6 +232,7 @@ define Build/fit -i $(KERNEL_BUILD_DIR)/initrd.cpio$(strip $(call Build/initrd_compression)))) \ -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ $(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \ + $(if $(DEVICE_DTS_DELIMITER),-l $(DEVICE_DTS_DELIMITER)) \ $(if $(DEVICE_DTS_OVERLAY),$(foreach dtso,$(DEVICE_DTS_OVERLAY), -O $(dtso):$(KERNEL_BUILD_DIR)/image-$(dtso).dtb)) \ -c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config-1") \ -A $(LINUX_KARCH) -v $(LINUX_VERSION) diff --git a/scripts/mkits.sh b/scripts/mkits.sh index 1add8087b0..f6699384ee 100755 --- a/scripts/mkits.sh +++ b/scripts/mkits.sh @@ -32,12 +32,14 @@ usage() { printf "\n\t-d ==> include Device Tree Blob 'dtb'" printf "\n\t-r ==> include RootFS blob 'rootfs'" printf "\n\t-H ==> specify hash algo instead of SHA1" + printf "\n\t-l ==> legacy mode character (@ etc otherwise -)" printf "\n\t-o ==> create output file 'its_file'" printf "\n\t-O ==> create config with dt overlay 'name:dtb'" printf "\n\t\t(can be specified more than once)\n" exit 1 } +REFERENCE_CHAR='-' FDTNUM=1 ROOTFSNUM=1 INITRDNUM=1 @@ -46,7 +48,7 @@ LOADABLES= DTOVERLAY= DTADDR= -while getopts ":A:a:c:C:D:d:e:f:i:k:n:o:O:v:r:H:" OPTION +while getopts ":A:a:c:C:D:d:e:f:i:k:l:n:o:O:v:r:H:" OPTION do case $OPTION in A ) ARCH=$OPTARG;; @@ -59,6 +61,7 @@ do f ) COMPATIBLE=$OPTARG;; i ) INITRD=$OPTARG;; k ) KERNEL=$OPTARG;; + l ) REFERENCE_CHAR=$OPTARG;; n ) FDTNUM=$OPTARG;; o ) OUTPUT=$OPTARG;; O ) DTOVERLAY="$DTOVERLAY ${OPTARG}";; @@ -91,7 +94,7 @@ fi # Conditionally create fdt information if [ -n "${DTB}" ]; then FDT_NODE=" - fdt-$FDTNUM { + fdt${REFERENCE_CHAR}$FDTNUM { description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree blob\"; ${COMPATIBLE_PROP} data = /incbin/(\"${DTB}\"); @@ -107,12 +110,12 @@ if [ -n "${DTB}" ]; then }; }; " - FDT_PROP="fdt = \"fdt-$FDTNUM\";" + FDT_PROP="fdt = \"fdt${REFERENCE_CHAR}$FDTNUM\";" fi if [ -n "${INITRD}" ]; then INITRD_NODE=" - initrd-$INITRDNUM { + initrd${REFERENCE_CHAR}$INITRDNUM { description = \"${ARCH_UPPER} OpenWrt ${DEVICE} initrd\"; ${COMPATIBLE_PROP} data = /incbin/(\"${INITRD}\"); @@ -127,7 +130,7 @@ if [ -n "${INITRD}" ]; then }; }; " - INITRD_PROP="ramdisk=\"initrd-${INITRDNUM}\";" + INITRD_PROP="ramdisk=\"initrd${REFERENCE_CHAR}${INITRDNUM}\";" fi @@ -149,7 +152,7 @@ if [ -n "${ROOTFS}" ]; then }; }; " - LOADABLES="${LOADABLES:+$LOADABLES, }\"rootfs-${ROOTFSNUM}\"" + LOADABLES="${LOADABLES:+$LOADABLES, }\"rootfs${REFERENCE_CHAR}${ROOTFSNUM}\"" fi # add DT overlay blobs @@ -184,8 +187,8 @@ OVCONFIGS="" config-$ovname { description = \"OpenWrt ${DEVICE} with $ovname\"; - kernel = \"kernel-1\"; - fdt = \"fdt-$FDTNUM\", \"$ovnode\"; + kernel = \"kernel${REFERENCE_CHAR}1\"; + fdt = \"fdt${REFERENCE_CHAR}$FDTNUM\", \"$ovnode\"; ${LOADABLES:+loadables = ${LOADABLES};} ${COMPATIBLE_PROP} ${INITRD_PROP} @@ -201,7 +204,7 @@ DATA="/dts-v1/; #address-cells = <1>; images { - kernel-1 { + kernel${REFERENCE_CHAR}1 { description = \"${ARCH_UPPER} OpenWrt Linux-${VERSION}\"; data = /incbin/(\"${KERNEL}\"); type = \"kernel\"; @@ -227,7 +230,7 @@ ${ROOTFS_NODE} default = \"${CONFIG}\"; ${CONFIG} { description = \"OpenWrt ${DEVICE}\"; - kernel = \"kernel-1\"; + kernel = \"kernel${REFERENCE_CHAR}1\"; ${FDT_PROP} ${LOADABLES:+loadables = ${LOADABLES};} ${COMPATIBLE_PROP} diff --git a/target/linux/bcm53xx/image/Makefile b/target/linux/bcm53xx/image/Makefile index b2a7da80c5..45355e1ec9 100644 --- a/target/linux/bcm53xx/image/Makefile +++ b/target/linux/bcm53xx/image/Makefile @@ -328,10 +328,12 @@ define Device/meraki_mr32 # if the partition is smaller than the old one. KERNEL_LOADADDR := 0x00008000 KERNEL_INITRAMFS_SUFFIX := .bin + DEVICE_DTS_DELIMITER := @ + DEVICE_DTS_CONFIG := config@1 KERNEL_INITRAMFS := kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb | \ pad-to 10362880 KERNEL := kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb - IMAGES := sysupgrade.bin + IMAGES += sysupgrade.bin # Currently the only device that uses the new image check IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata @@ -437,7 +439,7 @@ define Device/tplink_archer-c5-v2 TPLINK_BOARD := ARCHER-C5-V2 BROKEN := y endef -TARGET_DEVICES += tplink_archer-c5-v2 +#TARGET_DEVICES += tplink_archer-c5-v2 define Device/tplink_archer-c9-v1 DEVICE_VENDOR := TP-Link @@ -449,6 +451,6 @@ define Device/tplink_archer-c9-v1 TPLINK_BOARD := ARCHERC9 BROKEN := y endef -TARGET_DEVICES += tplink_archer-c9-v1 +#TARGET_DEVICES += tplink_archer-c9-v1 $(eval $(call BuildImage)) From 608baf44c60cd3614a9bd502b7742919725a4c43 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 18 Sep 2021 16:41:41 +0200 Subject: [PATCH 25/82] bcm53xx: MR32: read mac-address from eeprom Meraki wrote the ethernet MAC-address of the device onto the eeprom (AT24C64) at the fixed location 0x66 to 0x6C. Let's fetch it from there. Signed-off-by: Christian Lamparter --- .../bcm53xx/base-files/etc/board.d/02_network | 4 -- .../099-net-bcma-handle-deferred-probe.patch | 46 +++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch diff --git a/target/linux/bcm53xx/base-files/etc/board.d/02_network b/target/linux/bcm53xx/base-files/etc/board.d/02_network index 1daaa6ba00..e02286027f 100644 --- a/target/linux/bcm53xx/base-files/etc/board.d/02_network +++ b/target/linux/bcm53xx/base-files/etc/board.d/02_network @@ -94,10 +94,6 @@ bcm53xx_setup_macs() # As vendor doesn't use eth0 its MAC may be missing. Use one from eth2. et2macaddr="$(nvram get et2macaddr)" ;; - meraki,mr32) - # The MAC is stored on an AT24C64 eeprom and not on the nvram - et2macaddr=$(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) - ;; esac [ -n "$et2macaddr" ] && ucidef_set_interface_macaddr "lan" "$et2macaddr" diff --git a/target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch b/target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch new file mode 100644 index 0000000000..db2d98593e --- /dev/null +++ b/target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch @@ -0,0 +1,46 @@ +From 029497e66bdc762e001880e4c85a91f35a54b1e2 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 19 Sep 2021 13:57:25 +0200 +Subject: net: bgmac-bcma: handle deferred probe error due to mac-address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Due to the inclusion of nvmem handling into the mac-address getter +function of_get_mac_address() by +commit d01f449c008a ("of_net: add NVMEM support to of_get_mac_address") +it is now possible to get a -EPROBE_DEFER return code. Which did cause +bgmac to assign a random ethernet address. + +This exact issue happened on my Meraki MR32. The nvmem provider is +an EEPROM (at24c64) which gets instantiated once the module +driver is loaded... This happens once the filesystem becomes available. + +With this patch, bgmac_probe() will propagate the -EPROBE_DEFER error. +Then the driver subsystem will reschedule the probe at a later time. + +Cc: Petr Štetiar +Cc: Michael Walle +Fixes: d01f449c008a ("of_net: add NVMEM support to of_get_mac_address") +Signed-off-by: Christian Lamparter +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/bgmac-bcma.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c +index 85fa0ab7201c7..9513cfb5ba58c 100644 +--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c +@@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_device *core) + bcma_set_drvdata(core, bgmac); + + err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); ++ if (err == -EPROBE_DEFER) ++ return err; + + /* If no MAC address assigned via device tree, check SPROM */ + if (err) { +-- +cgit 1.2.3-1.el7 + From e0721608f9620b570c7f18d94681e86b01c0b9a0 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 22 Sep 2021 17:56:30 +0200 Subject: [PATCH 26/82] ipq-wifi: Update Plasma Cloud PA1200 BDFs to firmware 3.5.12 The official Plasma Cloud firmware adjusted the BDFs to contain new conformance test limits and target power values. These should be imported to avoid emissions outside the allowed limits. Signed-off-by: Sven Eckelmann --- .../ipq-wifi/board-plasmacloud_pa1200.qca4019 | Bin 24324 -> 24324 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/package/firmware/ipq-wifi/board-plasmacloud_pa1200.qca4019 b/package/firmware/ipq-wifi/board-plasmacloud_pa1200.qca4019 index 99d6df8c8c2bd6ed8058b290e00aef09d74dbfb8..285782d9334e4746490bad4590c36e374d4e4805 100644 GIT binary patch literal 24324 zcmeHPeN+=y7JmsrtcxoX0;1pmLx6-rfIu}!lus!iDN?FP(4|1tlGG?42E@=6ds?L! zQ2{9kQH&f6fu@KYS1p3o+K+RTvw!R#d-jjE=j?9J+3glBr{_pU42Ravj9%-Xd_y*;idBT<}? zz=A%)pue#Aga2T$fY$+TatRcHm;t~76#y*p@xz+{)_zF@$02IlN+`r|R{$g>CH;8s z9!ttw1b+VOu{5f9@oX(zZeO?6JWh@T9zwG8%?bxC5^HW5I2e`zGO{^vF64*m$77^; z%Qo%FBepn!+!CU7^R_PtoBcpR7$KakcwBlbjpyUzDK4MXfX9*Ut3dESsv^h>pR}0C@acaKQ)Z2L74;^9BFGTljWrn z246(SfT;_8N8t#s-ZkiYJ&6_73*%s zz&am}ThBw59MA08k`5lJY)sh^T@q4oqqFWnj!N`;K;|`LZEwzDL0wQq@5t8Pl*3{5 z{*^;*mFkqLsMl8IO&;Ifyg?DWHDLW`!%ZJ-JS?hT^~Tka#@<(s#5IQOoH$y&Z~YEo z36kKcwi%ZF{jXxcbV64QJvHgx2_1JX={}qNOt6?eoHKmM%m51D3A{ zUPYboXJixDjB*MrDQug2P|MD$ehAXb}^*Y7VrI;sqZsmZBI)0)YU-Vm-pe#6(3!@%elV^9<)G zHwcO#8E6KQh$bR6>iq}aeZRd^Z_j{HoJ>SL%SdNw(#&+*5f|l(xVO2;N_3@YrOXfY zLxRvuG*gs$I}^!A^F{fxbTl2wMa8ICB)%<1)}m`gYh?*&0wO`FAbND>c&u4)jtXb= z++$fPNU78uuQjVTI~%02k2RYsg%8}I$Hw5;7tPEc^}p+n1f#*CU|ANLbvFwsKnp|# zvLrO=ZW5A;rixN!19YyBa@ZFlk335m(I4)QIY&#vydxy zS5N=IpkZ`u;_|gmZhd*j{SII-8jZG>tx#k%I_)4|)aV`;HSR@PGl}h2!o6d|HU~AP}5H;O-#^jmj5&E0oU}?*1Zu9Grh7?%r0} z+$N#pIR4!k?jD7cv=E7Z_gUoS%`qe30hoB`8XSMZjFVqt#{1K7_m*KGXYJ7gcz+&` z2k=5sU|=A?3q@|WmqMaUpLC0XMNUl9c>}yZ@~#Jj1r`Oi1ddsvbfRx7{ufD~+RCll z{rxjD{R6(f){q!$9d}v_aygfov@3_mJj{|SVS7dgX$9alc!E|3vBCL2v50aAZV!FK z0{i%EU>s$GkssLL&SfufSIPm)u5m!xI&XjkczOGHCIrR{lL00J3oZi|+`J>){eS-X zw{O1w`p+;c>rzwJz=x#}cfWWMhyC4me}^(#-2L6}NZftNrs5(JxBuh4AMSb{i_hTh zaeO)sz^87^Ce4gJewxAEo3mq$@~3jnS<)pi{ z{c&UO0Y5p?G50wCl(73qStWe z*y%s$Iy5SIrX&nExOO8t8W3tqO^K#t=BlY*t5&`yUt_we?N-+1W=q7-pi{GpGMKs% zEd(=@rqkL6==Y`RG1ED1vr;aXnx?gV%DuT81VO|IZz;EuAx+X}hNRQIr>)h;FB9dn5B!;y}EjBxh8w&GVH9^Y*XgLFweqVrb|%R+plX>X63FR3~s?WxI^>s zQlAOQl^w`riOG_a3_K5qhLfo=;su+5p7Gu1)4JkXgB#A8e%F_MEV_Bc?!DbP?+R;I zR{7>!AKYe01YhBs! z+e+hD3hKaVGm%m>Q`V9;w$!-@|JC8iRH$*aL@|IFo_rAOlbP z77q9>EDJfv$5?BH#E*CjM`R=){=qkJghhmhW8o!W-n@mw9urT&?iV{)vnTGF-LCA% zpkVhecx(&@>1RYt1{`L<4t9UvM$J{who|*y!dPfc26vCY0cS2T`|}ZPZ}|MaLoN6gbwk2VSy-^bcn-WGAL}pOa2YZmcY)lIkVV#z{-ZW{g@Pf?fjo76QOMe za9lhG;^Iqt47cV27jHYBr`yi(_LThB#N6X!Gq`)&Wi^AlrzPVt5PrAd^-cl#4DQ}j gNPYL=^-e8ZSu=KqwWrG&+&%rb^9=6ZQ{S!s2br3mPXGV_ delta 2382 zcmZqK$JnxuaY7!G+~JJ{o!s?WIyyQatfQr&rlz7o9hQ~`*f1p}B|l zC$Hsm5?l%d^X4IullaYq=FA0xImqPX19oYf*YW!a*X!wmBSJ+%Za`S|1T6+86D?pu z0ji?~tDXu*1KkHTg>+Uj=~_tEF?k}>g3UFmyO<|8${A0dAg6+c*5Z&uSBsC& zIr)u_2M%*YC%43!O|FwOgW4@LSuO6~#0M;sC+LSUJyhTPLcfi>USD5N4}?J}5fq|I z;511&OGg_VK}x_RgpZ|(Um8hv;zbcq>EMMZ6yU`KgAEkyA&CJhJ%D+;a&m*M6C7{g z<(|BQ&kUG_Cr_}G17eBEQT!pB)$D=!7F=qAlih%@>VX*&zr|``prWFrL2H#%9f$ zMJr%DRQ8<3F!9BUaIvAmDQdT95lpd-4KDVq*$6eL?8#NJuJUWZMy#0wQnUzzTm!U9 UMIK@cgaj+GK_(YXR*ZWL0R0<+H2?qr From 8b090708208501a60e71d0118b9860dd401d7d8d Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 22 Sep 2021 17:56:30 +0200 Subject: [PATCH 27/82] ipq-wifi: Work around Plasma Cloud PA1200 5GHz crash It was noticed [1] that the ath10k firmware crashes on 5GHz since OpenWrt 21.02.0. The problem seems to be triggered by the the nonLinearTxFir field in the 5GHz BDF. If baseEepHeader.nonLinearTxFir (offset 0xc2) is 1 then the firmware just crashes when setting up the 5Ghz radio using `ifconfig wlan1 up`: ath10k_ahb a800000.wifi: firmware crashed! (guid 9e36ee82-4d2c-4c63-b20b-609a1eaca30c) ath10k_ahb a800000.wifi: qca4019 hw1.0 target 0x01000000 chip_id 0x003b00ff sub 0000:0000 ath10k_ahb a800000.wifi: kconfig debug 0 debugfs 1 tracing 0 dfs 1 testmode 0 ath10k_ahb a800000.wifi: firmware ver 10.4-3.6-00140 api 5 features no-p2p,mfp,peer-flow-ctrl,btcoex-param,allows-mesh-bcast,no-ps crc32 ba79b746 ath10k_ahb a800000.wifi: board_file api 2 bmi_id 0:17 crc32 5f400efc ath10k_ahb a800000.wifi: htt-ver 2.2 wmi-op 6 htt-op 4 cal pre-cal-file max-sta 512 raw 0 hwcrypto 1 ath10k_ahb a800000.wifi: firmware register dump: ath10k_ahb a800000.wifi: [00]: 0x0000000B 0x000015B3 0x009C3C27 0x00975B31 ath10k_ahb a800000.wifi: [04]: 0x009C3C27 0x00060530 0x00000018 0x004176B8 ath10k_ahb a800000.wifi: [08]: 0x00405A50 0x00412A30 0x00000000 0x00000000 ath10k_ahb a800000.wifi: [12]: 0x00000009 0x00000000 0x009B9742 0x009B974F ath10k_ahb a800000.wifi: [16]: 0x00971238 0x009B9742 0x00000000 0x00000000 ath10k_ahb a800000.wifi: [20]: 0x409C3C27 0x004053DC 0x00000D2C 0x00405A60 ath10k_ahb a800000.wifi: [24]: 0x809C3E13 0x0040543C 0x00000000 0xC09C3C27 ath10k_ahb a800000.wifi: [28]: 0x809B9AC5 0x0040547C 0x00412A30 0x0040549C ath10k_ahb a800000.wifi: [32]: 0x809B8ECD 0x0040549C 0x00000001 0x00412A30 ath10k_ahb a800000.wifi: [36]: 0x809B8FF3 0x004054CC 0x00412838 0x00000014 ath10k_ahb a800000.wifi: [40]: 0x809BEF98 0x0040551C 0x0041627C 0x00000002 ath10k_ahb a800000.wifi: [44]: 0x80986D47 0x0040553C 0x0041627C 0x00416A88 ath10k_ahb a800000.wifi: [48]: 0x809CBB0A 0x0040559C 0x0041ACC0 0x00000000 ath10k_ahb a800000.wifi: [52]: 0x809864EE 0x0040560C 0x0041ACC0 0x00000001 ath10k_ahb a800000.wifi: [56]: 0x809CA8A4 0x0040564C 0x0041ACC0 0x00000001 ath10k_ahb a800000.wifi: Copy Engine register dump: ath10k_ahb a800000.wifi: [00]: 0x0004a000 14 14 3 3 ath10k_ahb a800000.wifi: [01]: 0x0004a400 16 16 22 23 ath10k_ahb a800000.wifi: [02]: 0x0004a800 3 3 2 3 ath10k_ahb a800000.wifi: [03]: 0x0004ac00 15 15 15 15 ath10k_ahb a800000.wifi: [04]: 0x0004b000 4 4 44 4 ath10k_ahb a800000.wifi: [05]: 0x0004b400 3 3 2 3 ath10k_ahb a800000.wifi: [06]: 0x0004b800 1 1 1 1 ath10k_ahb a800000.wifi: [07]: 0x0004bc00 1 1 1 1 ath10k_ahb a800000.wifi: [08]: 0x0004c000 0 0 127 0 ath10k_ahb a800000.wifi: [09]: 0x0004c400 0 0 0 0 ath10k_ahb a800000.wifi: [10]: 0x0004c800 0 0 0 0 ath10k_ahb a800000.wifi: [11]: 0x0004cc00 0 0 0 0 ath10k_ahb a800000.wifi: failed to update channel list: -108 ath10k_ahb a800000.wifi: failed to set pdev regdomain: -108 ath10k_ahb a800000.wifi: failed to create WMI vdev 0: -108 ieee80211 phy1: Hardware restart was requested Since no actual solution is known (besides downgrading the ath10k firmware) it seems to be better to disable the nonLinearTxFir for now. [1] https://lore.kernel.org/ath10k/3423718.UToCqzeSYe@ripper/ Signed-off-by: Sven Eckelmann --- .../ipq-wifi/board-plasmacloud_pa1200.qca4019 | Bin 24324 -> 24324 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/package/firmware/ipq-wifi/board-plasmacloud_pa1200.qca4019 b/package/firmware/ipq-wifi/board-plasmacloud_pa1200.qca4019 index 285782d9334e4746490bad4590c36e374d4e4805..27bfcfecc65dfa5844c138930c7103e0f24d2803 100644 GIT binary patch delta 23 fcmZqK$Jnxual Date: Thu, 23 Sep 2021 12:48:37 -0700 Subject: [PATCH 28/82] restool: add back PKG_VERSION For some reason, the build system chops off the last number from the version, which is not correct. Add it back. Update hash. Fixes: 96c7164acd80 ("restool: update to LSDK-20.12") Signed-off-by: Rosen Penev [add Fixes] Signed-off-by: Adrian Schmutzler --- package/network/utils/layerscape/restool/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/network/utils/layerscape/restool/Makefile b/package/network/utils/layerscape/restool/Makefile index b48c033464..6335f98f9f 100644 --- a/package/network/utils/layerscape/restool/Makefile +++ b/package/network/utils/layerscape/restool/Makefile @@ -8,12 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=restool +PKG_VERSION:=LSDK-20.12 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://source.codeaurora.org/external/qoriq/qoriq-components/restool PKG_SOURCE_VERSION:=LSDK-20.12 -PKG_MIRROR_HASH:=1863acfaef319e6b277671fead51df0a31bdddb59022080d86b7d81da0bc8490 +PKG_MIRROR_HASH:=aeba5add9d06c2a3cdac1cc2953d98f00acaa0038dbaf725b468f3e99e5fdd93 PKG_FLAGS:=nonshared From a7fdd4de5931fdd0af61e2ab5d2da3db2339a41d Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Thu, 23 Sep 2021 18:46:15 -1000 Subject: [PATCH 29/82] imagebuilder: show architecture in `make info` output Using `make info` show the current target, revision, default packages and available profiles. This commits adds the used architecture. Signed-off-by: Paul Spooren --- target/imagebuilder/files/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/target/imagebuilder/files/Makefile b/target/imagebuilder/files/Makefile index aeae98aacd..871a40b3a1 100644 --- a/target/imagebuilder/files/Makefile +++ b/target/imagebuilder/files/Makefile @@ -102,6 +102,7 @@ staging_dir/host/.prereq-build: include/prereq-build.mk _call_info: FORCE echo 'Current Target: "$(TARGETID)"' + echo 'Current Architecture: "$(ARCH)"' echo 'Current Revision: "$(REVISION)"' echo 'Default Packages: $(DEFAULT_PACKAGES)' echo 'Available Profiles:' From 108901fffb66b60f307d959377852300caa8bbda Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Thu, 16 Sep 2021 23:51:50 -1000 Subject: [PATCH 30/82] scripts: store maintainer in package metadata The maintainer could be usable for downstream tooling, so start storing it in the metadata. Signed-off-by: Paul Spooren --- scripts/metadata.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/metadata.pm b/scripts/metadata.pm index 5fbb77a36c..f252c5309c 100644 --- a/scripts/metadata.pm +++ b/scripts/metadata.pm @@ -290,6 +290,7 @@ sub parse_package_metadata($) { }; /^Config:\s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(*FILE, "\t"); /^Prereq-Check:/ and $pkg->{prereq} = 1; + /^Maintainer: \s*(.+)\s*$/ and $pkg->{maintainer} = [ split /, /, $1 ]; /^Require-User:\s*(.*?)\s*$/ and do { my @ugspecs = split /\s+/, $1; From 9c331a6a91e870a1dc31f563333105e959f8b171 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 11 Sep 2021 22:44:11 -1000 Subject: [PATCH 31/82] base-files: reduce `sed` calls The `sed`-script shouldn't be called multiple times, especially not with the same files. This commit merges all files together in a single `sed`-script call. Signed-off-by: Paul Spooren --- package/base-files/Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/package/base-files/Makefile b/package/base-files/Makefile index 58ad08c63a..f87fd0fe6a 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -150,13 +150,11 @@ define Package/base-files/install $(VERSION_SED_SCRIPT) \ $(1)/etc/banner \ + $(1)/etc/device_info \ + $(1)/etc/openwrt_release \ $(1)/etc/openwrt_version \ $(1)/usr/lib/os-release - $(VERSION_SED_SCRIPT) \ - $(1)/etc/openwrt_release \ - $(1)/etc/device_info \ - $(1)/usr/lib/os-release $(SED) "s#%PATH%#$(TARGET_INIT_PATH)#g" \ $(1)/sbin/hotplug-call \ From 70543aafb29a79613ac9b49ec41e51e42fa598ac Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 11 Sep 2021 22:46:06 -1000 Subject: [PATCH 32/82] base-files: reduce number of `mkdir` calls The `mkdir` commands supports passing multiple arguments to batch create multiple folders, instead of calling the tool every single time. If the creation of one of the folders fails, all other folder are still created and therefore doesn't change the error handling. Also stop creating `/etc/` explicitly after subfolders of `/etc/` were already created. Signed-off-by: Paul Spooren --- package/base-files/Makefile | 38 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/package/base-files/Makefile b/package/base-files/Makefile index f87fd0fe6a..af5c0e6b00 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -161,24 +161,27 @@ define Package/base-files/install $(1)/etc/preinit \ $(1)/etc/profile - mkdir -p $(1)/CONTROL - mkdir -p $(1)/dev - mkdir -p $(1)/etc/config - mkdir -p $(1)/etc/crontabs - mkdir -p $(1)/etc/rc.d - mkdir -p $(1)/overlay - mkdir -p $(1)/lib/firmware - $(if $(LIB_SUFFIX),-$(LN) lib $(1)/lib$(LIB_SUFFIX)) - mkdir -p $(1)/mnt - mkdir -p $(1)/proc - mkdir -p $(1)/tmp - mkdir -p $(1)/usr/lib - $(if $(LIB_SUFFIX),-$(LN) lib $(1)/usr/lib$(LIB_SUFFIX)) - mkdir -p $(1)/usr/bin - mkdir -p $(1)/sys - mkdir -p $(1)/www - mkdir -p $(1)/root + mkdir -p \ + $(1)/CONTROL \ + $(1)/dev \ + $(1)/etc/config \ + $(1)/etc/crontabs \ + $(1)/etc/rc.d \ + $(1)/overlay \ + $(1)/lib/firmware \ + $(1)/mnt \ + $(1)/proc \ + $(1)/tmp \ + $(1)/usr/lib \ + $(1)/usr/bin \ + $(1)/sys \ + $(1)/www \ + $(1)/root + $(LN) /proc/mounts $(1)/etc/mtab + $(if $(LIB_SUFFIX),-$(LN) lib $(1)/lib$(LIB_SUFFIX)) + $(if $(LIB_SUFFIX),-$(LN) lib $(1)/usr/lib$(LIB_SUFFIX)) + ifneq ($(CONFIG_TARGET_ROOTFS_PERSIST_VAR),y) rm -f $(1)/var $(LN) tmp $(1)/var @@ -186,7 +189,6 @@ else mkdir -p $(1)/var $(LN) /tmp/run $(1)/var/run endif - mkdir -p $(1)/etc $(LN) /tmp/resolv.conf /tmp/TZ /tmp/localtime $(1)/etc/ chmod 0600 $(1)/etc/shadow From e2f284dbd1841a78bc35d2ae87aec4e4fd9769d9 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Tue, 4 May 2021 21:15:13 +0200 Subject: [PATCH 33/82] x86: use device vendor/model variable Remove use of DEVICE_TITLE in favor of the DEVICE_VENDOR and DEVICE_MODEL as used by all other targets. Signed-off-by: Moritz Warning --- target/linux/x86/image/64.mk | 3 ++- target/linux/x86/image/generic.mk | 3 ++- target/linux/x86/image/geode.mk | 6 ++++-- target/linux/x86/image/legacy.mk | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/target/linux/x86/image/64.mk b/target/linux/x86/image/64.mk index d5033f932a..f54858d0b7 100644 --- a/target/linux/x86/image/64.mk +++ b/target/linux/x86/image/64.mk @@ -1,5 +1,6 @@ define Device/generic - DEVICE_TITLE := Generic x86/64 + DEVICE_VENDOR := Generic + DEVICE_MODEL := x86/64 DEVICE_PACKAGES += kmod-amazon-ena kmod-bnx2 kmod-e1000e kmod-e1000 \ kmod-forcedeth kmod-igb kmod-ixgbe kmod-amd-xgbe kmod-r8169 kmod-fs-vfat GRUB2_VARIANT := generic diff --git a/target/linux/x86/image/generic.mk b/target/linux/x86/image/generic.mk index 81cccd30b0..e9545fbf31 100644 --- a/target/linux/x86/image/generic.mk +++ b/target/linux/x86/image/generic.mk @@ -1,5 +1,6 @@ define Device/generic - DEVICE_TITLE := Generic x86 + DEVICE_VENDOR := Generic + DEVICE_MODEL := x86 DEVICE_PACKAGES += kmod-3c59x kmod-8139too kmod-e100 kmod-e1000 kmod-natsemi \ kmod-ne2k-pci kmod-pcnet32 kmod-r8169 kmod-sis900 kmod-tg3 \ kmod-via-rhine kmod-via-velocity kmod-forcedeth kmod-fs-vfat diff --git a/target/linux/x86/image/geode.mk b/target/linux/x86/image/geode.mk index 2ed2245f7d..6cea887926 100644 --- a/target/linux/x86/image/geode.mk +++ b/target/linux/x86/image/geode.mk @@ -1,5 +1,6 @@ define Device/generic - DEVICE_TITLE := Generic x86/Geode + DEVICE_VENDOR := Generic + DEVICE_MODEL := x86/Geode DEVICE_PACKAGES += kmod-crypto-cbc kmod-crypto-hw-geode kmod-ledtrig-gpio GRUB2_VARIANT := legacy endef @@ -7,7 +8,8 @@ TARGET_DEVICES += generic define Device/geos $(call Device/generic) - DEVICE_TITLE := Traverse Technologies Geos + DEVICE_VENDOR := Traverse Technologies + DEVICE_MODEL := Geos DEVICE_PACKAGES += br2684ctl flashrom kmod-hwmon-lm90 kmod-mppe kmod-pppoa \ kmod-usb-ohci-pci linux-atm ppp-mod-pppoa pppdump pppstats soloscli tc endef diff --git a/target/linux/x86/image/legacy.mk b/target/linux/x86/image/legacy.mk index 5c13f95157..6c0d8e78f9 100644 --- a/target/linux/x86/image/legacy.mk +++ b/target/linux/x86/image/legacy.mk @@ -1,5 +1,6 @@ define Device/generic - DEVICE_TITLE := Generic x86/legacy + DEVICE_VENDOR := Generic + DEVICE_MODEL := x86/legacy DEVICE_PACKAGES += kmod-3c59x kmod-8139too kmod-e100 kmod-e1000 \ kmod-natsemi kmod-ne2k-pci kmod-pcnet32 kmod-r8169 kmod-sis900 \ kmod-tg3 kmod-via-rhine kmod-via-velocity kmod-forcedeth From b34aa6aff71374d5e4eb7ea2dda11cf6305d512b Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Wed, 5 May 2021 11:06:22 +0200 Subject: [PATCH 34/82] bcm47xx: use device vendor/model variable Remove use of DEVICE_TITLE in favor of the DEVICE_VENDOR and DEVICE_MODEL as used by all other targets. Signed-off-by: Moritz Warning --- target/linux/bcm47xx/image/Makefile | 9 ++++++--- target/linux/bcm47xx/image/generic.mk | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/target/linux/bcm47xx/image/Makefile b/target/linux/bcm47xx/image/Makefile index 30a1b2f476..4341a232cf 100644 --- a/target/linux/bcm47xx/image/Makefile +++ b/target/linux/bcm47xx/image/Makefile @@ -146,17 +146,20 @@ define Device/Default endef define Device/standard - DEVICE_TITLE := Image with LZMA loader and LZMA compressed kernel + DEVICE_VENDOR := Generic + DEVICE_MODEL := Image with LZMA loader and LZMA compressed kernel endef define Device/standard-noloader-gz - DEVICE_TITLE := Image with gzipped kernel + DEVICE_VENDOR := Generic + DEVICE_MODEL := Image with gzipped kernel KERNEL_NAME = vmlinux.gz IMAGE/trx := append-rootfs | trx-without-loader endef define Device/standard-noloader-nodictionarylzma - DEVICE_TITLE := Image with LZMA compressed kernel matching CFE decompressor + DEVICE_VENDOR := Generic + DEVICE_MODEL := Image with LZMA compressed kernel matching CFE decompressor KERNEL_NAME = vmlinux-nodictionary.lzma IMAGE/trx := append-rootfs | trx-without-loader endef diff --git a/target/linux/bcm47xx/image/generic.mk b/target/linux/bcm47xx/image/generic.mk index 61204bf232..94064cb7d1 100644 --- a/target/linux/bcm47xx/image/generic.mk +++ b/target/linux/bcm47xx/image/generic.mk @@ -66,7 +66,8 @@ TARGET_DEVICES += linksys_e3000-v1 # generic has Ethernet drivers as modules so overwrite standard image define Device/standard - DEVICE_TITLE := Image with LZMA loader and LZMA compressed kernel + DEVICE_VENDOR := Generic + DEVICE_MODEL := Image with LZMA loader and LZMA compressed kernel DEVICE_PACKAGES := kmod-b44 kmod-bgmac kmod-tg3 endef TARGET_DEVICES += standard From 3128dfc18a5eaff145d17b8a3fe1131d10922384 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Fri, 17 Sep 2021 12:00:40 -1000 Subject: [PATCH 35/82] scripts: package-metadata add pkgmanifestjson call The new `pkgmanifestjson` call prints all package manifest of a feed in JSON format. This function can be used to print an overview of packages information used for downstream tooling. The script is entirely based on Petrs work on dependency visualisation. Signed-off-by: Paul Spooren --- scripts/package-metadata.pl | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl index 02102be8f3..6288584d65 100755 --- a/scripts/package-metadata.pl +++ b/scripts/package-metadata.pl @@ -585,6 +585,40 @@ sub gen_usergroup_list() { } } +sub gen_package_manifest_json() { + my $json; + parse_package_metadata($ARGV[0]) or exit 1; + foreach my $name (sort {uc($a) cmp uc($b)} keys %package) { + my %depends; + my $pkg = $package{$name}; + foreach my $dep (@{$pkg->{depends} || []}) { + if ($dep =~ m!^\+?(?:[^:]+:)?([^@]+)$!) { + $depends{$1}++; + } + } + my @depends = sort keys %depends; + my $pkg_deps = join ' ', map { qq/"$_",/ } @depends; + $pkg_deps =~ s/\,$//; + + my $pkg_maintainer = join ' ', map { qq/"$_",/ } @{$pkg->{maintainer} || []}; + $pkg_maintainer =~ s/\,$//; + + $json = <<"END_JSON"; +${json}{ +"name":"$name", +"version":"$pkg->{version}", +"category":"$pkg->{category}", +"license":"$pkg->{license}", +"maintainer": [$pkg_maintainer], +"depends":[$pkg_deps]}, +END_JSON + } + + $json =~ s/[\n\r]//g; + $json =~ s/\,$//; + print "[$json]"; +} + sub parse_command() { GetOptions("ignore=s", \@ignore); my $cmd = shift @ARGV; @@ -594,6 +628,7 @@ sub parse_command() { /^kconfig/ and return gen_kconfig_overrides(); /^source$/ and return gen_package_source(); /^pkgaux$/ and return gen_package_auxiliary(); + /^pkgmanifestjson$/ and return gen_package_manifest_json(); /^license$/ and return gen_package_license(0); /^licensefull$/ and return gen_package_license(1); /^usergroup$/ and return gen_usergroup_list(); @@ -606,6 +641,7 @@ Available Commands: $0 kconfig [file] [config] [patchver] Kernel config overrides $0 source [file] Package source file information $0 pkgaux [file] Package auxiliary variables in makefile format + $0 pkgmanifestjson [file] Package manifests in JSON format $0 license [file] Package license information $0 licensefull [file] Package license information (full list) $0 usergroup [file] Package usergroup allocation list From b56f7407d999d29c200c8c5880655926ef9874b7 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 23 Sep 2021 21:01:37 +0200 Subject: [PATCH 36/82] rockchip: fix broken squashfs sysupgrade The rockchip platform supports squashfs SD card images. However, the resulting image is not padded to completely fill the rootfs partition. Because of that, the f2fs overlay might not be erased, resulting in uci-defaults not bing executed or the configuration not being erased, even though drop config was selected. Modify the image generation process so the image is padded to cover the entire root filesystem partition. Signed-off-by: David Bauer --- target/linux/rockchip/image/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/rockchip/image/Makefile b/target/linux/rockchip/image/Makefile index f5fdff637f..e4db1e5d58 100644 --- a/target/linux/rockchip/image/Makefile +++ b/target/linux/rockchip/image/Makefile @@ -34,7 +34,7 @@ define Build/pine64-img # http://opensource.rock-chips.com/wiki_Boot_option#Boot_flow # # U-Boot SPL expects the U-Boot ITB to be located at sector 0x4000 (8 MiB) on the MMC storage - $(SCRIPT_DIR)/gen_image_generic.sh \ + PADDING=1 $(SCRIPT_DIR)/gen_image_generic.sh \ $@ \ $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.boot \ $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS) \ From 5269c47e8db549695ceaf6a19afdd0cb90074622 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Manzano Date: Tue, 21 Sep 2021 12:49:30 +0200 Subject: [PATCH 37/82] hostapd: fix segfault when deinit mesh ifaces In hostapd_ubus_add_bss(), ubus objects are not registered for mesh interfaces. This provokes a segfault when accessing the ubus object in mesh deinit. This commit adds the same condition to hostapd_ubus_free_bss() for discarding those mesh interfaces. Signed-off-by: Jesus Fernandez Manzano --- package/network/services/hostapd/src/src/ap/ubus.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 09b25a29e5..367e1b652b 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -1498,6 +1498,11 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd) struct ubus_object *obj = &hapd->ubus.obj; char *name = (char *) obj->name; +#ifdef CONFIG_MESH + if (hapd->conf->mesh & MESH_ENABLED) + return; +#endif + if (!ctx) return; From 2c9a07ed28e87bbe2d221d48aaa19b04672646a5 Mon Sep 17 00:00:00 2001 From: Alan Luck Date: Tue, 20 Apr 2021 19:44:01 +1000 Subject: [PATCH 38/82] ramips: add missing information to dlink headers Add additional header information required for newer bootloaders found on DIR-2660-A1 & A2. Also remove the MTD splitter compatible from the second firmware partition, as OpenWrt only supports handling of the first one. Signed-off-by: Alan Luck [rephrase commit message, remove removal of read-only flags] Signed-off-by: David Bauer --- .../ramips/dts/mt7621_dlink_dir-xx60-a1.dtsi | 2 - target/linux/ramips/image/Makefile | 6 + target/linux/ramips/image/mt7621.mk | 11 +- tools/firmware-utils/Makefile | 1 + tools/firmware-utils/src/uimage_sgehdr.c | 167 ++++++++++++++++++ 5 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 tools/firmware-utils/src/uimage_sgehdr.c diff --git a/target/linux/ramips/dts/mt7621_dlink_dir-xx60-a1.dtsi b/target/linux/ramips/dts/mt7621_dlink_dir-xx60-a1.dtsi index a1550cfb40..9dcc050af2 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dir-xx60-a1.dtsi +++ b/target/linux/ramips/dts/mt7621_dlink_dir-xx60-a1.dtsi @@ -102,8 +102,6 @@ partition@4980000 { label = "firmware2"; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,padding = <96>; reg = <0x4980000 0x2800000>; }; diff --git a/target/linux/ramips/image/Makefile b/target/linux/ramips/image/Makefile index 3671caef9d..d523a62e0b 100644 --- a/target/linux/ramips/image/Makefile +++ b/target/linux/ramips/image/Makefile @@ -144,6 +144,12 @@ define Build/uimage-padhdr mv $@.new $@ endef +define Build/uimage-sgehdr + uimage_sgehdr -i $@ -o $@.new -m $(DEVICE_MODEL) \ + -h $(DEVICE_VARIANT) -s V1.00000 + mv $@.new $@ +endef + define Build/umedia-header fix-u-media-header -T 0x46 -B $(1) -i $@ -o $@.new && mv $@.new $@ endef diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index c115d04bd6..6e7391baef 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -286,12 +286,11 @@ define Device/dlink_dir-8xx-a1 IMAGE_SIZE := 16000k DEVICE_VENDOR := D-Link DEVICE_PACKAGES := kmod-mt7615e kmod-mt7615-firmware - KERNEL_INITRAMFS := $$(KERNEL) | uimage-padhdr 96 + KERNEL := $$(KERNEL) | uimage-sgehdr IMAGES += factory.bin - IMAGE/sysupgrade.bin := append-kernel | append-rootfs | uimage-padhdr 96 |\ - pad-rootfs | check-size | append-metadata - IMAGE/factory.bin := append-kernel | append-rootfs | uimage-padhdr 96 |\ - check-size + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | \ + check-size | append-metadata + IMAGE/factory.bin := append-kernel | append-rootfs | check-size endef define Device/dlink_dir-8xx-r1 @@ -314,7 +313,7 @@ define Device/dlink_dir-xx60-a1 DEVICE_VENDOR := D-Link DEVICE_PACKAGES := kmod-mt7615e kmod-mt7615-firmware kmod-usb3 \ kmod-usb-ledtrig-usbport - KERNEL := $$(KERNEL) | uimage-padhdr 96 + KERNEL := $$(KERNEL) | uimage-sgehdr IMAGES += factory.bin IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | \ diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 995fc79ece..d5b0816816 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -95,6 +95,7 @@ define Host/Compile $(call cc,trx2edips,-Wall) $(call cc,trx2usr,-Wall) $(call cc,uimage_padhdr,-Wall -lz) + $(call cc,uimage_sgehdr,-Wall -lz) $(call cc,wrt400n cyg_crc32,-Wall) $(call cc,xorimage,-Wall) $(call cc,zyimage,-Wall) diff --git a/tools/firmware-utils/src/uimage_sgehdr.c b/tools/firmware-utils/src/uimage_sgehdr.c new file mode 100644 index 0000000000..28143a8b22 --- /dev/null +++ b/tools/firmware-utils/src/uimage_sgehdr.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * uimage_sgehdr.c : add 96 bytes of extra header information after the normal tail of uimage header + * this is an edited version of uimage_padhdr.c + * + * Copyright (C) 2019 NOGUCHI Hiroshi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* from u-boot/include/image.h */ +#define IH_NMLEN 32 /* Image Name Length */ +#define SGE_PRODUCTLEN 64 /* sge_Product Length */ +#define SGE_VERSIONLEN 16 /* sge Version Length */ +#define OrignalHL 64 /* Original Header Length */ + +/* + * SGE format image header, + * all data in network byte order (aka natural aka bigendian). + */ +struct image_header { + uint32_t ih_magic; /* Image Header Magic Number */ + uint32_t ih_hcrc; /* Image Header CRC Checksum */ + uint32_t ih_time; /* Image Creation Timestamp */ + uint32_t ih_size; /* Image Data Size */ + uint32_t ih_load; /* Data Load Address */ + uint32_t ih_ep; /* Entry Point Address */ + uint32_t ih_dcrc; /* Image Data CRC Checksum */ + uint8_t ih_os; /* Operating System */ + uint8_t ih_arch; /* CPU architecture */ + uint8_t ih_type; /* Image Type */ + uint8_t ih_comp; /* Compression Type */ + uint8_t ih_name[IH_NMLEN]; /* Image Name */ + uint8_t sgeih_p[SGE_PRODUCTLEN]; /* sge_Product */ + uint8_t sgeih_sv[SGE_VERSIONLEN]; /* sge Software Version */ + uint8_t sgeih_hv[SGE_VERSIONLEN]; /* sge Hardware Version */ +}; + + +/* default padding size */ +#define IH_PAD_BYTES (96) + + +static void usage(char *prog) +{ + fprintf(stderr, + "%s -i -o -m -h -s \n", + prog); +} + +int main(int argc, char *argv[]) +{ + struct stat statbuf; + u_int8_t *filebuf; + int ifd; + int ofd; + ssize_t rsz; + u_int32_t crc_recalc; + struct image_header *imgh; + int opt; + char *infname = NULL; + char *outfname = NULL; + char *model = NULL; + char *hversion = NULL; + char *sversion = NULL; + int padsz = IH_PAD_BYTES; + int ltmp; + + while ((opt = getopt(argc, argv, "i:o:m:h:s:")) != -1) { + switch (opt) { + case 'i': + infname = optarg; + break; + case 'o': + outfname = optarg; + break; + case 'm': + model = optarg; + break; + case 'h': + hversion = optarg; + break; + case 's': + sversion = optarg; + break; + default: + break; + } + } + + if (!infname || !outfname) { + usage(argv[0]); + exit(1); + } + + ifd = open(infname, O_RDONLY); + if (ifd < 0) { + fprintf(stderr, + "could not open input file. (errno = %d)\n", errno); + exit(1); + } + + ofd = open(outfname, O_WRONLY | O_CREAT, 0644); + if (ofd < 0) { + fprintf(stderr, + "could not open output file. (errno = %d)\n", errno); + exit(1); + } + + if (fstat(ifd, &statbuf) < 0) { + fprintf(stderr, + "could not fstat input file. (errno = %d)\n", errno); + exit(1); + } + + filebuf = malloc(statbuf.st_size + padsz); + if (!filebuf) { + fprintf(stderr, "buffer allocation failed\n"); + exit(1); + } + + rsz = read(ifd, filebuf, OrignalHL); + if (rsz != OrignalHL) { + fprintf(stderr, + "could not read input file (errno = %d).\n", errno); + exit(1); + } + + memset(&(filebuf[OrignalHL]), 0, padsz); + + rsz = read(ifd, &(filebuf[sizeof(*imgh)]), + statbuf.st_size - OrignalHL); + if (rsz != (int32_t)(statbuf.st_size - OrignalHL)) { + fprintf(stderr, + "could not read input file (errno = %d).\n", errno); + exit(1); + } + + imgh = (struct image_header *)filebuf; + + imgh->ih_hcrc = 0; + + strncpy(imgh->sgeih_p, model, sizeof(imgh->sgeih_p)); + strncpy(imgh->sgeih_sv, sversion, sizeof(imgh->sgeih_sv)); + strncpy(imgh->sgeih_hv, hversion, sizeof(imgh->sgeih_hv)); + + crc_recalc = crc32(0, filebuf, sizeof(*imgh)); + imgh->ih_hcrc = htonl(crc_recalc); + + rsz = write(ofd, filebuf, statbuf.st_size + padsz); + if (rsz != (int32_t)statbuf.st_size + padsz) { + fprintf(stderr, + "could not write output file (errnor = %d).\n", errno); + exit(1); + } + + return 0; +} From 2bfac61483db32f8bd1f5b38702b39f206256265 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 24 Sep 2021 16:53:33 +0200 Subject: [PATCH 39/82] mac80211: backport support for BSS color changes This is needed for an upcoming mt76 update Signed-off-by: Felix Fietkau --- ...nl80211-add-support-for-BSS-coloring.patch | 485 ++++++++++++++++ ...211-add-support-for-BSS-color-change.patch | 524 ++++++++++++++++++ .../500-mac80211_configure_antenna_gain.patch | 32 +- 3 files changed, 1025 insertions(+), 16 deletions(-) create mode 100644 package/kernel/mac80211/patches/subsys/387-nl80211-add-support-for-BSS-coloring.patch create mode 100644 package/kernel/mac80211/patches/subsys/388-mac80211-add-support-for-BSS-color-change.patch diff --git a/package/kernel/mac80211/patches/subsys/387-nl80211-add-support-for-BSS-coloring.patch b/package/kernel/mac80211/patches/subsys/387-nl80211-add-support-for-BSS-coloring.patch new file mode 100644 index 0000000000..36b705de12 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/387-nl80211-add-support-for-BSS-coloring.patch @@ -0,0 +1,485 @@ +From: John Crispin +Date: Fri, 2 Jul 2021 19:44:07 +0200 +Subject: [PATCH] nl80211: add support for BSS coloring + +This patch adds support for BSS color collisions to the wireless subsystem. +Add the required functionality to nl80211 that will notify about color +collisions, triggering the color change and notifying when it is completed. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: John Crispin +Link: https://lore.kernel.org/r/500b3582aec8fe2c42ef46f3117b148cb7cbceb5.1625247619.git.lorenzo@kernel.org +[remove unnecessary NULL initialisation] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1252,6 +1252,27 @@ struct cfg80211_csa_settings { + #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 + + /** ++ * struct cfg80211_color_change_settings - color change settings ++ * ++ * Used for bss color change ++ * ++ * @beacon_color_change: beacon data while performing the color countdown ++ * @counter_offsets_beacon: offsets of the counters within the beacon (tail) ++ * @counter_offsets_presp: offsets of the counters within the probe response ++ * @beacon_next: beacon data to be used after the color change ++ * @count: number of beacons until the color change ++ * @color: the color used after the change ++ */ ++struct cfg80211_color_change_settings { ++ struct cfg80211_beacon_data beacon_color_change; ++ u16 counter_offset_beacon; ++ u16 counter_offset_presp; ++ struct cfg80211_beacon_data beacon_next; ++ u8 count; ++ u8 color; ++}; ++ ++/** + * struct iface_combination_params - input parameters for interface combinations + * + * Used to pass interface combination parameters +@@ -3979,6 +4000,8 @@ struct mgmt_frame_regs { + * This callback may sleep. + * @reset_tid_config: Reset TID specific configuration for the peer, for the + * given TIDs. This callback may sleep. ++ * ++ * @color_change: Initiate a color change. + */ + struct cfg80211_ops { + int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); +@@ -4309,6 +4332,9 @@ struct cfg80211_ops { + const u8 *peer, u8 tids); + int (*set_sar_specs)(struct wiphy *wiphy, + struct cfg80211_sar_specs *sar); ++ int (*color_change)(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_color_change_settings *params); + }; + + /* +@@ -8094,4 +8120,70 @@ void cfg80211_update_owe_info_event(stru + */ + void cfg80211_bss_flush(struct wiphy *wiphy); + ++/** ++ * cfg80211_bss_color_notify - notify about bss color event ++ * @dev: network device ++ * @gfp: allocation flags ++ * @cmd: the actual event we want to notify ++ * @count: the number of TBTTs until the color change happens ++ * @color_bitmap: representations of the colors that the local BSS is aware of ++ */ ++int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp, ++ enum nl80211_commands cmd, u8 count, ++ u64 color_bitmap); ++ ++/** ++ * cfg80211_obss_color_collision_notify - notify about bss color collision ++ * @dev: network device ++ * @color_bitmap: representations of the colors that the local BSS is aware of ++ */ ++static inline int cfg80211_obss_color_collision_notify(struct net_device *dev, ++ u64 color_bitmap) ++{ ++ return cfg80211_bss_color_notify(dev, GFP_KERNEL, ++ NL80211_CMD_OBSS_COLOR_COLLISION, ++ 0, color_bitmap); ++} ++ ++/** ++ * cfg80211_color_change_started_notify - notify color change start ++ * @dev: the device on which the color is switched ++ * @count: the number of TBTTs until the color change happens ++ * ++ * Inform the userspace about the color change that has started. ++ */ ++static inline int cfg80211_color_change_started_notify(struct net_device *dev, ++ u8 count) ++{ ++ return cfg80211_bss_color_notify(dev, GFP_KERNEL, ++ NL80211_CMD_COLOR_CHANGE_STARTED, ++ count, 0); ++} ++ ++/** ++ * cfg80211_color_change_aborted_notify - notify color change abort ++ * @dev: the device on which the color is switched ++ * ++ * Inform the userspace about the color change that has aborted. ++ */ ++static inline int cfg80211_color_change_aborted_notify(struct net_device *dev) ++{ ++ return cfg80211_bss_color_notify(dev, GFP_KERNEL, ++ NL80211_CMD_COLOR_CHANGE_ABORTED, ++ 0, 0); ++} ++ ++/** ++ * cfg80211_color_change_notify - notify color change completion ++ * @dev: the device on which the color was switched ++ * ++ * Inform the userspace about the color change that has completed. ++ */ ++static inline int cfg80211_color_change_notify(struct net_device *dev) ++{ ++ return cfg80211_bss_color_notify(dev, GFP_KERNEL, ++ NL80211_CMD_COLOR_CHANGE_COMPLETED, ++ 0, 0); ++} ++ + #endif /* __NET_CFG80211_H */ +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -1185,6 +1185,21 @@ + * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to + * specify the wiphy index to be applied to. + * ++ * @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever ++ * mac80211/drv detects a bss color collision. ++ * ++ * @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that ++ * userspace wants to change the BSS color. ++ * ++ * @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has ++ * started ++ * ++ * @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has ++ * been aborted ++ * ++ * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change ++ * has completed ++ * + * @NL80211_CMD_MAX: highest used command number + * @__NL80211_CMD_AFTER_LAST: internal use + */ +@@ -1417,6 +1432,14 @@ enum nl80211_commands { + + NL80211_CMD_SET_SAR_SPECS, + ++ NL80211_CMD_OBSS_COLOR_COLLISION, ++ ++ NL80211_CMD_COLOR_CHANGE_REQUEST, ++ ++ NL80211_CMD_COLOR_CHANGE_STARTED, ++ NL80211_CMD_COLOR_CHANGE_ABORTED, ++ NL80211_CMD_COLOR_CHANGE_COMPLETED, ++ + /* add new commands above here */ + + /* used to define NL80211_CMD_MAX below */ +@@ -2560,6 +2583,16 @@ enum nl80211_commands { + * disassoc events to indicate that an immediate reconnect to the AP + * is desired. + * ++ * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the ++ * %NL80211_CMD_OBSS_COLOR_COLLISION event. ++ * ++ * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's ++ * until the color switch event. ++ * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are ++ * switching to ++ * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE ++ * information for the time while performing a color switch. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3057,6 +3090,12 @@ enum nl80211_attrs { + + NL80211_ATTR_DISABLE_HE, + ++ NL80211_ATTR_OBSS_COLOR_BITMAP, ++ ++ NL80211_ATTR_COLOR_CHANGE_COUNT, ++ NL80211_ATTR_COLOR_CHANGE_COLOR, ++ NL80211_ATTR_COLOR_CHANGE_ELEMS, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -5950,6 +5989,9 @@ enum nl80211_feature_flags { + * frame protection for all management frames exchanged during the + * negotiation and range measurement procedure. + * ++ * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision ++ * detection and change announcemnts. ++ * + * @NUM_NL80211_EXT_FEATURES: number of extended features. + * @MAX_NL80211_EXT_FEATURES: highest extended feature index. + */ +@@ -6014,6 +6056,7 @@ enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_SECURE_LTF, + NL80211_EXT_FEATURE_SECURE_RTT, + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, ++ NL80211_EXT_FEATURE_BSS_COLOR, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -753,6 +753,10 @@ static const struct nla_policy nl80211_p + NL80211_SAE_PWE_BOTH), + [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy), + [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, ++ [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 }, ++ [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 }, ++ [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 }, ++ [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy), + }; + + /* policy for the key attributes */ +@@ -14677,6 +14681,106 @@ bad_tid_conf: + return ret; + } + ++static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *rdev = info->user_ptr[0]; ++ struct cfg80211_color_change_settings params = {}; ++ struct net_device *dev = info->user_ptr[1]; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct nlattr **tb; ++ u16 offset; ++ int err; ++ ++ if (!rdev->ops->color_change) ++ return -EOPNOTSUPP; ++ ++ if (!wiphy_ext_feature_isset(&rdev->wiphy, ++ NL80211_EXT_FEATURE_BSS_COLOR)) ++ return -EOPNOTSUPP; ++ ++ if (wdev->iftype != NL80211_IFTYPE_AP) ++ return -EOPNOTSUPP; ++ ++ if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] || ++ !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] || ++ !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS]) ++ return -EINVAL; ++ ++ params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]); ++ params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]); ++ ++ err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_next); ++ if (err) ++ return err; ++ ++ tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL); ++ if (!tb) ++ return -ENOMEM; ++ ++ err = nla_parse_nested(tb, NL80211_ATTR_MAX, ++ info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS], ++ nl80211_policy, info->extack); ++ if (err) ++ goto out; ++ ++ err = nl80211_parse_beacon(rdev, tb, ¶ms.beacon_color_change); ++ if (err) ++ goto out; ++ ++ if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]); ++ if (offset >= params.beacon_color_change.tail_len) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (params.beacon_color_change.tail[offset] != params.count) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ params.counter_offset_beacon = offset; ++ ++ if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) { ++ if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) != ++ sizeof(u16)) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]); ++ if (offset >= params.beacon_color_change.probe_resp_len) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (params.beacon_color_change.probe_resp[offset] != ++ params.count) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ params.counter_offset_presp = offset; ++ } ++ ++ wdev_lock(wdev); ++ err = rdev_color_change(rdev, dev, ¶ms); ++ wdev_unlock(wdev); ++ ++out: ++ kfree(tb); ++ return err; ++} ++ + #define NL80211_FLAG_NEED_WIPHY 0x01 + #define NL80211_FLAG_NEED_NETDEV 0x02 + #define NL80211_FLAG_NEED_RTNL 0x04 +@@ -15758,6 +15862,14 @@ static const struct genl_small_ops nl802 + .internal_flags = NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL, + }, ++ { ++ .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST, ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, ++ .doit = nl80211_color_change, ++ .flags = GENL_UNS_ADMIN_PERM, ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NEED_RTNL, ++ }, + }; + + static struct genl_family nl80211_fam __genl_ro_after_init = { +@@ -17384,6 +17496,51 @@ void cfg80211_ch_switch_started_notify(s + } + EXPORT_SYMBOL(cfg80211_ch_switch_started_notify); + ++int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp, ++ enum nl80211_commands cmd, u8 count, ++ u64 color_bitmap) ++{ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct wiphy *wiphy = wdev->wiphy; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ struct sk_buff *msg; ++ void *hdr; ++ ++ ASSERT_WDEV_LOCK(wdev); ++ ++ trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap); ++ ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); ++ if (!msg) ++ return -ENOMEM; ++ ++ hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); ++ if (!hdr) ++ goto nla_put_failure; ++ ++ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) ++ goto nla_put_failure; ++ ++ if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED && ++ nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count)) ++ goto nla_put_failure; ++ ++ if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION && ++ nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP, ++ color_bitmap, NL80211_ATTR_PAD)) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ ++ return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), ++ msg, 0, NL80211_MCGRP_MLME, gfp); ++ ++nla_put_failure: ++ nlmsg_free(msg); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(cfg80211_bss_color_notify); ++ + void + nl80211_radar_notify(struct cfg80211_registered_device *rdev, + const struct cfg80211_chan_def *chandef, +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1368,4 +1368,17 @@ static inline int rdev_set_sar_specs(str + return ret; + } + ++static inline int rdev_color_change(struct cfg80211_registered_device *rdev, ++ struct net_device *dev, ++ struct cfg80211_color_change_settings *params) ++{ ++ int ret; ++ ++ trace_rdev_color_change(&rdev->wiphy, dev, params); ++ ret = rdev->ops->color_change(&rdev->wiphy, dev, params); ++ trace_rdev_return_int(&rdev->wiphy, ret); ++ ++ return ret; ++} ++ + #endif /* __CFG80211_RDEV_OPS */ +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -3570,6 +3570,52 @@ TRACE_EVENT(rdev_set_sar_specs, + WIPHY_PR_ARG, __entry->type, __entry->num) + ); + ++TRACE_EVENT(rdev_color_change, ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, ++ struct cfg80211_color_change_settings *params), ++ TP_ARGS(wiphy, netdev, params), ++ TP_STRUCT__entry( ++ WIPHY_ENTRY ++ NETDEV_ENTRY ++ __field(u8, count) ++ __field(u16, bcn_ofs) ++ __field(u16, pres_ofs) ++ ), ++ TP_fast_assign( ++ WIPHY_ASSIGN; ++ NETDEV_ASSIGN; ++ __entry->count = params->count; ++ __entry->bcn_ofs = params->counter_offset_beacon; ++ __entry->pres_ofs = params->counter_offset_presp; ++ ), ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ++ ", count: %u", ++ WIPHY_PR_ARG, NETDEV_PR_ARG, ++ __entry->count) ++); ++ ++TRACE_EVENT(cfg80211_bss_color_notify, ++ TP_PROTO(struct net_device *netdev, ++ enum nl80211_commands cmd, ++ u8 count, u64 color_bitmap), ++ TP_ARGS(netdev, cmd, count, color_bitmap), ++ TP_STRUCT__entry( ++ NETDEV_ENTRY ++ __field(enum nl80211_bss_scan_width, cmd) ++ __field(u8, count) ++ __field(u64, color_bitmap) ++ ), ++ TP_fast_assign( ++ NETDEV_ASSIGN; ++ __entry->cmd = cmd; ++ __entry->count = count; ++ __entry->color_bitmap = color_bitmap; ++ ), ++ TP_printk(NETDEV_PR_FMT ", cmd: %x, count: %u, bitmap: %llx", ++ NETDEV_PR_ARG, __entry->cmd, __entry->count, ++ __entry->color_bitmap) ++); ++ + #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ + + #undef TRACE_INCLUDE_PATH diff --git a/package/kernel/mac80211/patches/subsys/388-mac80211-add-support-for-BSS-color-change.patch b/package/kernel/mac80211/patches/subsys/388-mac80211-add-support-for-BSS-color-change.patch new file mode 100644 index 0000000000..0a3118545f --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/388-mac80211-add-support-for-BSS-color-change.patch @@ -0,0 +1,524 @@ +From: John Crispin +Date: Fri, 2 Jul 2021 19:44:08 +0200 +Subject: [PATCH] mac80211: add support for BSS color change + +The color change announcement is very similar to how CSA works where +we have an IE that includes a counter. When the counter hits 0, the new +color is applied via an updated beacon. + +This patch makes the CSA counter functionality reusable, rather than +implementing it again. This also allows for future reuse incase support +for other counter IEs gets added. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: John Crispin +Link: https://lore.kernel.org/r/057c1e67b82bee561ea44ce6a45a8462d3da6995.1625247619.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1710,6 +1710,10 @@ enum ieee80211_offload_flags { + * protected by fq->lock. + * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see + * &enum ieee80211_offload_flags. ++ * @color_change_active: marks whether a color change is ongoing. Internally it is ++ * write-protected by sdata_lock and local->mtx so holding either is fine ++ * for read access. ++ * @color_change_color: the bss color that will be used after the change. + */ + struct ieee80211_vif { + enum nl80211_iftype type; +@@ -1738,6 +1742,9 @@ struct ieee80211_vif { + + bool txqs_stopped[IEEE80211_NUM_ACS]; + ++ bool color_change_active; ++ u8 color_change_color; ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +@@ -4982,6 +4989,16 @@ void ieee80211_csa_finish(struct ieee802 + bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif); + + /** ++ * ieee80211_color_change_finish - notify mac80211 about color change ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * ++ * After a color change announcement was scheduled and the counter in this ++ * announcement hits 1, this function must be called by the driver to ++ * notify mac80211 that the color can be changed ++ */ ++void ieee80211_color_change_finish(struct ieee80211_vif *vif); ++ ++/** + * ieee80211_proberesp_get - retrieve a Probe Response template + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. +@@ -6726,6 +6743,18 @@ ieee80211_get_unsol_bcast_probe_resp_tmp + struct ieee80211_vif *vif); + + /** ++ * ieeee80211_obss_color_collision_notify - notify userland about a BSS color ++ * collision. ++ * ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @color_bitmap: a 64 bit bitmap representing the colors that the local BSS is ++ * aware of. ++ */ ++void ++ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif, ++ u64 color_bitmap); ++ ++/** + * ieee80211_is_tx_data - check if frame is a data frame + * + * The function is used to check if a frame is a data frame. Frames with +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -827,9 +827,11 @@ static int ieee80211_set_monitor_channel + return ret; + } + +-static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, +- const u8 *resp, size_t resp_len, +- const struct ieee80211_csa_settings *csa) ++static int ++ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, ++ const u8 *resp, size_t resp_len, ++ const struct ieee80211_csa_settings *csa, ++ const struct ieee80211_color_change_settings *cca) + { + struct probe_resp *new, *old; + +@@ -849,6 +851,8 @@ static int ieee80211_set_probe_resp(stru + memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp, + csa->n_counter_offsets_presp * + sizeof(new->cntdwn_counter_offsets[0])); ++ else if (cca) ++ new->cntdwn_counter_offsets[0] = cca->counter_offset_presp; + + rcu_assign_pointer(sdata->u.ap.probe_resp, new); + if (old) +@@ -954,7 +958,8 @@ static int ieee80211_set_ftm_responder_p + + static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, + struct cfg80211_beacon_data *params, +- const struct ieee80211_csa_settings *csa) ++ const struct ieee80211_csa_settings *csa, ++ const struct ieee80211_color_change_settings *cca) + { + struct beacon_data *new, *old; + int new_head_len, new_tail_len; +@@ -1003,6 +1008,9 @@ static int ieee80211_assign_beacon(struc + memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon, + csa->n_counter_offsets_beacon * + sizeof(new->cntdwn_counter_offsets[0])); ++ } else if (cca) { ++ new->cntdwn_current_counter = cca->count; ++ new->cntdwn_counter_offsets[0] = cca->counter_offset_beacon; + } + + /* copy in head */ +@@ -1019,7 +1027,7 @@ static int ieee80211_assign_beacon(struc + memcpy(new->tail, old->tail, new_tail_len); + + err = ieee80211_set_probe_resp(sdata, params->probe_resp, +- params->probe_resp_len, csa); ++ params->probe_resp_len, csa, cca); + if (err < 0) { + kfree(new); + return err; +@@ -1176,7 +1184,7 @@ static int ieee80211_start_ap(struct wip + if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) + sdata->vif.bss_conf.beacon_tx_rate = params->beacon_rate; + +- err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL); ++ err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL, NULL); + if (err < 0) + goto error; + changed |= err; +@@ -1231,17 +1239,17 @@ static int ieee80211_change_beacon(struc + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + sdata_assert_lock(sdata); + +- /* don't allow changing the beacon while CSA is in place - offset ++ /* don't allow changing the beacon while a countdown is in place - offset + * of channel switch counter may change + */ +- if (sdata->vif.csa_active) ++ if (sdata->vif.csa_active || sdata->vif.color_change_active) + return -EBUSY; + + old = sdata_dereference(sdata->u.ap.beacon, sdata); + if (!old) + return -ENOENT; + +- err = ieee80211_assign_beacon(sdata, params, NULL); ++ err = ieee80211_assign_beacon(sdata, params, NULL, NULL); + if (err < 0) + return err; + ieee80211_bss_info_change_notify(sdata, err); +@@ -3174,7 +3182,7 @@ static int ieee80211_set_after_csa_beaco + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, +- NULL); ++ NULL, NULL); + kfree(sdata->u.ap.next_beacon); + sdata->u.ap.next_beacon = NULL; + +@@ -3340,7 +3348,7 @@ static int ieee80211_set_csa_beacon(stru + csa.n_counter_offsets_presp = params->n_counter_offsets_presp; + csa.count = params->count; + +- err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa); ++ err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL); + if (err < 0) { + kfree(sdata->u.ap.next_beacon); + return err; +@@ -3428,6 +3436,15 @@ static int ieee80211_set_csa_beacon(stru + return 0; + } + ++static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) ++{ ++ sdata->vif.color_change_active = false; ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ ++ cfg80211_color_change_aborted_notify(sdata->dev); ++} ++ + static int + __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_csa_settings *params) +@@ -3496,6 +3513,10 @@ __ieee80211_channel_switch(struct wiphy + goto out; + } + ++ /* if there is a color change in progress, abort it */ ++ if (sdata->vif.color_change_active) ++ ieee80211_color_change_abort(sdata); ++ + err = ieee80211_set_csa_beacon(sdata, params, &changed); + if (err) { + ieee80211_vif_unreserve_chanctx(sdata); +@@ -4147,6 +4168,196 @@ static int ieee80211_set_sar_specs(struc + return local->ops->set_sar_specs(&local->hw, sar); + } + ++static int ++ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata, ++ u32 *changed) ++{ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP: { ++ int ret; ++ ++ ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, ++ NULL, NULL); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ ++ if (ret < 0) ++ return ret; ++ ++ *changed |= ret; ++ break; ++ } ++ default: ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata, ++ struct cfg80211_color_change_settings *params, ++ u32 *changed) ++{ ++ struct ieee80211_color_change_settings color_change = {}; ++ int err; ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP: ++ sdata->u.ap.next_beacon = ++ cfg80211_beacon_dup(¶ms->beacon_next); ++ if (!sdata->u.ap.next_beacon) ++ return -ENOMEM; ++ ++ if (params->count <= 1) ++ break; ++ ++ color_change.counter_offset_beacon = ++ params->counter_offset_beacon; ++ color_change.counter_offset_presp = ++ params->counter_offset_presp; ++ color_change.count = params->count; ++ ++ err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change, ++ NULL, &color_change); ++ if (err < 0) { ++ kfree(sdata->u.ap.next_beacon); ++ return err; ++ } ++ *changed |= err; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static void ++ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata, ++ u8 color, int enable, u32 changed) ++{ ++ sdata->vif.bss_conf.he_bss_color.color = color; ++ sdata->vif.bss_conf.he_bss_color.enabled = enable; ++ changed |= BSS_CHANGED_HE_BSS_COLOR; ++ ++ ieee80211_bss_info_change_notify(sdata, changed); ++} ++ ++static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ u32 changed = 0; ++ int err; ++ ++ sdata_assert_lock(sdata); ++ lockdep_assert_held(&local->mtx); ++ ++ sdata->vif.color_change_active = false; ++ ++ err = ieee80211_set_after_color_change_beacon(sdata, &changed); ++ if (err) { ++ cfg80211_color_change_aborted_notify(sdata->dev); ++ return err; ++ } ++ ++ ieee80211_color_change_bss_config_notify(sdata, ++ sdata->vif.color_change_color, ++ 1, changed); ++ cfg80211_color_change_notify(sdata->dev); ++ ++ return 0; ++} ++ ++void ieee80211_color_change_finalize_work(struct work_struct *work) ++{ ++ struct ieee80211_sub_if_data *sdata = ++ container_of(work, struct ieee80211_sub_if_data, ++ color_change_finalize_work); ++ struct ieee80211_local *local = sdata->local; ++ ++ sdata_lock(sdata); ++ mutex_lock(&local->mtx); ++ ++ /* AP might have been stopped while waiting for the lock. */ ++ if (!sdata->vif.color_change_active) ++ goto unlock; ++ ++ if (!ieee80211_sdata_running(sdata)) ++ goto unlock; ++ ++ ieee80211_color_change_finalize(sdata); ++ ++unlock: ++ mutex_unlock(&local->mtx); ++ sdata_unlock(sdata); ++} ++ ++void ieee80211_color_change_finish(struct ieee80211_vif *vif) ++{ ++ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ ++ ieee80211_queue_work(&sdata->local->hw, ++ &sdata->color_change_finalize_work); ++} ++EXPORT_SYMBOL_GPL(ieee80211_color_change_finish); ++ ++void ++ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif, ++ u64 color_bitmap) ++{ ++ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ ++ if (sdata->vif.color_change_active || sdata->vif.csa_active) ++ return; ++ ++ cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap); ++} ++EXPORT_SYMBOL_GPL(ieeee80211_obss_color_collision_notify); ++ ++static int ++ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_color_change_settings *params) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ u32 changed = 0; ++ int err; ++ ++ sdata_assert_lock(sdata); ++ ++ mutex_lock(&local->mtx); ++ ++ /* don't allow another color change if one is already active or if csa ++ * is active ++ */ ++ if (sdata->vif.color_change_active || sdata->vif.csa_active) { ++ err = -EBUSY; ++ goto out; ++ } ++ ++ err = ieee80211_set_color_change_beacon(sdata, params, &changed); ++ if (err) ++ goto out; ++ ++ sdata->vif.color_change_active = true; ++ sdata->vif.color_change_color = params->color; ++ ++ cfg80211_color_change_started_notify(sdata->dev, params->count); ++ ++ if (changed) ++ ieee80211_color_change_bss_config_notify(sdata, 0, 0, changed); ++ else ++ /* if the beacon didn't change, we can finalize immediately */ ++ ieee80211_color_change_finalize(sdata); ++ ++out: ++ mutex_unlock(&local->mtx); ++ ++ return err; ++} ++ + const struct cfg80211_ops mac80211_config_ops = { + .add_virtual_intf = ieee80211_add_iface, + .del_virtual_intf = ieee80211_del_iface, +@@ -4251,4 +4462,5 @@ const struct cfg80211_ops mac80211_confi + .set_tid_config = ieee80211_set_tid_config, + .reset_tid_config = ieee80211_reset_tid_config, + .set_sar_specs = ieee80211_set_sar_specs, ++ .color_change = ieee80211_color_change, + }; +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -248,6 +248,12 @@ struct ieee80211_csa_settings { + u8 count; + }; + ++struct ieee80211_color_change_settings { ++ u16 counter_offset_beacon; ++ u16 counter_offset_presp; ++ u8 count; ++}; ++ + struct beacon_data { + u8 *head, *tail; + int head_len, tail_len; +@@ -932,6 +938,8 @@ struct ieee80211_sub_if_data { + bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ + struct cfg80211_chan_def csa_chandef; + ++ struct work_struct color_change_finalize_work; ++ + struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ + struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */ + +@@ -1900,6 +1908,9 @@ void ieee80211_csa_finalize_work(struct + int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_csa_settings *params); + ++/* color change handling */ ++void ieee80211_color_change_finalize_work(struct work_struct *work); ++ + /* interface handling */ + #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ + NETIF_F_HW_CSUM | NETIF_F_SG | \ +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -465,6 +465,7 @@ static void ieee80211_do_stop(struct iee + sdata_unlock(sdata); + + cancel_work_sync(&sdata->csa_finalize_work); ++ cancel_work_sync(&sdata->color_change_finalize_work); + + cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); + +@@ -1639,6 +1640,7 @@ static void ieee80211_setup_sdata(struct + INIT_WORK(&sdata->work, ieee80211_iface_work); + INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); + INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work); ++ INIT_WORK(&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work); + INIT_LIST_HEAD(&sdata->assigned_chanctx_list); + INIT_LIST_HEAD(&sdata->reserved_chanctx_list); + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4790,11 +4790,11 @@ static int ieee80211_beacon_add_tim(stru + static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata, + struct beacon_data *beacon) + { ++ u8 *beacon_data, count, max_count = 1; + struct probe_resp *resp; +- u8 *beacon_data; + size_t beacon_data_len; ++ u16 *bcn_offsets; + int i; +- u8 count = beacon->cntdwn_current_counter; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +@@ -4814,21 +4814,27 @@ static void ieee80211_set_beacon_cntdwn( + } + + rcu_read_lock(); +- for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) { +- resp = rcu_dereference(sdata->u.ap.probe_resp); ++ resp = rcu_dereference(sdata->u.ap.probe_resp); + +- if (beacon->cntdwn_counter_offsets[i]) { +- if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >= +- beacon_data_len)) { ++ bcn_offsets = beacon->cntdwn_counter_offsets; ++ count = beacon->cntdwn_current_counter; ++ if (sdata->vif.csa_active) ++ max_count = IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++ ++ for (i = 0; i < max_count; ++i) { ++ if (bcn_offsets[i]) { ++ if (WARN_ON_ONCE(bcn_offsets[i] >= beacon_data_len)) { + rcu_read_unlock(); + return; + } +- +- beacon_data[beacon->cntdwn_counter_offsets[i]] = count; ++ beacon_data[bcn_offsets[i]] = count; + } + +- if (sdata->vif.type == NL80211_IFTYPE_AP && resp) +- resp->data[resp->cntdwn_counter_offsets[i]] = count; ++ if (sdata->vif.type == NL80211_IFTYPE_AP && resp) { ++ u16 *resp_offsets = resp->cntdwn_counter_offsets; ++ ++ resp->data[resp_offsets[i]] = count; ++ } + } + rcu_read_unlock(); + } +@@ -5038,6 +5044,7 @@ __ieee80211_beacon_get(struct ieee80211_ + if (offs) { + offs->tim_offset = beacon->head_len; + offs->tim_length = skb->len - beacon->head_len; ++ offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; + + /* for AP the csa offsets are from tail */ + csa_off_base = skb->len; diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch index b2ee61a6dc..2755efb194 100644 --- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -3793,6 +3793,7 @@ struct mgmt_frame_regs { +@@ -3814,6 +3814,7 @@ struct mgmt_frame_regs { * (as advertised by the nl80211 feature flag.) * @get_tx_power: store the current TX power into the dbm variable; * return 0 if successful @@ -8,7 +8,7 @@ * * @set_wds_peer: set the WDS peer for a WDS interface * -@@ -4115,6 +4116,7 @@ struct cfg80211_ops { +@@ -4138,6 +4139,7 @@ struct cfg80211_ops { enum nl80211_tx_power_setting type, int mbm); int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); @@ -36,9 +36,9 @@ u8 ps_dtim_period; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2560,6 +2560,9 @@ enum nl80211_commands { - * disassoc events to indicate that an immediate reconnect to the AP - * is desired. +@@ -2593,6 +2593,9 @@ enum nl80211_commands { + * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE + * information for the time while performing a color switch. * + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. @@ -46,9 +46,9 @@ * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3057,6 +3060,8 @@ enum nl80211_attrs { - - NL80211_ATTR_DISABLE_HE, +@@ -3096,6 +3099,8 @@ enum nl80211_attrs { + NL80211_ATTR_COLOR_CHANGE_COLOR, + NL80211_ATTR_COLOR_CHANGE_ELEMS, + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2761,6 +2761,19 @@ static int ieee80211_get_tx_power(struct +@@ -2769,6 +2769,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -4202,6 +4215,7 @@ const struct cfg80211_ops mac80211_confi +@@ -4413,6 +4426,7 @@ const struct cfg80211_ops mac80211_confi .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, @@ -87,7 +87,7 @@ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1426,6 +1426,7 @@ struct ieee80211_local { +@@ -1434,6 +1434,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */ @@ -129,15 +129,15 @@ local->hw.max_mtu = IEEE80211_MAX_DATA_LEN; --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -753,6 +753,7 @@ static const struct nla_policy nl80211_p - NL80211_SAE_PWE_BOTH), - [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy), - [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, +@@ -757,6 +757,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 }, + [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 }, + [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy), + [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, }; /* policy for the key attributes */ -@@ -3318,6 +3319,20 @@ static int nl80211_set_wiphy(struct sk_b +@@ -3322,6 +3323,20 @@ static int nl80211_set_wiphy(struct sk_b if (result) return result; } From ea44aebc27182a8130a9999b4415efa799f9b2ad Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 24 Sep 2021 18:38:24 +0200 Subject: [PATCH 40/82] tools/fakeroot: fix build error on macOS Signed-off-by: Felix Fietkau --- tools/fakeroot/patches/100-macos_compile_fix.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tools/fakeroot/patches/100-macos_compile_fix.patch diff --git a/tools/fakeroot/patches/100-macos_compile_fix.patch b/tools/fakeroot/patches/100-macos_compile_fix.patch new file mode 100644 index 0000000000..64c0b472c6 --- /dev/null +++ b/tools/fakeroot/patches/100-macos_compile_fix.patch @@ -0,0 +1,11 @@ +--- a/libfakeroot_inode64.c ++++ b/libfakeroot_inode64.c +@@ -36,6 +36,8 @@ + #include + #endif /* HAVE_FTS_H */ + ++void load_library_symbols(void); ++ + #include "wrapped.h" + #include "wraptmpf.h" + #include "wrapdef.h" From 8ea0d08e0e9bc6ea4128048ee0ff90a775581934 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 25 Sep 2021 13:52:07 +0200 Subject: [PATCH 41/82] kernel: add patch to fix an issue with kernel headers that broke perf Signed-off-by: Felix Fietkau --- .../101-Use-stddefs.h-instead-of-compiler.h.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 target/linux/generic/pending-5.10/101-Use-stddefs.h-instead-of-compiler.h.patch diff --git a/target/linux/generic/pending-5.10/101-Use-stddefs.h-instead-of-compiler.h.patch b/target/linux/generic/pending-5.10/101-Use-stddefs.h-instead-of-compiler.h.patch new file mode 100644 index 0000000000..824b9444ee --- /dev/null +++ b/target/linux/generic/pending-5.10/101-Use-stddefs.h-instead-of-compiler.h.patch @@ -0,0 +1,11 @@ +--- a/include/uapi/linux/swab.h ++++ b/include/uapi/linux/swab.h +@@ -3,7 +3,7 @@ + #define _UAPI_LINUX_SWAB_H + + #include +-#include ++#include + #include + #include + From 16ae56b4f9ec54b4cc4d381be7f7c327c00ddc4c Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 20 Sep 2021 20:13:35 +0300 Subject: [PATCH 42/82] realtek: fix RTL8231 gpio expander for high GPIOs GPIOs > 31 require special handling. This patch fixes both the initialisation and direction get/set operations. Signed-off-by: Paul Fertser Reviewed-by: Sander Vanheule --- .../realtek/files-5.4/drivers/gpio/gpio-rtl8231.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c b/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c index 031f60f530..a8ffcdc313 100644 --- a/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c +++ b/target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c @@ -106,12 +106,11 @@ static int rtl8231_pin_dir(struct rtl8231_gpios *gpios, u32 gpio, u32 dir) u32 v; int pin_sel_addr = RTL8231_GPIO_PIN_SEL(gpio); int pin_dir_addr = RTL8231_GPIO_DIR(gpio); - int pin = gpio % 16; - int dpin = pin; + int dpin = gpio % 16; if (gpio > 31) { pr_debug("WARNING: HIGH pin\n"); - dpin = pin << 5; + dpin += 5; pin_dir_addr = pin_sel_addr; } @@ -140,7 +139,7 @@ static int rtl8231_pin_dir_get(struct rtl8231_gpios *gpios, u32 gpio, u32 *dir) if (gpio > 31) { pin_dir_addr = RTL8231_GPIO_PIN_SEL(gpio); - pin = pin << 5; + pin += 5; } v = rtl8231_read(gpios, pin_dir_addr); @@ -240,6 +239,8 @@ void rtl8231_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) int rtl8231_init(struct rtl8231_gpios *gpios) { + u32 v; + pr_info("%s called, MDIO bus ID: %d\n", __func__, gpios->smi_bus_id); gpios->reg_cached = 0; @@ -253,9 +254,11 @@ int rtl8231_init(struct rtl8231_gpios *gpios) sw_w32_mask(3, 1, RTL838X_DMY_REG5); } - /*Select GPIO functionality for pins 0-15, 16-31 and 32-37 */ + /* Select GPIO functionality for pins 0-34 */ rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(0), 0xffff); rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(16), 0xffff); + v = rtl8231_read(gpios, RTL8231_GPIO_PIN_SEL(32)); + rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(32), v | 0x7); return 0; } From 7ff0efa0b0dc5719b19ffafcee5544f55f05be4b Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 18 Sep 2021 21:39:04 +0900 Subject: [PATCH 43/82] ramips: add support for I-O DATA WN-DX2033GR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I-O DATA WN-DX2033GR is a 2.4/5 GHz band 11ac (Wi-Fi 5) router, based on MT7621A. Specification: - SoC : MediaTek MT7621A - RAM : DDR3 128 MiB - Flash : Raw NAND 128 MiB (Macronix MX30LF1G18AC-TI) - WLAN : 2.4/5 GHz - 2.4 GHz : 2T2R, MediaTek MT7603E - 5 GHz : 4T4R, MediaTek MT7615 - Ethernet : 5x 10/100/1000 Mbps - Switch : MediaTek MT7530 (SoC) - LEDs/Keys : 2x/3x (2x buttons, 1x slide-switch) - UART : through-hole on PCB - J5: 3.3V, TX, RX, NC, GND from triangle mark - 57600n8 - Power : 12 VDC, 1 A Flash instruction using initramfs image: 1. Boot WN-DX2033GR normally 2. Access to "http://192.168.0.1/" and open firmware update page ("ファームウェア") 3. Select the OpenWrt initramfs image and click update ("更新") button to perform firmware update 4. On the initramfs image, download the sysupgrade.bin image to the device and perform sysupgrade with it 5. Wait ~120 seconds to complete flashing Notes: - The hardware of WN-DX2033GR and WN-AX2033GR are almost the same, and it is certified under the same radio-wave related regulations in Japan - The last 0x80000 (512 KiB) in NAND flash is not used on stock firmware - stock firmware requires "customized uImage header" (called as "combo image") by MSTC (MitraStar Technology Corp.), but U-Boot doesn't - uImage magic ( 0x0 - 0x3 ) : 0x434F4D42 ("COMB") - header crc32 ( 0x4 - 0x7 ) : with "data length" and "data crc32" - image name (0x20 - 0x37) : model ID and firmware versions - data length (0x38 - 0x3b) : kernel + rootfs - data crc32 (0x3c - 0x3f) : kernel + rootfs - There are 2x important flags in the flash: - bootnum : select os partition for booting (persist, 0x4) - 0x01: firmware - 0x02: firmware_2 - debugflag : allow interrupt kernel loader, it's named as "Z-LOADER" (Factory, 0xFE75) - 0x00: disable debug - 0x01: enable debug MAC addresses: LAN : 50:41:B9:xx:xx:90 (Factory, 0xE000 (hex) / Ubootenv, ethaddr (text)) WAN : 50:41:B9:xx:xx:92 (Factory, 0xE006 (hex)) 2.4 GHz : 50:41:B9:xx:xx:90 (Factory, 0x4 (hex)) 5 GHz : 50:41:B9:xx:xx:91 (Factory, 0x8004 (hex)) Signed-off-by: INAGAKI Hiroshi --- .../ramips/dts/mt7621_iodata_wn-dx2033gr.dts | 40 +++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 9 +++++ .../mt7621/base-files/lib/upgrade/platform.sh | 3 +- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts new file mode 100644 index 0000000000..ce02def7ff --- /dev/null +++ b/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621_iodata_wn-xx-xr.dtsi" + +/ { + compatible = "iodata,wn-dx2033gr", "mediatek,mt7621-soc"; + model = "I-O DATA WN-DX2033GR"; +}; + +&partitions { + partition@6b00000 { + label = "idmkey"; + reg = <0x6b00000 0x0100000>; + read-only; + }; + + partition@6c00000 { + label = "Backup"; + reg = <0x6c00000 0x1380000>; + read-only; + }; +}; + +&pcie0 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x0>; + ieee80211-freq-limit = <2400000 2483000>; + }; +}; + +&pcie1 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x8000>; + ieee80211-freq-limit = <5000000 5710000>; + }; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 6e7391baef..d28aa96224 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -707,6 +707,15 @@ define Device/iodata_wn-dx1200gr endef TARGET_DEVICES += iodata_wn-dx1200gr +define Device/iodata_wn-dx2033gr + $(Device/iodata_nand) + DEVICE_MODEL := WN-DX2033GR + KERNEL_INITRAMFS := $(KERNEL_DTB) | loader-kernel | lzma | \ + uImage lzma -M 0x434f4d42 -n '3.10(XID.0)b30' | iodata-mstc-header + DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615e kmod-mt7615-firmware +endef +TARGET_DEVICES += iodata_wn-dx2033gr + define Device/iodata_wn-gx300gr $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh index ef9b680f32..a925dd0f18 100755 --- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh +++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh @@ -84,7 +84,8 @@ platform_do_upgrade() { ;; iodata,wn-ax1167gr2|\ iodata,wn-ax2033gr|\ - iodata,wn-dx1167r) + iodata,wn-dx1167r|\ + iodata,wn-dx2033gr) iodata_mstc_upgrade_prepare "0xfe75" nand_do_upgrade "$1" ;; From 8f27ac5ec066e6cc85013eb49150aa5d7144de33 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 13 Sep 2021 14:08:35 +0200 Subject: [PATCH 44/82] ipq40xx: 5.10: copy patches Copy over the 5.4 kernel patches to 5.10 folder. Signed-off-by: Robert Marko --- ...5.7-ARM-qcom-Add-support-for-IPQ40xx.patch | 42 + ...r-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch | 153 +++ ...om-ipq4019-Add-SDHCI-controller-node.patch | 36 + ...om-Add-nodes-for-SMP-boot-in-IPQ40xx.patch | 71 ++ ...RM-dts-qcom-add-gpio-ranges-property.patch | 119 +++ ...om-ipq4019-fix-high-resolution-timer.patch | 33 + ...net-phy-mdio-add-IPQ4019-MDIO-driver.patch | 210 ++++ ...2-ARM-dts-qcom-ipq4019-add-MDIO-node.patch | 57 + ...add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch | 31 + ....5-crypto-qce-switch-to-skcipher-API.patch | 993 ++++++++++++++++++ ...ce-fix-ctr-aes-qce-block-chunk-sizes.patch | 43 + ...crypto-qce-fix-xts-aes-qce-key-sizes.patch | 60 ++ ...-save-a-sg-table-slot-for-result-buf.patch | 85 ++ ....6-crypto-qce-update-the-skcipher-IV.patch | 31 + ...qce-initialize-fallback-only-for-AES.patch | 54 + ...e-allow-building-only-hashes-ciphers.patch | 419 ++++++++ ...e-use-cryptlen-when-adding-extra-sgl.patch | 89 ++ ...-use-AES-fallback-for-small-requests.patch | 113 ++ ...-handle-AES-XTS-cases-that-qce-fails.patch | 59 ++ ...-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch | 197 ++++ .../0018-v5.9-pinctrl-msm-open-drain.patch | 81 ++ ...d-spi-nor-Add-support-for-mx25r3235f.patch | 29 + .../100-GPIO-add-named-gpio-exports.patch | 165 +++ ...dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch | 32 + ...com-ipq4019-add-USB-devicetree-nodes.patch | 97 ++ ...arm-dts-qcom-ipq4019-add-more-labels.patch | 42 + .../104-clk-fix-apss-cpu-overclocking.patch | 115 ++ .../300-clk-qcom-ipq4019-add-ess-reset.patch | 52 + ...-compressed-add-appended-DTB-section.patch | 48 + ...d-set-ipq40xx-watchdog-to-allow-boot.patch | 66 ++ ...msm-use-sdhci_set_clock-instead-of-s.patch | 25 + ...702-dts-ipq4019-add-PHY-switch-nodes.patch | 46 + ...4019-needs-rfs-vlan_tag-callbacks-in.patch | 53 + .../705-net-add-qualcomm-ar40xx-phy.patch | 26 + .../706-dt-bindings-net-add-QCA807x-PHY.patch | 61 ++ ...7-net-phy-Add-Qualcom-QCA807x-driver.patch | 50 + ...8-arm-dts-ipq4019-QCA807x-properties.patch | 62 ++ ...add-qualcomm-essedma-ethernet-driver.patch | 37 + ...ts-ipq4019-add-ethernet-essedma-node.patch | 92 ++ .../850-soc-add-qualcomm-syscon.patch | 180 ++++ .../900-dts-ipq4019-ap-dk01.1.patch | 176 ++++ .../901-arm-boot-add-dts-files.patch | 74 ++ .../902-dts-ipq4019-ap-dk04.1.patch | 167 +++ .../997-device_tree_cmdline.patch | 12 + 44 files changed, 4683 insertions(+) create mode 100644 target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch create mode 100644 target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch create mode 100644 target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch create mode 100644 target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch create mode 100644 target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch create mode 100644 target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch create mode 100644 target/linux/ipq40xx/patches-5.10/104-clk-fix-apss-cpu-overclocking.patch create mode 100644 target/linux/ipq40xx/patches-5.10/300-clk-qcom-ipq4019-add-ess-reset.patch create mode 100644 target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch create mode 100644 target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch create mode 100644 target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch create mode 100644 target/linux/ipq40xx/patches-5.10/702-dts-ipq4019-add-PHY-switch-nodes.patch create mode 100644 target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch create mode 100644 target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch create mode 100644 target/linux/ipq40xx/patches-5.10/706-dt-bindings-net-add-QCA807x-PHY.patch create mode 100644 target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch create mode 100644 target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch create mode 100644 target/linux/ipq40xx/patches-5.10/710-net-add-qualcomm-essedma-ethernet-driver.patch create mode 100644 target/linux/ipq40xx/patches-5.10/711-dts-ipq4019-add-ethernet-essedma-node.patch create mode 100644 target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch create mode 100644 target/linux/ipq40xx/patches-5.10/900-dts-ipq4019-ap-dk01.1.patch create mode 100644 target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch create mode 100644 target/linux/ipq40xx/patches-5.10/902-dts-ipq4019-ap-dk04.1.patch create mode 100644 target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch diff --git a/target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch b/target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch new file mode 100644 index 0000000000..8aa71f360f --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch @@ -0,0 +1,42 @@ +From f125e2d4339dda6937865f975470b29c84714c9b Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Mon, 6 Jan 2020 14:57:15 +0100 +Subject: [PATCH] ARM: qcom: Add support for IPQ40xx + +Add support for the Qualcomm IPQ40xx SoC in Kconfig. +Also add its appropriate textofs. + +Signed-off-by: Christian Lamparter +Signed-off-by: John Crispin +Tested-by: Robert Marko +Cc: Luka Perkov +Signed-off-by: Arnd Bergmann +--- + arch/arm/Makefile | 1 + + arch/arm/mach-qcom/Kconfig | 5 +++++ + 2 files changed, 6 insertions(+) + +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -152,6 +152,7 @@ textofs-$(CONFIG_PM_H1940) := 0x001 + ifeq ($(CONFIG_ARCH_SA1100),y) + textofs-$(CONFIG_SA1111) := 0x00208000 + endif ++textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000 + textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 + textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 + textofs-$(CONFIG_ARCH_MESON) := 0x00208000 +--- a/arch/arm/mach-qcom/Kconfig ++++ b/arch/arm/mach-qcom/Kconfig +@@ -12,6 +12,11 @@ menuconfig ARCH_QCOM + + if ARCH_QCOM + ++config ARCH_IPQ40XX ++ bool "Enable support for IPQ40XX" ++ select CLKSRC_QCOM ++ select HAVE_ARM_ARCH_TIMER ++ + config ARCH_MSM8X60 + bool "Enable support for MSM8X60" + select CLKSRC_QCOM diff --git a/target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch b/target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch new file mode 100644 index 0000000000..aaf8c807ed --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch @@ -0,0 +1,153 @@ +From 97043d292365ae39d62b54a6d79dff98d048b501 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 22 Jan 2020 12:44:14 +0100 +Subject: [PATCH] From ebf652b408200504194be32ad0a3f5bb49d6000a Mon Sep 17 + 00:00:00 2001 From: Robert Marko Date: Sun, 12 Jan + 2020 12:30:01 +0100 Subject: [PATCH] regulator: add IPQ4019 SDHCI VQMMC LDO + driver + +This introduces the IPQ4019 VQMMC LDO driver needed for +the SD/EMMC driver I/O level operation. +This will enable introducing SD/EMMC support for the built-in controller. + +Signed-off-by: Mantas Pucka +Signed-off-by: Robert Marko +Link: https://lore.kernel.org/r/20200112113003.11110-1-robert.marko@sartura.hr +Signed-off-by: Mark Brown +--- + drivers/regulator/Kconfig | 7 ++ + drivers/regulator/Makefile | 1 + + drivers/regulator/vqmmc-ipq4019-regulator.c | 101 ++++++++++++++++++++ + 3 files changed, 109 insertions(+) + create mode 100644 drivers/regulator/vqmmc-ipq4019-regulator.c + +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -1077,6 +1077,13 @@ config REGULATOR_VEXPRESS + This driver provides support for voltage regulators available + on the ARM Ltd's Versatile Express platform. + ++config REGULATOR_VQMMC_IPQ4019 ++ tristate "IPQ4019 VQMMC SD LDO regulator support" ++ depends on ARCH_QCOM ++ help ++ This driver provides support for the VQMMC LDO I/0 ++ voltage regulator of the IPQ4019 SD/EMMC controller. ++ + config REGULATOR_WM831X + tristate "Wolfson Microelectronics WM831x PMIC regulators" + depends on MFD_WM831X +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -132,6 +132,7 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-r + obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o + obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o + obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o ++obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o + obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o + obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o + obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o +--- /dev/null ++++ b/drivers/regulator/vqmmc-ipq4019-regulator.c +@@ -0,0 +1,101 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// ++// Copyright (c) 2019 Mantas Pucka ++// Copyright (c) 2019 Robert Marko ++// ++// Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static const unsigned int ipq4019_vmmc_voltages[] = { ++ 1500000, 1800000, 2500000, 3000000, ++}; ++ ++static const struct regulator_ops ipq4019_regulator_voltage_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .map_voltage = regulator_map_voltage_ascend, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++}; ++ ++static const struct regulator_desc vmmc_regulator = { ++ .name = "vmmcq", ++ .ops = &ipq4019_regulator_voltage_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++ .volt_table = ipq4019_vmmc_voltages, ++ .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages), ++ .vsel_reg = 0, ++ .vsel_mask = 0x3, ++}; ++ ++static const struct regmap_config ipq4019_vmmcq_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++}; ++ ++static int ipq4019_regulator_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct regulator_init_data *init_data; ++ struct regulator_config cfg = {}; ++ struct regulator_dev *rdev; ++ struct resource *res; ++ struct regmap *rmap; ++ void __iomem *base; ++ ++ init_data = of_get_regulator_init_data(dev, dev->of_node, ++ &vmmc_regulator); ++ if (!init_data) ++ return -EINVAL; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config); ++ if (IS_ERR(rmap)) ++ return PTR_ERR(rmap); ++ ++ cfg.dev = dev; ++ cfg.init_data = init_data; ++ cfg.of_node = dev->of_node; ++ cfg.regmap = rmap; ++ ++ rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg); ++ if (IS_ERR(rdev)) { ++ dev_err(dev, "Failed to register regulator: %ld\n", ++ PTR_ERR(rdev)); ++ return PTR_ERR(rdev); ++ } ++ platform_set_drvdata(pdev, rdev); ++ ++ return 0; ++} ++ ++static const struct of_device_id regulator_ipq4019_of_match[] = { ++ { .compatible = "qcom,vqmmc-ipq4019-regulator", }, ++ {}, ++}; ++ ++static struct platform_driver ipq4019_regulator_driver = { ++ .probe = ipq4019_regulator_probe, ++ .driver = { ++ .name = "vqmmc-ipq4019-regulator", ++ .of_match_table = of_match_ptr(regulator_ipq4019_of_match), ++ }, ++}; ++module_platform_driver(ipq4019_regulator_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Mantas Pucka "); ++MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator"); diff --git a/target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch b/target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch new file mode 100644 index 0000000000..25fce8daf0 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch @@ -0,0 +1,36 @@ +From 04b3b72b5b8fdb883bfdc619cb29b03641b1cc6a Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 15 Aug 2019 19:28:23 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: Add SDHCI controller node + +IPQ4019 has a built in SD/eMMC controller which is supported by the +SDHCI MSM driver, by the "qcom,sdhci-msm-v4" binding. +So lets add the appropriate node for it. + +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -206,6 +206,18 @@ + interrupts = ; + }; + ++ sdhci: sdhci@7824900 { ++ compatible = "qcom,sdhci-msm-v4"; ++ reg = <0x7824900 0x11c>, <0x7824000 0x800>; ++ interrupts = , ; ++ interrupt-names = "hc_irq", "pwr_irq"; ++ bus-width = <8>; ++ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>, ++ <&gcc GCC_DCD_XO_CLK>; ++ clock-names = "core", "iface", "xo"; ++ status = "disabled"; ++ }; ++ + blsp_dma: dma@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x23000>; diff --git a/target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch b/target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch new file mode 100644 index 0000000000..3a4127febf --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch @@ -0,0 +1,71 @@ +From 5e4548922009870a38bcf1d887317676d4e08f54 Mon Sep 17 00:00:00 2001 +From: Damir Franusic +Date: Thu, 21 Nov 2019 16:29:02 +0100 +Subject: [PATCH] ARM: dts: qcom: Add nodes for SMP boot in IPQ40xx + +Add missing nodes and properties to enable SMP +support on IPQ40xx devices. + +Booting without "saw_l2" node: + +[ 0.001400] CPU: Testing write buffer coherency: ok +[ 0.001856] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 +[ 0.060163] Setting up static identity map for 0x80300000 - 0x80300060 +[ 0.080140] rcu: Hierarchical SRCU implementation. +[ 0.120258] smp: Bringing up secondary CPUs ... +[ 0.200540] CPU1: failed to boot: -19 +[ 0.280689] CPU2: failed to boot: -19 +[ 0.360874] CPU3: failed to boot: -19 +[ 0.360966] smp: Brought up 1 node, 1 CPU +[ 0.360979] SMP: Total of 1 processors activated (96.00 BogoMIPS). +[ 0.360988] CPU: All CPU(s) started in SVC mode. + +Then, booting with "saw_l2" node present (this patch applied): + +[ 0.001450] CPU: Testing write buffer coherency: ok +[ 0.001904] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 +[ 0.060161] Setting up static identity map for 0x80300000 - 0x80300060 +[ 0.080137] rcu: Hierarchical SRCU implementation. +[ 0.120252] smp: Bringing up secondary CPUs ... +[ 0.200958] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 +[ 0.281091] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002 +[ 0.361264] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003 +[ 0.361430] smp: Brought up 1 node, 4 CPUs +[ 0.361460] SMP: Total of 4 processors activated (384.00 BogoMIPS). +[ 0.361469] CPU: All CPU(s) started in SVC mode. + +Signed-off-by: Damir Franusic +Cc: Luka Perkov +Cc: Robert Marko +Cc: Andy Gross +Cc: Rob Herring +Cc: linux-arm-msm@vger.kernel.org +Link: https://lore.kernel.org/r/20191121152902.21394-1-damir.franusic@gmail.com +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -102,6 +102,7 @@ + L2: l2-cache { + compatible = "cache"; + cache-level = <2>; ++ qcom,saw = <&saw_l2>; + }; + }; + +@@ -353,6 +354,12 @@ + regulator; + }; + ++ saw_l2: regulator@b012000 { ++ compatible = "qcom,saw2"; ++ reg = <0xb012000 0x1000>; ++ regulator; ++ }; ++ + blsp1_uart1: serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x78af000 0x200>; diff --git a/target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch b/target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch new file mode 100644 index 0000000000..6922bc8ff3 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch @@ -0,0 +1,119 @@ +From 8b99dc0922618062a1589ebd74df6108b4f9ac22 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Wed, 8 Jan 2020 13:54:55 +0100 +Subject: [PATCH] ARM: dts: qcom: add gpio-ranges property + +This patch adds the gpio-ranges property to almost all of +the Qualcomm ARM platforms that utilize the pinctrl-msm +framework. + +The gpio-ranges property is part of the gpiolib subsystem. +As a result, the binding text is available in section +"2.1 gpio- and pin-controller interaction" of +Documentation/devicetree/bindings/gpio/gpio.txt + +For more information please see the patch titled: +"pinctrl: msm: fix gpio-hog related boot issues" from +this series. + +Reported-by: Sven Eckelmann +Tested-by: Sven Eckelmann [ipq4019] +Reviewed-by: Bjorn Andersson +Reviewed-by: Linus Walleij +Signed-off-by: Christian Lamparter +Tested-by: Robert Marko [ipq4019] +Cc: Luka Perkov +Signed-off-by: Robert Marko +Link: https://lore.kernel.org/r/20200108125455.308969-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-apq8064.dtsi | 1 + + arch/arm/boot/dts/qcom-apq8084.dtsi | 1 + + arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + + arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 + + arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 + + arch/arm/boot/dts/qcom-msm8660.dtsi | 1 + + arch/arm/boot/dts/qcom-msm8960.dtsi | 1 + + arch/arm/boot/dts/qcom-msm8974.dtsi | 1 + + 8 files changed, 8 insertions(+) + +--- a/arch/arm/boot/dts/qcom-apq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-apq8064.dtsi +@@ -350,6 +350,7 @@ + reg = <0x800000 0x4000>; + + gpio-controller; ++ gpio-ranges = <&tlmm_pinmux 0 0 90>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-apq8084.dtsi ++++ b/arch/arm/boot/dts/qcom-apq8084.dtsi +@@ -401,6 +401,7 @@ + compatible = "qcom,apq8084-pinctrl"; + reg = <0xfd510000 0x4000>; + gpio-controller; ++ gpio-ranges = <&tlmm 0 0 147>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -201,6 +201,7 @@ + compatible = "qcom,ipq4019-pinctrl"; + reg = <0x01000000 0x300000>; + gpio-controller; ++ gpio-ranges = <&tlmm 0 0 100>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi +@@ -119,6 +119,7 @@ + reg = <0x800000 0x4000>; + + gpio-controller; ++ gpio-ranges = <&qcom_pinmux 0 0 69>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-mdm9615.dtsi ++++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi +@@ -128,6 +128,7 @@ + msmgpio: pinctrl@800000 { + compatible = "qcom,mdm9615-pinctrl"; + gpio-controller; ++ gpio-ranges = <&msmgpio 0 0 88>; + #gpio-cells = <2>; + interrupts = ; + interrupt-controller; +--- a/arch/arm/boot/dts/qcom-msm8660.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8660.dtsi +@@ -115,6 +115,7 @@ + reg = <0x800000 0x4000>; + + gpio-controller; ++ gpio-ranges = <&tlmm 0 0 173>; + #gpio-cells = <2>; + interrupts = <0 16 0x4>; + interrupt-controller; +--- a/arch/arm/boot/dts/qcom-msm8960.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8960.dtsi +@@ -107,6 +107,7 @@ + msmgpio: pinctrl@800000 { + compatible = "qcom,msm8960-pinctrl"; + gpio-controller; ++ gpio-ranges = <&msmgpio 0 0 152>; + #gpio-cells = <2>; + interrupts = <0 16 0x4>; + interrupt-controller; +--- a/arch/arm/boot/dts/qcom-msm8974.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8974.dtsi +@@ -707,6 +707,7 @@ + compatible = "qcom,msm8974-pinctrl"; + reg = <0xfd510000 0x4000>; + gpio-controller; ++ gpio-ranges = <&msmgpio 0 0 146>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; diff --git a/target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch b/target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch new file mode 100644 index 0000000000..f82021f4cd --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch @@ -0,0 +1,33 @@ +From 8acc36189dcaf4487d8c6ba7445948f39b1d248a Mon Sep 17 00:00:00 2001 +From: Abhishek Sahu +Date: Fri, 3 Apr 2020 13:40:40 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: fix high resolution timer + +Cherry-picked from CAF QSDK repo. +Original commit message: +The kernel is failing in switching the timer for high resolution +mode and clock source operates in 10ms resolution. The always-on +property needs to be given for timer device tree node to make +clock source working in 1ns resolution. + +Signed-off-by: Abhishek Sahu +Signed-off-by: Pavel Kubelun +Signed-off-by: Christian Lamparter +Tested-by: Robert Marko +Cc: Luka Perkov +Link: https://lore.kernel.org/r/20200403114040.349787-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -166,6 +166,7 @@ + <1 4 0xf08>, + <1 1 0xf08>; + clock-frequency = <48000000>; ++ always-on; + }; + + soc { diff --git a/target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch b/target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch new file mode 100644 index 0000000000..d678f761f5 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch @@ -0,0 +1,210 @@ +From 466ed24fb22342f3ae1c10758a6a0c6a8c081b2d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 30 Apr 2020 11:07:05 +0200 +Subject: [PATCH] net: phy: mdio: add IPQ4019 MDIO driver + +This patch adds the driver for the MDIO interface +inside of Qualcomm IPQ40xx series SoC-s. + +Signed-off-by: Christian Lamparter +Signed-off-by: Robert Marko +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Cc: Luka Perkov +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 7 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mdio-ipq4019.c | 160 +++++++++++++++++++++++++++++++++ + 3 files changed, 168 insertions(+) + create mode 100644 drivers/net/phy/mdio-ipq4019.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -156,6 +156,13 @@ config MDIO_I2C + + This is library mode. + ++config MDIO_IPQ4019 ++ tristate "Qualcomm IPQ4019 MDIO interface support" ++ depends on HAS_IOMEM && OF_MDIO ++ help ++ This driver supports the MDIO interface found in Qualcomm ++ IPQ40xx series Soc-s. ++ + config MDIO_MOXART + tristate "MOXA ART MDIO interface support" + depends on ARCH_MOXART || COMPILE_TEST +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium + obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o + obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o + obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o ++obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o + obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o + obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o + obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o +--- /dev/null ++++ b/drivers/net/phy/mdio-ipq4019.c +@@ -0,0 +1,160 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright (c) 2015, The Linux Foundation. All rights reserved. */ ++/* Copyright (c) 2020 Sartura Ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MDIO_ADDR_REG 0x44 ++#define MDIO_DATA_WRITE_REG 0x48 ++#define MDIO_DATA_READ_REG 0x4c ++#define MDIO_CMD_REG 0x50 ++#define MDIO_CMD_ACCESS_BUSY BIT(16) ++#define MDIO_CMD_ACCESS_START BIT(8) ++#define MDIO_CMD_ACCESS_CODE_READ 0 ++#define MDIO_CMD_ACCESS_CODE_WRITE 1 ++ ++#define ipq4019_MDIO_TIMEOUT 10000 ++#define ipq4019_MDIO_SLEEP 10 ++ ++struct ipq4019_mdio_data { ++ void __iomem *membase; ++}; ++ ++static int ipq4019_mdio_wait_busy(struct mii_bus *bus) ++{ ++ struct ipq4019_mdio_data *priv = bus->priv; ++ unsigned int busy; ++ ++ return readl_poll_timeout(priv->membase + MDIO_CMD_REG, busy, ++ (busy & MDIO_CMD_ACCESS_BUSY) == 0, ++ ipq4019_MDIO_SLEEP, ipq4019_MDIO_TIMEOUT); ++} ++ ++static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct ipq4019_mdio_data *priv = bus->priv; ++ unsigned int cmd; ++ ++ /* Reject clause 45 */ ++ if (regnum & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ /* issue the phy address and reg */ ++ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); ++ ++ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ; ++ ++ /* issue read command */ ++ writel(cmd, priv->membase + MDIO_CMD_REG); ++ ++ /* Wait read complete */ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ /* Read and return data */ ++ return readl(priv->membase + MDIO_DATA_READ_REG); ++} ++ ++static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct ipq4019_mdio_data *priv = bus->priv; ++ unsigned int cmd; ++ ++ /* Reject clause 45 */ ++ if (regnum & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ /* issue the phy address and reg */ ++ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); ++ ++ /* issue write data */ ++ writel(value, priv->membase + MDIO_DATA_WRITE_REG); ++ ++ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE; ++ /* issue write command */ ++ writel(cmd, priv->membase + MDIO_CMD_REG); ++ ++ /* Wait write complete */ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static int ipq4019_mdio_probe(struct platform_device *pdev) ++{ ++ struct ipq4019_mdio_data *priv; ++ struct mii_bus *bus; ++ int ret; ++ ++ bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); ++ if (!bus) ++ return -ENOMEM; ++ ++ priv = bus->priv; ++ ++ priv->membase = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->membase)) ++ return PTR_ERR(priv->membase); ++ ++ bus->name = "ipq4019_mdio"; ++ bus->read = ipq4019_mdio_read; ++ bus->write = ipq4019_mdio_write; ++ bus->parent = &pdev->dev; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id); ++ ++ ret = of_mdiobus_register(bus, pdev->dev.of_node); ++ if (ret) { ++ dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, bus); ++ ++ return 0; ++} ++ ++static int ipq4019_mdio_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ ++ mdiobus_unregister(bus); ++ ++ return 0; ++} ++ ++static const struct of_device_id ipq4019_mdio_dt_ids[] = { ++ { .compatible = "qcom,ipq4019-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids); ++ ++static struct platform_driver ipq4019_mdio_driver = { ++ .probe = ipq4019_mdio_probe, ++ .remove = ipq4019_mdio_remove, ++ .driver = { ++ .name = "ipq4019-mdio", ++ .of_match_table = ipq4019_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(ipq4019_mdio_driver); ++ ++MODULE_DESCRIPTION("ipq4019 MDIO interface driver"); ++MODULE_AUTHOR("Qualcomm Atheros"); ++MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch b/target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch new file mode 100644 index 0000000000..1976686e8f --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch @@ -0,0 +1,57 @@ +From 9c8c0f70ec6fdac2398632c723c48277be09b7c0 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 30 Apr 2020 11:07:07 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: add MDIO node + +This patch adds the necessary MDIO interface node +to the Qualcomm IPQ4019 DTSI. + +Built-in QCA8337N switch is managed using it, +and since we have a driver for it lets add it. + +Signed-off-by: Christian Lamparter +Signed-off-by: Robert Marko +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Cc: Luka Perkov +Signed-off-by: David S. Miller +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -577,5 +577,33 @@ + "legacy"; + status = "disabled"; + }; ++ ++ mdio: mdio@90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "qcom,ipq4019-mdio"; ++ reg = <0x90000 0x64>; ++ status = "disabled"; ++ ++ ethphy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ ++ ethphy1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ ++ ethphy2: ethernet-phy@2 { ++ reg = <2>; ++ }; ++ ++ ethphy3: ethernet-phy@3 { ++ reg = <3>; ++ }; ++ ++ ethphy4: ethernet-phy@4 { ++ reg = <4>; ++ }; ++ }; + }; + }; diff --git a/target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch b/target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch new file mode 100644 index 0000000000..415d6fff99 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch @@ -0,0 +1,31 @@ +From: Eneas U de Queiroz +Subject: [PATCH] crypto: qce - add CRYPTO_ALG_KERN_DRIVER_ONLY flag + +Set the CRYPTO_ALG_KERN_DRIVER_ONLY flag to all algorithms exposed by +the qce driver, since they are all hardware accelerated, accessible +through a kernel driver only, and not available directly to userspace. + +Signed-off-by: Eneas U de Queiroz + +--- a/drivers/crypto/qce/ablkcipher.c ++++ b/drivers/crypto/qce/ablkcipher.c +@@ -380,7 +380,7 @@ static int qce_ablkcipher_register_one(c + + alg->cra_priority = 300; + alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK; ++ CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; + alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); + alg->cra_alignmask = 0; + alg->cra_type = &crypto_ablkcipher_type; +--- a/drivers/crypto/qce/sha.c ++++ b/drivers/crypto/qce/sha.c +@@ -495,7 +495,7 @@ static int qce_ahash_register_one(const + base = &alg->halg.base; + base->cra_blocksize = def->blocksize; + base->cra_priority = 300; +- base->cra_flags = CRYPTO_ALG_ASYNC; ++ base->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; + base->cra_ctxsize = sizeof(struct qce_sha_ctx); + base->cra_alignmask = 0; + base->cra_module = THIS_MODULE; diff --git a/target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch b/target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch new file mode 100644 index 0000000000..4dcb942150 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch @@ -0,0 +1,993 @@ +From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 5 Nov 2019 14:28:17 +0100 +Subject: [PATCH] crypto: qce - switch to skcipher API + +Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface") +dated 20 august 2015 introduced the new skcipher API which is supposed to +replace both blkcipher and ablkcipher. While all consumers of the API have +been converted long ago, some producers of the ablkcipher remain, forcing +us to keep the ablkcipher support routines alive, along with the matching +code to expose [a]blkciphers via the skcipher API. + +So switch this driver to the skcipher API, allowing us to finally drop the +blkcipher code in the near future. + +Reviewed-by: Stanimir Varbanov +Signed-off-by: Ard Biesheuvel +Backported-to-4.19-by: Eneas U de Queiroz + +--- a/drivers/crypto/qce/Makefile ++++ b/drivers/crypto/qce/Makefile +@@ -4,4 +4,4 @@ qcrypto-objs := core.o \ + common.o \ + dma.o \ + sha.o \ +- ablkcipher.o ++ skcipher.o +--- a/drivers/crypto/qce/cipher.h ++++ b/drivers/crypto/qce/cipher.h +@@ -45,12 +45,12 @@ struct qce_cipher_reqctx { + unsigned int cryptlen; + }; + +-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm) ++static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm) + { +- struct crypto_alg *alg = tfm->__crt_alg; +- return container_of(alg, struct qce_alg_template, alg.crypto); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ return container_of(alg, struct qce_alg_template, alg.skcipher); + } + +-extern const struct qce_algo_ops ablkcipher_ops; ++extern const struct qce_algo_ops skcipher_ops; + + #endif /* _CIPHER_H_ */ +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -304,13 +304,13 @@ go_proc: + return 0; + } + +-static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req, ++static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + u32 totallen, u32 offset) + { +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; + __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0}; + __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0}; +@@ -389,8 +389,8 @@ int qce_start(struct crypto_async_reques + u32 offset) + { + switch (type) { +- case CRYPTO_ALG_TYPE_ABLKCIPHER: +- return qce_setup_regs_ablkcipher(async_req, totallen, offset); ++ case CRYPTO_ALG_TYPE_SKCIPHER: ++ return qce_setup_regs_skcipher(async_req, totallen, offset); + case CRYPTO_ALG_TYPE_AHASH: + return qce_setup_regs_ahash(async_req, totallen, offset); + default: +--- a/drivers/crypto/qce/common.h ++++ b/drivers/crypto/qce/common.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + /* key size in bytes */ + #define QCE_SHA_HMAC_KEY_SIZE 64 +@@ -79,7 +80,7 @@ struct qce_alg_template { + unsigned long alg_flags; + const u32 *std_iv; + union { +- struct crypto_alg crypto; ++ struct skcipher_alg skcipher; + struct ahash_alg ahash; + } alg; + struct qce_device *qce; +--- a/drivers/crypto/qce/core.c ++++ b/drivers/crypto/qce/core.c +@@ -22,7 +22,7 @@ + #define QCE_QUEUE_LENGTH 1 + + static const struct qce_algo_ops *qce_ops[] = { +- &ablkcipher_ops, ++ &skcipher_ops, + &ahash_ops, + }; + +--- a/drivers/crypto/qce/ablkcipher.c ++++ /dev/null +@@ -1,440 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "cipher.h" +- +-static LIST_HEAD(ablkcipher_algs); +- +-static void qce_ablkcipher_done(void *data) +-{ +- struct crypto_async_request *async_req = data; +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +- struct qce_device *qce = tmpl->qce; +- enum dma_data_direction dir_src, dir_dst; +- u32 status; +- int error; +- bool diff_dst; +- +- diff_dst = (req->src != req->dst) ? true : false; +- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; +- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; +- +- error = qce_dma_terminate_all(&qce->dma); +- if (error) +- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n", +- error); +- +- if (diff_dst) +- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); +- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); +- +- sg_free_table(&rctx->dst_tbl); +- +- error = qce_check_status(qce, &status); +- if (error < 0) +- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status); +- +- qce->async_req_done(tmpl->qce, error); +-} +- +-static int +-qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) +-{ +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +- struct qce_device *qce = tmpl->qce; +- enum dma_data_direction dir_src, dir_dst; +- struct scatterlist *sg; +- bool diff_dst; +- gfp_t gfp; +- int ret; +- +- rctx->iv = req->info; +- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher); +- rctx->cryptlen = req->nbytes; +- +- diff_dst = (req->src != req->dst) ? true : false; +- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; +- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; +- +- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes); +- if (diff_dst) +- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); +- else +- rctx->dst_nents = rctx->src_nents; +- if (rctx->src_nents < 0) { +- dev_err(qce->dev, "Invalid numbers of src SG.\n"); +- return rctx->src_nents; +- } +- if (rctx->dst_nents < 0) { +- dev_err(qce->dev, "Invalid numbers of dst SG.\n"); +- return -rctx->dst_nents; +- } +- +- rctx->dst_nents += 1; +- +- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? +- GFP_KERNEL : GFP_ATOMIC; +- +- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); +- if (ret) +- return ret; +- +- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); +- +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); +- if (IS_ERR(sg)) { +- ret = PTR_ERR(sg); +- goto error_free; +- } +- +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); +- if (IS_ERR(sg)) { +- ret = PTR_ERR(sg); +- goto error_free; +- } +- +- sg_mark_end(sg); +- rctx->dst_sg = rctx->dst_tbl.sgl; +- +- ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); +- if (ret < 0) +- goto error_free; +- +- if (diff_dst) { +- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); +- if (ret < 0) +- goto error_unmap_dst; +- rctx->src_sg = req->src; +- } else { +- rctx->src_sg = rctx->dst_sg; +- } +- +- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, +- rctx->dst_sg, rctx->dst_nents, +- qce_ablkcipher_done, async_req); +- if (ret) +- goto error_unmap_src; +- +- qce_dma_issue_pending(&qce->dma); +- +- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0); +- if (ret) +- goto error_terminate; +- +- return 0; +- +-error_terminate: +- qce_dma_terminate_all(&qce->dma); +-error_unmap_src: +- if (diff_dst) +- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); +-error_unmap_dst: +- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); +-error_free: +- sg_free_table(&rctx->dst_tbl); +- return ret; +-} +- +-static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +- unsigned int keylen) +-{ +- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- int ret; +- +- if (!key || !keylen) +- return -EINVAL; +- +- switch (keylen) { +- case AES_KEYSIZE_128: +- case AES_KEYSIZE_256: +- break; +- default: +- goto fallback; +- } +- +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-fallback: +- ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); +- if (!ret) +- ctx->enc_keylen = keylen; +- return ret; +-} +- +-static int qce_des_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +- unsigned int keylen) +-{ +- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); +- int err; +- +- err = verify_ablkcipher_des_key(ablk, key); +- if (err) +- return err; +- +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-} +- +-static int qce_des3_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +- unsigned int keylen) +-{ +- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); +- int err; +- +- err = verify_ablkcipher_des3_key(ablk, key); +- if (err) +- return err; +- +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-} +- +-static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) +-{ +- struct crypto_tfm *tfm = +- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); +- int ret; +- +- rctx->flags = tmpl->alg_flags; +- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; +- +- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && +- ctx->enc_keylen != AES_KEYSIZE_256) { +- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); +- +- skcipher_request_set_sync_tfm(subreq, ctx->fallback); +- skcipher_request_set_callback(subreq, req->base.flags, +- NULL, NULL); +- skcipher_request_set_crypt(subreq, req->src, req->dst, +- req->nbytes, req->info); +- ret = encrypt ? crypto_skcipher_encrypt(subreq) : +- crypto_skcipher_decrypt(subreq); +- skcipher_request_zero(subreq); +- return ret; +- } +- +- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); +-} +- +-static int qce_ablkcipher_encrypt(struct ablkcipher_request *req) +-{ +- return qce_ablkcipher_crypt(req, 1); +-} +- +-static int qce_ablkcipher_decrypt(struct ablkcipher_request *req) +-{ +- return qce_ablkcipher_crypt(req, 0); +-} +- +-static int qce_ablkcipher_init(struct crypto_tfm *tfm) +-{ +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- +- memset(ctx, 0, sizeof(*ctx)); +- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx); +- +- ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(tfm), +- 0, CRYPTO_ALG_NEED_FALLBACK); +- return PTR_ERR_OR_ZERO(ctx->fallback); +-} +- +-static void qce_ablkcipher_exit(struct crypto_tfm *tfm) +-{ +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- +- crypto_free_sync_skcipher(ctx->fallback); +-} +- +-struct qce_ablkcipher_def { +- unsigned long flags; +- const char *name; +- const char *drv_name; +- unsigned int blocksize; +- unsigned int ivsize; +- unsigned int min_keysize; +- unsigned int max_keysize; +-}; +- +-static const struct qce_ablkcipher_def ablkcipher_def[] = { +- { +- .flags = QCE_ALG_AES | QCE_MODE_ECB, +- .name = "ecb(aes)", +- .drv_name = "ecb-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_AES | QCE_MODE_CBC, +- .name = "cbc(aes)", +- .drv_name = "cbc-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_AES | QCE_MODE_CTR, +- .name = "ctr(aes)", +- .drv_name = "ctr-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_AES | QCE_MODE_XTS, +- .name = "xts(aes)", +- .drv_name = "xts-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_DES | QCE_MODE_ECB, +- .name = "ecb(des)", +- .drv_name = "ecb-des-qce", +- .blocksize = DES_BLOCK_SIZE, +- .ivsize = 0, +- .min_keysize = DES_KEY_SIZE, +- .max_keysize = DES_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_DES | QCE_MODE_CBC, +- .name = "cbc(des)", +- .drv_name = "cbc-des-qce", +- .blocksize = DES_BLOCK_SIZE, +- .ivsize = DES_BLOCK_SIZE, +- .min_keysize = DES_KEY_SIZE, +- .max_keysize = DES_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_3DES | QCE_MODE_ECB, +- .name = "ecb(des3_ede)", +- .drv_name = "ecb-3des-qce", +- .blocksize = DES3_EDE_BLOCK_SIZE, +- .ivsize = 0, +- .min_keysize = DES3_EDE_KEY_SIZE, +- .max_keysize = DES3_EDE_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_3DES | QCE_MODE_CBC, +- .name = "cbc(des3_ede)", +- .drv_name = "cbc-3des-qce", +- .blocksize = DES3_EDE_BLOCK_SIZE, +- .ivsize = DES3_EDE_BLOCK_SIZE, +- .min_keysize = DES3_EDE_KEY_SIZE, +- .max_keysize = DES3_EDE_KEY_SIZE, +- }, +-}; +- +-static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def, +- struct qce_device *qce) +-{ +- struct qce_alg_template *tmpl; +- struct crypto_alg *alg; +- int ret; +- +- tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); +- if (!tmpl) +- return -ENOMEM; +- +- alg = &tmpl->alg.crypto; +- +- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); +- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", +- def->drv_name); +- +- alg->cra_blocksize = def->blocksize; +- alg->cra_ablkcipher.ivsize = def->ivsize; +- alg->cra_ablkcipher.min_keysize = def->min_keysize; +- alg->cra_ablkcipher.max_keysize = def->max_keysize; +- alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? qce_des3_setkey : +- IS_DES(def->flags) ? qce_des_setkey : +- qce_ablkcipher_setkey; +- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt; +- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt; +- +- alg->cra_priority = 300; +- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; +- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); +- alg->cra_alignmask = 0; +- alg->cra_type = &crypto_ablkcipher_type; +- alg->cra_module = THIS_MODULE; +- alg->cra_init = qce_ablkcipher_init; +- alg->cra_exit = qce_ablkcipher_exit; +- +- INIT_LIST_HEAD(&tmpl->entry); +- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER; +- tmpl->alg_flags = def->flags; +- tmpl->qce = qce; +- +- ret = crypto_register_alg(alg); +- if (ret) { +- kfree(tmpl); +- dev_err(qce->dev, "%s registration failed\n", alg->cra_name); +- return ret; +- } +- +- list_add_tail(&tmpl->entry, &ablkcipher_algs); +- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name); +- return 0; +-} +- +-static void qce_ablkcipher_unregister(struct qce_device *qce) +-{ +- struct qce_alg_template *tmpl, *n; +- +- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) { +- crypto_unregister_alg(&tmpl->alg.crypto); +- list_del(&tmpl->entry); +- kfree(tmpl); +- } +-} +- +-static int qce_ablkcipher_register(struct qce_device *qce) +-{ +- int ret, i; +- +- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) { +- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce); +- if (ret) +- goto err; +- } +- +- return 0; +-err: +- qce_ablkcipher_unregister(qce); +- return ret; +-} +- +-const struct qce_algo_ops ablkcipher_ops = { +- .type = CRYPTO_ALG_TYPE_ABLKCIPHER, +- .register_algs = qce_ablkcipher_register, +- .unregister_algs = qce_ablkcipher_unregister, +- .async_req_handle = qce_ablkcipher_async_req_handle, +-}; +--- /dev/null ++++ b/drivers/crypto/qce/skcipher.c +@@ -0,0 +1,440 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cipher.h" ++ ++static LIST_HEAD(skcipher_algs); ++ ++static void qce_skcipher_done(void *data) ++{ ++ struct crypto_async_request *async_req = data; ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ enum dma_data_direction dir_src, dir_dst; ++ u32 status; ++ int error; ++ bool diff_dst; ++ ++ diff_dst = (req->src != req->dst) ? true : false; ++ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; ++ ++ error = qce_dma_terminate_all(&qce->dma); ++ if (error) ++ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", ++ error); ++ ++ if (diff_dst) ++ dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); ++ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); ++ ++ sg_free_table(&rctx->dst_tbl); ++ ++ error = qce_check_status(qce, &status); ++ if (error < 0) ++ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); ++ ++ qce->async_req_done(tmpl->qce, error); ++} ++ ++static int ++qce_skcipher_async_req_handle(struct crypto_async_request *async_req) ++{ ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ enum dma_data_direction dir_src, dir_dst; ++ struct scatterlist *sg; ++ bool diff_dst; ++ gfp_t gfp; ++ int ret; ++ ++ rctx->iv = req->iv; ++ rctx->ivsize = crypto_skcipher_ivsize(skcipher); ++ rctx->cryptlen = req->cryptlen; ++ ++ diff_dst = (req->src != req->dst) ? true : false; ++ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; ++ ++ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); ++ if (diff_dst) ++ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); ++ else ++ rctx->dst_nents = rctx->src_nents; ++ if (rctx->src_nents < 0) { ++ dev_err(qce->dev, "Invalid numbers of src SG.\n"); ++ return rctx->src_nents; ++ } ++ if (rctx->dst_nents < 0) { ++ dev_err(qce->dev, "Invalid numbers of dst SG.\n"); ++ return -rctx->dst_nents; ++ } ++ ++ rctx->dst_nents += 1; ++ ++ gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? ++ GFP_KERNEL : GFP_ATOMIC; ++ ++ ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); ++ if (ret) ++ return ret; ++ ++ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); ++ ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; ++ } ++ ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; ++ } ++ ++ sg_mark_end(sg); ++ rctx->dst_sg = rctx->dst_tbl.sgl; ++ ++ ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); ++ if (ret < 0) ++ goto error_free; ++ ++ if (diff_dst) { ++ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); ++ if (ret < 0) ++ goto error_unmap_dst; ++ rctx->src_sg = req->src; ++ } else { ++ rctx->src_sg = rctx->dst_sg; ++ } ++ ++ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, ++ rctx->dst_sg, rctx->dst_nents, ++ qce_skcipher_done, async_req); ++ if (ret) ++ goto error_unmap_src; ++ ++ qce_dma_issue_pending(&qce->dma); ++ ++ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); ++ if (ret) ++ goto error_terminate; ++ ++ return 0; ++ ++error_terminate: ++ qce_dma_terminate_all(&qce->dma); ++error_unmap_src: ++ if (diff_dst) ++ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); ++error_unmap_dst: ++ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); ++error_free: ++ sg_free_table(&rctx->dst_tbl); ++ return ret; ++} ++ ++static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++{ ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); ++ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ int ret; ++ ++ if (!key || !keylen) ++ return -EINVAL; ++ ++ switch (keylen) { ++ case AES_KEYSIZE_128: ++ case AES_KEYSIZE_256: ++ break; ++ default: ++ goto fallback; ++ } ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++ return 0; ++fallback: ++ ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); ++ if (!ret) ++ ctx->enc_keylen = keylen; ++ return ret; ++} ++ ++static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); ++ int err; ++ ++ err = verify_skcipher_des_key(ablk, key); ++ if (err) ++ return err; ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++ return 0; ++} ++ ++static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); ++ int err; ++ ++ err = verify_skcipher_des3_key(ablk, key); ++ if (err) ++ return err; ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++ return 0; ++} ++ ++static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); ++ int ret; ++ ++ rctx->flags = tmpl->alg_flags; ++ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ ++ if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && ++ ctx->enc_keylen != AES_KEYSIZE_256) { ++ SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); ++ ++ skcipher_request_set_sync_tfm(subreq, ctx->fallback); ++ skcipher_request_set_callback(subreq, req->base.flags, ++ NULL, NULL); ++ skcipher_request_set_crypt(subreq, req->src, req->dst, ++ req->cryptlen, req->iv); ++ ret = encrypt ? crypto_skcipher_encrypt(subreq) : ++ crypto_skcipher_decrypt(subreq); ++ skcipher_request_zero(subreq); ++ return ret; ++ } ++ ++ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); ++} ++ ++static int qce_skcipher_encrypt(struct skcipher_request *req) ++{ ++ return qce_skcipher_crypt(req, 1); ++} ++ ++static int qce_skcipher_decrypt(struct skcipher_request *req) ++{ ++ return qce_skcipher_crypt(req, 0); ++} ++ ++static int qce_skcipher_init(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); ++ ++ ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), ++ 0, CRYPTO_ALG_NEED_FALLBACK); ++ return PTR_ERR_OR_ZERO(ctx->fallback); ++} ++ ++static void qce_skcipher_exit(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ crypto_free_sync_skcipher(ctx->fallback); ++} ++ ++struct qce_skcipher_def { ++ unsigned long flags; ++ const char *name; ++ const char *drv_name; ++ unsigned int blocksize; ++ unsigned int ivsize; ++ unsigned int min_keysize; ++ unsigned int max_keysize; ++}; ++ ++static const struct qce_skcipher_def skcipher_def[] = { ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_ECB, ++ .name = "ecb(aes)", ++ .drv_name = "ecb-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_CBC, ++ .name = "cbc(aes)", ++ .drv_name = "cbc-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_CTR, ++ .name = "ctr(aes)", ++ .drv_name = "ctr-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_XTS, ++ .name = "xts(aes)", ++ .drv_name = "xts-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_DES | QCE_MODE_ECB, ++ .name = "ecb(des)", ++ .drv_name = "ecb-des-qce", ++ .blocksize = DES_BLOCK_SIZE, ++ .ivsize = 0, ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_DES | QCE_MODE_CBC, ++ .name = "cbc(des)", ++ .drv_name = "cbc-des-qce", ++ .blocksize = DES_BLOCK_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_3DES | QCE_MODE_ECB, ++ .name = "ecb(des3_ede)", ++ .drv_name = "ecb-3des-qce", ++ .blocksize = DES3_EDE_BLOCK_SIZE, ++ .ivsize = 0, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_3DES | QCE_MODE_CBC, ++ .name = "cbc(des3_ede)", ++ .drv_name = "cbc-3des-qce", ++ .blocksize = DES3_EDE_BLOCK_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ }, ++}; ++ ++static int qce_skcipher_register_one(const struct qce_skcipher_def *def, ++ struct qce_device *qce) ++{ ++ struct qce_alg_template *tmpl; ++ struct skcipher_alg *alg; ++ int ret; ++ ++ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); ++ if (!tmpl) ++ return -ENOMEM; ++ ++ alg = &tmpl->alg.skcipher; ++ ++ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); ++ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", ++ def->drv_name); ++ ++ alg->base.cra_blocksize = def->blocksize; ++ alg->ivsize = def->ivsize; ++ alg->min_keysize = def->min_keysize; ++ alg->max_keysize = def->max_keysize; ++ alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : ++ IS_DES(def->flags) ? qce_des_setkey : ++ qce_skcipher_setkey; ++ alg->encrypt = qce_skcipher_encrypt; ++ alg->decrypt = qce_skcipher_decrypt; ++ ++ alg->base.cra_priority = 300; ++ alg->base.cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY; ++ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); ++ alg->base.cra_alignmask = 0; ++ alg->base.cra_module = THIS_MODULE; ++ ++ alg->init = qce_skcipher_init; ++ alg->exit = qce_skcipher_exit; ++ ++ INIT_LIST_HEAD(&tmpl->entry); ++ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; ++ tmpl->alg_flags = def->flags; ++ tmpl->qce = qce; ++ ++ ret = crypto_register_skcipher(alg); ++ if (ret) { ++ kfree(tmpl); ++ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); ++ return ret; ++ } ++ ++ list_add_tail(&tmpl->entry, &skcipher_algs); ++ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); ++ return 0; ++} ++ ++static void qce_skcipher_unregister(struct qce_device *qce) ++{ ++ struct qce_alg_template *tmpl, *n; ++ ++ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { ++ crypto_unregister_skcipher(&tmpl->alg.skcipher); ++ list_del(&tmpl->entry); ++ kfree(tmpl); ++ } ++} ++ ++static int qce_skcipher_register(struct qce_device *qce) ++{ ++ int ret, i; ++ ++ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { ++ ret = qce_skcipher_register_one(&skcipher_def[i], qce); ++ if (ret) ++ goto err; ++ } ++ ++ return 0; ++err: ++ qce_skcipher_unregister(qce); ++ return ret; ++} ++ ++const struct qce_algo_ops skcipher_ops = { ++ .type = CRYPTO_ALG_TYPE_SKCIPHER, ++ .register_algs = qce_skcipher_register, ++ .unregister_algs = qce_skcipher_unregister, ++ .async_req_handle = qce_skcipher_async_req_handle, ++}; diff --git a/target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch b/target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch new file mode 100644 index 0000000000..ac4f163f4a --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch @@ -0,0 +1,43 @@ +From bb5c863b3d3cbd10e80b2ebf409934a091058f54 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:13 -0300 +Subject: [PATCH 02/11] crypto: qce - fix ctr-aes-qce block, chunk sizes + +Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher, +adding the definition for chucksize instead, where the underlying block +size belongs. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -270,6 +270,7 @@ struct qce_skcipher_def { + const char *name; + const char *drv_name; + unsigned int blocksize; ++ unsigned int chunksize; + unsigned int ivsize; + unsigned int min_keysize; + unsigned int max_keysize; +@@ -298,7 +299,8 @@ static const struct qce_skcipher_def skc + .flags = QCE_ALG_AES | QCE_MODE_CTR, + .name = "ctr(aes)", + .drv_name = "ctr-aes-qce", +- .blocksize = AES_BLOCK_SIZE, ++ .blocksize = 1, ++ .chunksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, +@@ -368,6 +370,7 @@ static int qce_skcipher_register_one(con + def->drv_name); + + alg->base.cra_blocksize = def->blocksize; ++ alg->chunksize = def->chunksize; + alg->ivsize = def->ivsize; + alg->min_keysize = def->min_keysize; + alg->max_keysize = def->max_keysize; diff --git a/target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch b/target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch new file mode 100644 index 0000000000..4dcf1ac726 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch @@ -0,0 +1,60 @@ +From 7de4c2bd196f111e39cc60f6197654aff23ba2b4 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:14 -0300 +Subject: [PATCH 03/11] crypto: qce - fix xts-aes-qce key sizes + +XTS-mode uses two keys, so the keysizes should be doubled in +skcipher_def, and halved when checking if it is AES-128/192/256. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -154,12 +154,13 @@ static int qce_skcipher_setkey(struct cr + { + struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); + struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; + int ret; + + if (!key || !keylen) + return -EINVAL; + +- switch (keylen) { ++ switch (IS_XTS(flags) ? keylen >> 1 : keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_256: + break; +@@ -213,13 +214,15 @@ static int qce_skcipher_crypt(struct skc + struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); ++ int keylen; + int ret; + + rctx->flags = tmpl->alg_flags; + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + +- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && +- ctx->enc_keylen != AES_KEYSIZE_256) { ++ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && ++ keylen != AES_KEYSIZE_256) { + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_sync_tfm(subreq, ctx->fallback); +@@ -311,8 +314,8 @@ static const struct qce_skcipher_def skc + .drv_name = "xts-aes-qce", + .blocksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE * 2, ++ .max_keysize = AES_MAX_KEY_SIZE * 2, + }, + { + .flags = QCE_ALG_DES | QCE_MODE_ECB, diff --git a/target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch b/target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch new file mode 100644 index 0000000000..2385d483f2 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch @@ -0,0 +1,85 @@ +From 3ee50c896d712dc2fc8f34c2cd1918d035e74045 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:15 -0300 +Subject: [PATCH 04/11] crypto: qce - save a sg table slot for result buf + +When ctr-aes-qce is used for gcm-mode, an extra sg entry for the +authentication tag is present, causing trouble when the qce driver +prepares the dst-results sg table for dma. + +It computes the number of entries needed with sg_nents_for_len, leaving +out the tag entry. Then it creates a sg table with that number plus +one, used to store a result buffer. + +When copying the sg table, there's no limit to the number of entries +copied, so the extra slot is filled with the authentication tag sg. +When the driver tries to add the result sg, the list is full, and it +returns EINVAL. + +By limiting the number of sg entries copied to the dest table, the slot +for the result buffer is guaranteed to be unused. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/dma.c | 6 ++++-- + drivers/crypto/qce/dma.h | 3 ++- + drivers/crypto/qce/skcipher.c | 4 ++-- + 3 files changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/crypto/qce/dma.c ++++ b/drivers/crypto/qce/dma.c +@@ -47,7 +47,8 @@ void qce_dma_release(struct qce_dma_data + } + + struct scatterlist * +-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) ++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, ++ int max_ents) + { + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; + +@@ -60,12 +61,13 @@ qce_sgtable_add(struct sg_table *sgt, st + if (!sg) + return ERR_PTR(-EINVAL); + +- while (new_sgl && sg) { ++ while (new_sgl && sg && max_ents) { + sg_set_page(sg, sg_page(new_sgl), new_sgl->length, + new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); ++ max_ents--; + } + + return sg_last; +--- a/drivers/crypto/qce/dma.h ++++ b/drivers/crypto/qce/dma.h +@@ -42,6 +42,7 @@ int qce_dma_prep_sgs(struct qce_dma_data + void qce_dma_issue_pending(struct qce_dma_data *dma); + int qce_dma_terminate_all(struct qce_dma_data *dma); + struct scatterlist * +-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add); ++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, ++ int max_ents); + + #endif /* _DMA_H_ */ +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -95,13 +95,13 @@ qce_skcipher_async_req_handle(struct cry + + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); + +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; + } + +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; diff --git a/target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch b/target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch new file mode 100644 index 0000000000..5efdb72c44 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch @@ -0,0 +1,31 @@ +From 3e806a12d10af2581aa26c37b58439286eab9782 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:16 -0300 +Subject: [PATCH 05/11] crypto: qce - update the skcipher IV + +Update the IV after the completion of each cipher operation. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -21,6 +21,7 @@ static void qce_skcipher_done(void *data + struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; ++ struct qce_result_dump *result_buf = qce->dma.result_buf; + enum dma_data_direction dir_src, dir_dst; + u32 status; + int error; +@@ -45,6 +46,7 @@ static void qce_skcipher_done(void *data + if (error < 0) + dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); + ++ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + qce->async_req_done(tmpl->qce, error); + } + diff --git a/target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch b/target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch new file mode 100644 index 0000000000..84aef04ef4 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch @@ -0,0 +1,54 @@ +From 8ceda883205db6dfedb82e39f67feae3b50c95a1 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:17 -0300 +Subject: [PATCH 06/11] crypto: qce - initialize fallback only for AES + +Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where +AES-192 is not handled by the qce hardware, and don't allocate & free +the fallback skcipher for other algorithms. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -257,7 +257,14 @@ static int qce_skcipher_init(struct cryp + + memset(ctx, 0, sizeof(*ctx)); + crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); ++ return 0; ++} ++ ++static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + ++ qce_skcipher_init(tfm); + ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), + 0, CRYPTO_ALG_NEED_FALLBACK); + return PTR_ERR_OR_ZERO(ctx->fallback); +@@ -387,14 +394,18 @@ static int qce_skcipher_register_one(con + + alg->base.cra_priority = 300; + alg->base.cra_flags = CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK | + CRYPTO_ALG_KERN_DRIVER_ONLY; + alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); + alg->base.cra_alignmask = 0; + alg->base.cra_module = THIS_MODULE; + +- alg->init = qce_skcipher_init; +- alg->exit = qce_skcipher_exit; ++ if (IS_AES(def->flags)) { ++ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; ++ alg->init = qce_skcipher_init_fallback; ++ alg->exit = qce_skcipher_exit; ++ } else { ++ alg->init = qce_skcipher_init; ++ } + + INIT_LIST_HEAD(&tmpl->entry); + tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; diff --git a/target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch b/target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch new file mode 100644 index 0000000000..5b1372d08f --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch @@ -0,0 +1,419 @@ +From 59e056cda4beb5412e3653e6360c2eb0fa770baa Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:18 -0300 +Subject: [PATCH 07/11] crypto: qce - allow building only hashes/ciphers + +Allow the user to choose whether to build support for all algorithms +(default), hashes-only, or skciphers-only. + +The QCE engine does not appear to scale as well as the CPU to handle +multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the +QCE handles only 2 requests in parallel. + +Ipsec throughput seems to improve when disabling either family of +algorithms, sharing the load with the CPU. Enabling skciphers-only +appears to work best. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -617,6 +617,14 @@ config CRYPTO_DEV_QCE + tristate "Qualcomm crypto engine accelerator" + depends on ARCH_QCOM || COMPILE_TEST + depends on HAS_IOMEM ++ help ++ This driver supports Qualcomm crypto engine accelerator ++ hardware. To compile this driver as a module, choose M here. The ++ module will be called qcrypto. ++ ++config CRYPTO_DEV_QCE_SKCIPHER ++ bool ++ depends on CRYPTO_DEV_QCE + select CRYPTO_AES + select CRYPTO_LIB_DES + select CRYPTO_ECB +@@ -624,10 +632,57 @@ config CRYPTO_DEV_QCE + select CRYPTO_XTS + select CRYPTO_CTR + select CRYPTO_BLKCIPHER ++ ++config CRYPTO_DEV_QCE_SHA ++ bool ++ depends on CRYPTO_DEV_QCE ++ ++choice ++ prompt "Algorithms enabled for QCE acceleration" ++ default CRYPTO_DEV_QCE_ENABLE_ALL ++ depends on CRYPTO_DEV_QCE + help +- This driver supports Qualcomm crypto engine accelerator +- hardware. To compile this driver as a module, choose M here. The +- module will be called qcrypto. ++ This option allows to choose whether to build support for all algorihtms ++ (default), hashes-only, or skciphers-only. ++ ++ The QCE engine does not appear to scale as well as the CPU to handle ++ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the ++ QCE handles only 2 requests in parallel. ++ ++ Ipsec throughput seems to improve when disabling either family of ++ algorithms, sharing the load with the CPU. Enabling skciphers-only ++ appears to work best. ++ ++ config CRYPTO_DEV_QCE_ENABLE_ALL ++ bool "All supported algorithms" ++ select CRYPTO_DEV_QCE_SKCIPHER ++ select CRYPTO_DEV_QCE_SHA ++ help ++ Enable all supported algorithms: ++ - AES (CBC, CTR, ECB, XTS) ++ - 3DES (CBC, ECB) ++ - DES (CBC, ECB) ++ - SHA1, HMAC-SHA1 ++ - SHA256, HMAC-SHA256 ++ ++ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER ++ bool "Symmetric-key ciphers only" ++ select CRYPTO_DEV_QCE_SKCIPHER ++ help ++ Enable symmetric-key ciphers only: ++ - AES (CBC, CTR, ECB, XTS) ++ - 3DES (ECB, CBC) ++ - DES (ECB, CBC) ++ ++ config CRYPTO_DEV_QCE_ENABLE_SHA ++ bool "Hash/HMAC only" ++ select CRYPTO_DEV_QCE_SHA ++ help ++ Enable hashes/HMAC algorithms only: ++ - SHA1, HMAC-SHA1 ++ - SHA256, HMAC-SHA256 ++ ++endchoice + + config CRYPTO_DEV_QCOM_RNG + tristate "Qualcomm Random Number Generator Driver" +--- a/drivers/crypto/qce/Makefile ++++ b/drivers/crypto/qce/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o + qcrypto-objs := core.o \ + common.o \ +- dma.o \ +- sha.o \ +- skcipher.o ++ dma.o ++ ++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o ++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -45,52 +45,56 @@ qce_clear_array(struct qce_device *qce, + qce_write(qce, offset + i * sizeof(u32), 0); + } + +-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) ++static u32 qce_config_reg(struct qce_device *qce, int little) + { +- u32 cfg = 0; ++ u32 beats = (qce->burst_size >> 3) - 1; ++ u32 pipe_pair = qce->pipe_pair_id; ++ u32 config; + +- if (IS_AES(flags)) { +- if (aes_key_size == AES_KEYSIZE_128) +- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; +- else if (aes_key_size == AES_KEYSIZE_256) +- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; +- } ++ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; ++ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | ++ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); ++ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; ++ config &= ~HIGH_SPD_EN_N_SHIFT; + +- if (IS_AES(flags)) +- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; +- else if (IS_DES(flags) || IS_3DES(flags)) +- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; ++ if (little) ++ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); + +- if (IS_DES(flags)) +- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; ++ return config; ++} + +- if (IS_3DES(flags)) +- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; ++void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) ++{ ++ __be32 *d = dst; ++ const u8 *s = src; ++ unsigned int n; + +- switch (flags & QCE_MODE_MASK) { +- case QCE_MODE_ECB: +- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CBC: +- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CTR: +- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_XTS: +- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CCM: +- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; +- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; +- break; +- default: +- return ~0; ++ n = len / sizeof(u32); ++ for (; n > 0; n--) { ++ *d = cpu_to_be32p((const __u32 *) s); ++ s += sizeof(__u32); ++ d++; + } ++} + +- return cfg; ++static void qce_setup_config(struct qce_device *qce) ++{ ++ u32 config; ++ ++ /* get big endianness */ ++ config = qce_config_reg(qce, 0); ++ ++ /* clear status */ ++ qce_write(qce, REG_STATUS, 0); ++ qce_write(qce, REG_CONFIG, config); ++} ++ ++static inline void qce_crypto_go(struct qce_device *qce) ++{ ++ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); + } + ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + static u32 qce_auth_cfg(unsigned long flags, u32 key_size) + { + u32 cfg = 0; +@@ -137,88 +141,6 @@ static u32 qce_auth_cfg(unsigned long fl + return cfg; + } + +-static u32 qce_config_reg(struct qce_device *qce, int little) +-{ +- u32 beats = (qce->burst_size >> 3) - 1; +- u32 pipe_pair = qce->pipe_pair_id; +- u32 config; +- +- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; +- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | +- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); +- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; +- config &= ~HIGH_SPD_EN_N_SHIFT; +- +- if (little) +- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); +- +- return config; +-} +- +-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) +-{ +- __be32 *d = dst; +- const u8 *s = src; +- unsigned int n; +- +- n = len / sizeof(u32); +- for (; n > 0; n--) { +- *d = cpu_to_be32p((const __u32 *) s); +- s += sizeof(__u32); +- d++; +- } +-} +- +-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) +-{ +- u8 swap[QCE_AES_IV_LENGTH]; +- u32 i, j; +- +- if (ivsize > QCE_AES_IV_LENGTH) +- return; +- +- memset(swap, 0, QCE_AES_IV_LENGTH); +- +- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; +- i < QCE_AES_IV_LENGTH; i++, j--) +- swap[i] = src[j]; +- +- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); +-} +- +-static void qce_xtskey(struct qce_device *qce, const u8 *enckey, +- unsigned int enckeylen, unsigned int cryptlen) +-{ +- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; +- unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); +- unsigned int xtsdusize; +- +- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, +- enckeylen / 2); +- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); +- +- /* xts du size 512B */ +- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); +- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); +-} +- +-static void qce_setup_config(struct qce_device *qce) +-{ +- u32 config; +- +- /* get big endianness */ +- config = qce_config_reg(qce, 0); +- +- /* clear status */ +- qce_write(qce, REG_STATUS, 0); +- qce_write(qce, REG_CONFIG, config); +-} +- +-static inline void qce_crypto_go(struct qce_device *qce) +-{ +- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); +-} +- + static int qce_setup_regs_ahash(struct crypto_async_request *async_req, + u32 totallen, u32 offset) + { +@@ -303,6 +225,87 @@ go_proc: + + return 0; + } ++#endif ++ ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER ++static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) ++{ ++ u32 cfg = 0; ++ ++ if (IS_AES(flags)) { ++ if (aes_key_size == AES_KEYSIZE_128) ++ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; ++ else if (aes_key_size == AES_KEYSIZE_256) ++ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; ++ } ++ ++ if (IS_AES(flags)) ++ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; ++ else if (IS_DES(flags) || IS_3DES(flags)) ++ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; ++ ++ if (IS_DES(flags)) ++ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; ++ ++ if (IS_3DES(flags)) ++ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; ++ ++ switch (flags & QCE_MODE_MASK) { ++ case QCE_MODE_ECB: ++ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CBC: ++ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CTR: ++ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_XTS: ++ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CCM: ++ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; ++ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; ++ break; ++ default: ++ return ~0; ++ } ++ ++ return cfg; ++} ++ ++static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) ++{ ++ u8 swap[QCE_AES_IV_LENGTH]; ++ u32 i, j; ++ ++ if (ivsize > QCE_AES_IV_LENGTH) ++ return; ++ ++ memset(swap, 0, QCE_AES_IV_LENGTH); ++ ++ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; ++ i < QCE_AES_IV_LENGTH; i++, j--) ++ swap[i] = src[j]; ++ ++ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); ++} ++ ++static void qce_xtskey(struct qce_device *qce, const u8 *enckey, ++ unsigned int enckeylen, unsigned int cryptlen) ++{ ++ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; ++ unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); ++ unsigned int xtsdusize; ++ ++ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, ++ enckeylen / 2); ++ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); ++ ++ /* xts du size 512B */ ++ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); ++ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); ++} + + static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + u32 totallen, u32 offset) +@@ -384,15 +387,20 @@ static int qce_setup_regs_skcipher(struc + + return 0; + } ++#endif + + int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, + u32 offset) + { + switch (type) { ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER + case CRYPTO_ALG_TYPE_SKCIPHER: + return qce_setup_regs_skcipher(async_req, totallen, offset); ++#endif ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + case CRYPTO_ALG_TYPE_AHASH: + return qce_setup_regs_ahash(async_req, totallen, offset); ++#endif + default: + return -EINVAL; + } +--- a/drivers/crypto/qce/core.c ++++ b/drivers/crypto/qce/core.c +@@ -22,8 +22,12 @@ + #define QCE_QUEUE_LENGTH 1 + + static const struct qce_algo_ops *qce_ops[] = { ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER + &skcipher_ops, ++#endif ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + &ahash_ops, ++#endif + }; + + static void qce_unregister_algs(struct qce_device *qce) diff --git a/target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch b/target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch new file mode 100644 index 0000000000..160420b485 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch @@ -0,0 +1,89 @@ +From d6364b8128439a8c0e381f80c38667de9f15eef8 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 7 Feb 2020 12:02:25 -0300 +Subject: [PATCH 09/11] crypto: qce - use cryptlen when adding extra sgl + +The qce crypto driver appends an extra entry to the dst sgl, to maintain +private state information. + +When the gcm driver sends requests to the ctr skcipher, it passes the +authentication tag after the actual crypto payload, but it must not be +touched. + +Commit 1336c2221bee ("crypto: qce - save a sg table slot for result +buf") limited the destination sgl to avoid overwriting the +authentication tag but it assumed the tag would be in a separate sgl +entry. + +This is not always the case, so it is better to limit the length of the +destination buffer to req->cryptlen before appending the result buf. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/dma.c | 11 ++++++----- + drivers/crypto/qce/dma.h | 2 +- + drivers/crypto/qce/skcipher.c | 5 +++-- + 3 files changed, 10 insertions(+), 8 deletions(-) + +--- a/drivers/crypto/qce/dma.c ++++ b/drivers/crypto/qce/dma.c +@@ -48,9 +48,10 @@ void qce_dma_release(struct qce_dma_data + + struct scatterlist * + qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, +- int max_ents) ++ unsigned int max_len) + { + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; ++ unsigned int new_len; + + while (sg) { + if (!sg_page(sg)) +@@ -61,13 +62,13 @@ qce_sgtable_add(struct sg_table *sgt, st + if (!sg) + return ERR_PTR(-EINVAL); + +- while (new_sgl && sg && max_ents) { +- sg_set_page(sg, sg_page(new_sgl), new_sgl->length, +- new_sgl->offset); ++ while (new_sgl && sg && max_len) { ++ new_len = new_sgl->length > max_len ? max_len : new_sgl->length; ++ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); +- max_ents--; ++ max_len -= new_len; + } + + return sg_last; +--- a/drivers/crypto/qce/dma.h ++++ b/drivers/crypto/qce/dma.h +@@ -43,6 +43,6 @@ void qce_dma_issue_pending(struct qce_dm + int qce_dma_terminate_all(struct qce_dma_data *dma); + struct scatterlist * + qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, +- int max_ents); ++ unsigned int max_len); + + #endif /* _DMA_H_ */ +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -97,13 +97,14 @@ qce_skcipher_async_req_handle(struct cry + + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); + +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; + } + +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, ++ QCE_RESULT_BUF_SZ); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; diff --git a/target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch b/target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch new file mode 100644 index 0000000000..0b5c8c6d66 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch @@ -0,0 +1,113 @@ +From ce163ba0bf298f1707321ac025ef639f88e62801 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 7 Feb 2020 12:02:26 -0300 +Subject: [PATCH 10/11] crypto: qce - use AES fallback for small requests + +Process small blocks using the fallback cipher, as a workaround for an +observed failure (DMA-related, apparently) when computing the GCM ghash +key. This brings a speed gain as well, since it avoids the latency of +using the hardware engine to process small blocks. + +Using software for all 16-byte requests would be enough to make GCM +work, but to increase performance, a larger threshold would be better. +Measuring the performance of supported ciphers with openssl speed, +software matches hardware at around 768-1024 bytes. + +Considering the 256-bit ciphers, software is 2-3 times faster than qce +at 256-bytes, 30% faster at 512, and about even at 768-bytes. With +128-bit keys, the break-even point would be around 1024-bytes. + +This adds the 'aes_sw_max_len' parameter, to set the largest request +length processed by the software fallback. Its default is being set to +512 bytes, a little lower than the break-even point, to balance the cost +in CPU usage. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -684,6 +684,29 @@ choice + + endchoice + ++config CRYPTO_DEV_QCE_SW_MAX_LEN ++ int "Default maximum request size to use software for AES" ++ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER ++ default 512 ++ help ++ This sets the default maximum request size to perform AES requests ++ using software instead of the crypto engine. It can be changed by ++ setting the aes_sw_max_len parameter. ++ ++ Small blocks are processed faster in software than hardware. ++ Considering the 256-bit ciphers, software is 2-3 times faster than ++ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes. ++ With 128-bit keys, the break-even point would be around 1024-bytes. ++ ++ The default is set a little lower, to 512 bytes, to balance the ++ cost in CPU usage. The minimum recommended setting is 16-bytes ++ (1 AES block), since AES-GCM will fail if you set it lower. ++ Setting this to zero will send all requests to the hardware. ++ ++ Note that 192-bit keys are not supported by the hardware and are ++ always processed by the software fallback, and all DES requests ++ are done by the hardware. ++ + config CRYPTO_DEV_QCOM_RNG + tristate "Qualcomm Random Number Generator Driver" + depends on ARCH_QCOM || COMPILE_TEST +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -12,6 +13,13 @@ + + #include "cipher.h" + ++static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; ++module_param(aes_sw_max_len, uint, 0644); ++MODULE_PARM_DESC(aes_sw_max_len, ++ "Only use hardware for AES requests larger than this " ++ "[0=always use hardware; anything <16 breaks AES-GCM; default=" ++ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]"); ++ + static LIST_HEAD(skcipher_algs); + + static void qce_skcipher_done(void *data) +@@ -166,15 +174,10 @@ static int qce_skcipher_setkey(struct cr + switch (IS_XTS(flags) ? keylen >> 1 : keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_256: ++ memcpy(ctx->enc_key, key, keylen); + break; +- default: +- goto fallback; + } + +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-fallback: + ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); + if (!ret) + ctx->enc_keylen = keylen; +@@ -224,8 +227,9 @@ static int qce_skcipher_crypt(struct skc + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; + keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + +- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && +- keylen != AES_KEYSIZE_256) { ++ if (IS_AES(rctx->flags) && ++ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++ req->cryptlen <= aes_sw_max_len)) { + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_sync_tfm(subreq, ctx->fallback); diff --git a/target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch b/target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch new file mode 100644 index 0000000000..18beda6296 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch @@ -0,0 +1,59 @@ +From 7f19380b2cfd412dcef2facefb3f6c62788864d7 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 7 Feb 2020 12:02:27 -0300 +Subject: [PATCH 11/11] crypto: qce - handle AES-XTS cases that qce fails + +QCE hangs when presented with an AES-XTS request whose length is larger +than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the +fallback cipher handle them. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/common.c | 2 -- + drivers/crypto/qce/common.h | 3 +++ + drivers/crypto/qce/skcipher.c | 9 +++++++-- + 3 files changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -15,8 +15,6 @@ + #include "regs-v5.h" + #include "sha.h" + +-#define QCE_SECTOR_SIZE 512 +- + static inline u32 qce_read(struct qce_device *qce, u32 offset) + { + return readl(qce->base + offset); +--- a/drivers/crypto/qce/common.h ++++ b/drivers/crypto/qce/common.h +@@ -12,6 +12,9 @@ + #include + #include + ++/* xts du size */ ++#define QCE_SECTOR_SIZE 512 ++ + /* key size in bytes */ + #define QCE_SHA_HMAC_KEY_SIZE 64 + #define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -227,9 +227,14 @@ static int qce_skcipher_crypt(struct skc + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; + keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + ++ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and ++ * is not a multiple of it; pass such requests to the fallback ++ */ + if (IS_AES(rctx->flags) && +- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || +- req->cryptlen <= aes_sw_max_len)) { ++ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++ req->cryptlen <= aes_sw_max_len) || ++ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && ++ req->cryptlen % QCE_SECTOR_SIZE))) { + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_sync_tfm(subreq, ctx->fallback); diff --git a/target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch b/target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch new file mode 100644 index 0000000000..ad09a9f250 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch @@ -0,0 +1,197 @@ +From 3c9d8f6c03a2cda1849ec3c84f82ec030d1f49ef Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 3 May 2020 22:18:22 +0200 +Subject: [PATCH] phy: add driver for Qualcomm IPQ40xx USB PHY + +Add a driver to setup the USB PHY-s on Qualcom m IPQ40xx series SoCs. +The driver sets up HS and SS phys. + +Signed-off-by: John Crispin +Signed-off-by: Robert Marko +Cc: Luka Perkov +Link: https://lore.kernel.org/r/20200503201823.531757-1-robert.marko@sartura.hr +Signed-off-by: Vinod Koul +--- + drivers/phy/qualcomm/Kconfig | 7 + + drivers/phy/qualcomm/Makefile | 1 + + drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c | 148 ++++++++++++++++++++ + 3 files changed, 156 insertions(+) + create mode 100644 drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c + +--- a/drivers/phy/qualcomm/Kconfig ++++ b/drivers/phy/qualcomm/Kconfig +@@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA + depends on OF + select GENERIC_PHY + ++config PHY_QCOM_IPQ4019_USB ++ tristate "Qualcomm IPQ4019 USB PHY driver" ++ depends on OF && (ARCH_QCOM || COMPILE_TEST) ++ select GENERIC_PHY ++ help ++ Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. ++ + config PHY_QCOM_IPQ806X_SATA + tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" + depends on ARCH_QCOM +--- a/drivers/phy/qualcomm/Makefile ++++ b/drivers/phy/qualcomm/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o + obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o ++obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o + obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o + obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c +@@ -0,0 +1,148 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) 2018 John Crispin ++ * ++ * Based on code from ++ * Allwinner Technology Co., Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ipq4019_usb_phy { ++ struct device *dev; ++ struct phy *phy; ++ void __iomem *base; ++ struct reset_control *por_rst; ++ struct reset_control *srif_rst; ++}; ++ ++static int ipq4019_ss_phy_power_off(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ reset_control_assert(phy->por_rst); ++ msleep(10); ++ ++ return 0; ++} ++ ++static int ipq4019_ss_phy_power_on(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ ipq4019_ss_phy_power_off(_phy); ++ ++ reset_control_deassert(phy->por_rst); ++ ++ return 0; ++} ++ ++static struct phy_ops ipq4019_usb_ss_phy_ops = { ++ .power_on = ipq4019_ss_phy_power_on, ++ .power_off = ipq4019_ss_phy_power_off, ++}; ++ ++static int ipq4019_hs_phy_power_off(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ reset_control_assert(phy->por_rst); ++ msleep(10); ++ ++ reset_control_assert(phy->srif_rst); ++ msleep(10); ++ ++ return 0; ++} ++ ++static int ipq4019_hs_phy_power_on(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ ipq4019_hs_phy_power_off(_phy); ++ ++ reset_control_deassert(phy->srif_rst); ++ msleep(10); ++ ++ reset_control_deassert(phy->por_rst); ++ ++ return 0; ++} ++ ++static struct phy_ops ipq4019_usb_hs_phy_ops = { ++ .power_on = ipq4019_hs_phy_power_on, ++ .power_off = ipq4019_hs_phy_power_off, ++}; ++ ++static const struct of_device_id ipq4019_usb_phy_of_match[] = { ++ { .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops}, ++ { .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match); ++ ++static int ipq4019_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ struct phy_provider *phy_provider; ++ struct ipq4019_usb_phy *phy; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ phy->dev = &pdev->dev; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ phy->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(phy->base)) { ++ dev_err(dev, "failed to remap register memory\n"); ++ return PTR_ERR(phy->base); ++ } ++ ++ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst"); ++ if (IS_ERR(phy->por_rst)) { ++ if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER) ++ dev_err(dev, "POR reset is missing\n"); ++ return PTR_ERR(phy->por_rst); ++ } ++ ++ phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst"); ++ if (IS_ERR(phy->srif_rst)) ++ return PTR_ERR(phy->srif_rst); ++ ++ phy->phy = devm_phy_create(dev, NULL, of_device_get_match_data(dev)); ++ if (IS_ERR(phy->phy)) { ++ dev_err(dev, "failed to create PHY\n"); ++ return PTR_ERR(phy->phy); ++ } ++ phy_set_drvdata(phy->phy, phy); ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static struct platform_driver ipq4019_usb_phy_driver = { ++ .probe = ipq4019_usb_phy_probe, ++ .driver = { ++ .of_match_table = ipq4019_usb_phy_of_match, ++ .name = "ipq4019-usb-phy", ++ } ++}; ++module_platform_driver(ipq4019_usb_phy_driver); ++ ++MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch b/target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch new file mode 100644 index 0000000000..5cd4ccc30f --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch @@ -0,0 +1,81 @@ +From 5b08c1d567ee8e6af94696b3e549997cbdb2bb80 Mon Sep 17 00:00:00 2001 +From: Jaiganesh Narayanan +Date: Thu, 1 Sep 2016 10:40:38 +0530 +Subject: [PATCH] pinctrl: qcom: ipq4019: add open drain support + +Signed-off-by: Jaiganesh Narayanan +[ Brian: adapted from from the Chromium OS kernel used on IPQ4019-based + WiFi APs. ] +Signed-off-by: Brian Norris +--- +https://lore.kernel.org/linux-gpio/20200703080646.23233-1-computersforpeace@gmail.com/ + + drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1 + + drivers/pinctrl/qcom/pinctrl-msm.c | 13 +++++++++++++ + drivers/pinctrl/qcom/pinctrl-msm.h | 2 ++ + 3 files changed, 16 insertions(+) + +--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c ++++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c +@@ -254,6 +254,7 @@ DECLARE_QCA_GPIO_PINS(99); + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ ++ .od_bit = 12, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ +--- a/drivers/pinctrl/qcom/pinctrl-msm.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm.c +@@ -225,6 +225,10 @@ static int msm_config_reg(struct msm_pin + *bit = g->pull_bit; + *mask = 3; + break; ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ *bit = g->od_bit; ++ *mask = 1; ++ break; + case PIN_CONFIG_DRIVE_STRENGTH: + *bit = g->drv_bit; + *mask = 7; +@@ -302,6 +306,12 @@ static int msm_config_group_get(struct p + if (!arg) + return -EINVAL; + break; ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ /* Pin is not open-drain */ ++ if (!arg) ++ return -EINVAL; ++ arg = 1; ++ break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = msm_regval_to_drive(arg); + break; +@@ -374,6 +384,9 @@ static int msm_config_group_set(struct p + else + arg = MSM_PULL_UP; + break; ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ arg = 1; ++ break; + case PIN_CONFIG_DRIVE_STRENGTH: + /* Check for invalid values */ + if (arg > 16 || arg < 2 || (arg % 2) != 0) +--- a/drivers/pinctrl/qcom/pinctrl-msm.h ++++ b/drivers/pinctrl/qcom/pinctrl-msm.h +@@ -38,6 +38,7 @@ struct msm_function { + * @mux_bit: Offset in @ctl_reg for the pinmux function selection. + * @pull_bit: Offset in @ctl_reg for the bias configuration. + * @drv_bit: Offset in @ctl_reg for the drive strength configuration. ++ * @od_bit: Offset in @ctl_reg for controlling open drain. + * @oe_bit: Offset in @ctl_reg for controlling output enable. + * @in_bit: Offset in @io_reg for the input bit value. + * @out_bit: Offset in @io_reg for the output bit value. +@@ -75,6 +76,7 @@ struct msm_pingroup { + unsigned pull_bit:5; + unsigned drv_bit:5; + ++ unsigned od_bit:5; + unsigned oe_bit:5; + unsigned in_bit:5; + unsigned out_bit:5; diff --git a/target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch b/target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch new file mode 100644 index 0000000000..f1be01c8e1 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch @@ -0,0 +1,29 @@ +From 707745e8d4e75b638b990d67950ab292b3b8ea2a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 16 Dec 2019 01:36:46 +0100 +Subject: [PATCH] mtd: spi-nor: Add support for mx25r3235f + +Add MTD support for the Macronix MX25R3235F SPI NOR chip from Macronix. +The chip has 4MB of total capacity, divided into a total of 64 sectors, +each 64KB sized. The chip also supports 4KB large sectors. +Additionally, it supports dual and quad read modes. + +Functionality was verified on an HPE/Aruba AP-303 board. + +Signed-off-by: David Bauer +Signed-off-by: Tudor Ambarus +--- + drivers/mtd/spi-nor/spi-nor.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -2353,6 +2353,8 @@ static const struct flash_info spi_nor_i + { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, ++ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, diff --git a/target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch b/target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch new file mode 100644 index 0000000000..805836fcca --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,165 @@ +From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 24/53] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ + drivers/gpio/gpiolib-sysfs.c | 10 +++++- + include/asm-generic/gpio.h | 6 ++++ + include/linux/gpio/consumer.h | 8 +++++ + 4 files changed, 91 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + #include "gpiolib-of.h" +@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip + { + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ if (!gpio_is_valid(gpio)) ++ return gpio; ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++ .probe = of_gpio_export_probe, ++}; ++ ++module_platform_driver(gpio_export_driver); +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -571,7 +571,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -633,6 +633,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -654,6 +656,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { diff --git a/target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch b/target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch new file mode 100644 index 0000000000..14affc28c1 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch @@ -0,0 +1,32 @@ +From 77d9b11ae7269dcf376c3b9493209f712524e986 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 22 Jan 2020 12:56:35 +0100 +Subject: [PATCH] arm: dts: IPQ4019: add SDHCI VQMMC LDO node + +Since we now have driver for the SDHCI VQMMC LDO needed +for I/0 voltage levels lets introduce the necessary node for it. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -209,6 +209,16 @@ + interrupts = ; + }; + ++ vqmmc: regulator@1948000 { ++ compatible = "qcom,vqmmc-ipq4019-regulator"; ++ reg = <0x01948000 0x4>; ++ regulator-name = "vqmmc"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-always-on; ++ status = "disabled"; ++ }; ++ + sdhci: sdhci@7824900 { + compatible = "qcom,sdhci-msm-v4"; + reg = <0x7824900 0x11c>, <0x7824000 0x800>; diff --git a/target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch b/target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch new file mode 100644 index 0000000000..b033a1baee --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch @@ -0,0 +1,97 @@ +From 193856b5fe11c50a0b6ff22457dd674c1a45fec6 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Wed, 9 Sep 2020 18:31:03 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: add USB devicetree nodes + +Since we now have driver for the USB PHY, and USB controller is already supported by the DWC3 driver lets add the necessary nodes to DTSI. + +Signed-off-by: John Crispin +Signed-off-by: Robert Marko +Cc: Luka Perkov +Reviewed-by: Vinod Koul +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 74 +++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -615,5 +615,79 @@ + reg = <4>; + }; + }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ compatible = "qcom,usb-ss-ipq4019-phy"; ++ #phy-cells = <0>; ++ reg = <0x9a000 0x800>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB3_UNIPHY_PHY_ARES>; ++ reset-names = "por_rst"; ++ status = "disabled"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ compatible = "qcom,usb-hs-ipq4019-phy"; ++ #phy-cells = <0>; ++ reg = <0xa6000 0x40>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB3_HSPHY_POR_ARES>, <&gcc USB3_HSPHY_S_ARES>; ++ reset-names = "por_rst", "srif_rst"; ++ status = "disabled"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ compatible = "qcom,dwc3"; ++ reg = <0x8af8800 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc GCC_USB3_MASTER_CLK>, ++ <&gcc GCC_USB3_SLEEP_CLK>, ++ <&gcc GCC_USB3_MOCK_UTMI_CLK>; ++ clock-names = "master", "sleep", "mock_utmi"; ++ ranges; ++ status = "disabled"; ++ ++ dwc3@8a00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x8a00000 0xf8000>; ++ interrupts = ; ++ phys = <&usb3_hs_phy>, <&usb3_ss_phy>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ dr_mode = "host"; ++ }; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ compatible = "qcom,usb-hs-ipq4019-phy"; ++ #phy-cells = <0>; ++ reg = <0xa8000 0x40>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB2_HSPHY_POR_ARES>, <&gcc USB2_HSPHY_S_ARES>; ++ reset-names = "por_rst", "srif_rst"; ++ status = "disabled"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ compatible = "qcom,dwc3"; ++ reg = <0x60f8800 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc GCC_USB2_MASTER_CLK>, ++ <&gcc GCC_USB2_SLEEP_CLK>, ++ <&gcc GCC_USB2_MOCK_UTMI_CLK>; ++ clock-names = "master", "sleep", "mock_utmi"; ++ ranges; ++ status = "disabled"; ++ ++ dwc3@6000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x6000000 0xf8000>; ++ interrupts = ; ++ phys = <&usb2_hs_phy>; ++ phy-names = "usb2-phy"; ++ dr_mode = "host"; ++ }; ++ }; + }; + }; diff --git a/target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch b/target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch new file mode 100644 index 0000000000..0e215ee7cf --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch @@ -0,0 +1,42 @@ +From caa3ee6b094ee18021943504c938919fcac325ec Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 9 Sep 2020 20:40:33 +0200 +Subject: [PATCH] arm: dts: qcom: ipq4019: add more labels + +Lets add labels to more commonly used nodes for easier modification in board DTS files. + +Signed-off-by: Robert Marko +Cc: Luka Perkov +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -190,7 +190,7 @@ + reg = <0x1800000 0x60000>; + }; + +- rng@22000 { ++ prng: rng@22000 { + compatible = "qcom,prng"; + reg = <0x22000 0x140>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; +@@ -310,7 +310,7 @@ + status = "disabled"; + }; + +- crypto@8e3a000 { ++ crypto: crypto@8e3a000 { + compatible = "qcom,crypto-v5.1"; + reg = <0x08e3a000 0x6000>; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>, +@@ -396,7 +396,7 @@ + dma-names = "rx", "tx"; + }; + +- watchdog@b017000 { ++ watchdog: watchdog@b017000 { + compatible = "qcom,kpss-wdt", "qcom,kpss-wdt-ipq4019"; + reg = <0xb017000 0x40>; + clocks = <&sleep_clk>; diff --git a/target/linux/ipq40xx/patches-5.10/104-clk-fix-apss-cpu-overclocking.patch b/target/linux/ipq40xx/patches-5.10/104-clk-fix-apss-cpu-overclocking.patch new file mode 100644 index 0000000000..25a2020bd2 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/104-clk-fix-apss-cpu-overclocking.patch @@ -0,0 +1,115 @@ +From f2b87dc1028b710ec8ce25808b9d21f92b376184 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 11 Mar 2018 14:41:31 +0100 +Subject: [PATCH 2/2] clk: fix apss cpu overclocking + +There's an interaction issue between the clk changes:" +clk: qcom: ipq4019: Add the apss cpu pll divider clock node +clk: qcom: ipq4019: remove fixed clocks and add pll clocks +" and the cpufreq-dt. + +cpufreq-dt is now spamming the kernel-log with the following: + +[ 1099.190658] cpu cpu0: dev_pm_opp_set_rate: failed to find current OPP +for freq 761142857 (-34) + +This only happens on certain devices like the Compex WPJ428 +and AVM FritzBox!4040. However, other devices like the Asus +RT-AC58U and Meraki MR33 work just fine. + +The issue stem from the fact that all higher CPU-Clocks +are achieved by switching the clock-parent to the P_DDRPLLAPSS +(ddrpllapss). Which is set by Qualcomm's proprietary bootcode +as part of the DDR calibration. + +For example, the FB4040 uses 256 MiB Nanya NT5CC128M16IP clocked +at round 533 MHz (ddrpllsdcc = 190285714 Hz). + +whereas the 128 MiB Nanya NT5CC64M16GP-DI in the ASUS RT-AC58U is +clocked at a slightly higher 537 MHz ( ddrpllsdcc = 192000000 Hz). + +This patch attempts to fix the issue by modifying +clk_cpu_div_round_rate(), clk_cpu_div_set_rate(), clk_cpu_div_recalc_rate() +to use a new qcom_find_freq_close() function, which returns the closest +matching frequency, instead of the next higher. This way, the SoC in +the FB4040 (with its max clock speed of 710.4 MHz) will no longer +try to overclock to 761 MHz. + +Fixes: d83dcacea18 ("clk: qcom: ipq4019: Add the apss cpu pll divider clock node") +Signed-off-by: Christian Lamparter +Signed-off-by: John Crispin +--- + drivers/clk/qcom/gcc-ipq4019.c | 34 +++++++++++++++++++++++++++++++--- + 1 file changed, 31 insertions(+), 3 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1243,6 +1243,29 @@ static const struct clk_fepll_vco gcc_fe + .reg = 0x2f020, + }; + ++ ++const struct freq_tbl *qcom_find_freq_close(const struct freq_tbl *f, ++ unsigned long rate) ++{ ++ const struct freq_tbl *last = NULL; ++ ++ for ( ; f->freq; f++) { ++ if (rate == f->freq) ++ return f; ++ ++ if (f->freq > rate) { ++ if (!last || ++ (f->freq - rate) < (rate - last->freq)) ++ return f; ++ else ++ return last; ++ } ++ last = f; ++ } ++ ++ return last; ++} ++ + /* + * Round rate function for APSS CPU PLL Clock divider. + * It looks up the frequency table and returns the next higher frequency +@@ -1255,7 +1278,7 @@ static long clk_cpu_div_round_rate(struc + struct clk_hw *p_hw; + const struct freq_tbl *f; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1278,7 +1301,7 @@ static int clk_cpu_div_set_rate(struct c + u32 mask; + int ret; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1305,6 +1328,7 @@ static unsigned long + clk_cpu_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { ++ const struct freq_tbl *f; + struct clk_fepll *pll = to_clk_fepll(hw); + u32 cdiv, pre_div; + u64 rate; +@@ -1325,7 +1349,11 @@ clk_cpu_div_recalc_rate(struct clk_hw *h + rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2; + do_div(rate, pre_div); + +- return rate; ++ f = qcom_find_freq_close(pll->freq_tbl, rate); ++ if (!f) ++ return rate; ++ ++ return f->freq; + }; + + static const struct clk_ops clk_regmap_cpu_div_ops = { diff --git a/target/linux/ipq40xx/patches-5.10/300-clk-qcom-ipq4019-add-ess-reset.patch b/target/linux/ipq40xx/patches-5.10/300-clk-qcom-ipq4019-add-ess-reset.patch new file mode 100644 index 0000000000..4297f32e05 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/300-clk-qcom-ipq4019-add-ess-reset.patch @@ -0,0 +1,52 @@ +From 480c1f7648fc586db12d6003c717c23667a4fcf0 Mon Sep 17 00:00:00 2001 +From: Ram Chandra Jangir +Date: Tue, 28 Mar 2017 22:35:33 +0530 +Subject: [PATCH] clk: qcom: ipq4019: add ess reset + +Added the ESS reset in IPQ4019 GCC. + +Signed-off-by: Ram Chandra Jangir +--- + drivers/clk/qcom/gcc-ipq4019.c | 11 +++++++++++ + include/dt-bindings/clock/qcom,gcc-ipq4019.h | 11 +++++++++++ + 2 files changed, 22 insertions(+) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1736,6 +1736,17 @@ static const struct qcom_reset_map gcc_i + [GCC_TCSR_BCR] = {0x22000, 0}, + [GCC_MPM_BCR] = {0x24000, 0}, + [GCC_SPDM_BCR] = {0x25000, 0}, ++ [ESS_MAC1_ARES] = {0x1200C, 0}, ++ [ESS_MAC2_ARES] = {0x1200C, 1}, ++ [ESS_MAC3_ARES] = {0x1200C, 2}, ++ [ESS_MAC4_ARES] = {0x1200C, 3}, ++ [ESS_MAC5_ARES] = {0x1200C, 4}, ++ [ESS_PSGMII_ARES] = {0x1200C, 5}, ++ [ESS_MAC1_CLK_DIS] = {0x1200C, 8}, ++ [ESS_MAC2_CLK_DIS] = {0x1200C, 9}, ++ [ESS_MAC3_CLK_DIS] = {0x1200C, 10}, ++ [ESS_MAC4_CLK_DIS] = {0x1200C, 11}, ++ [ESS_MAC5_CLK_DIS] = {0x1200C, 12}, + }; + + static const struct regmap_config gcc_ipq4019_regmap_config = { +--- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h ++++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h +@@ -165,5 +165,16 @@ + #define GCC_QDSS_BCR 69 + #define GCC_MPM_BCR 70 + #define GCC_SPDM_BCR 71 ++#define ESS_MAC1_ARES 72 ++#define ESS_MAC2_ARES 73 ++#define ESS_MAC3_ARES 74 ++#define ESS_MAC4_ARES 75 ++#define ESS_MAC5_ARES 76 ++#define ESS_PSGMII_ARES 77 ++#define ESS_MAC1_CLK_DIS 78 ++#define ESS_MAC2_CLK_DIS 79 ++#define ESS_MAC3_CLK_DIS 80 ++#define ESS_MAC4_CLK_DIS 81 ++#define ESS_MAC5_CLK_DIS 82 + + #endif diff --git a/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch b/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch new file mode 100644 index 0000000000..7e6184fc73 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch @@ -0,0 +1,48 @@ +From 0843a61d6913bdac8889eb048ed89f7903059787 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 30 Oct 2020 13:36:31 +0100 +Subject: [PATCH] arm: compressed: add appended DTB section + +This adds a appended_dtb section to the ARM decompressor +linker script. + +This allows using the existing ARM zImage appended DTB support for +appending a DTB to the raw ELF kernel. + +Its size is set to 1MB max to match the zImage appended DTB size limit. + +To use it to pass the DTB to the kernel, objcopy is used: + +objcopy --set-section-flags=.appended_dtb=alloc,contents \ + --update-section=.appended_dtb=.dtb vmlinux + +This is based off the following patch: +https://github.com/openwrt/openwrt/commit/c063e27e02a9dcac0e7f5877fb154e58fa3e1a69 + +Signed-off-by: Robert Marko +--- + arch/arm/boot/compressed/vmlinux.lds.S | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -93,6 +93,13 @@ SECTIONS + + _edata = .; + ++ .appended_dtb : { ++ /* leave space for appended DTB */ ++ . += 0x100000; ++ } ++ ++ _edata_dtb = .; ++ + /* + * The image_end section appears after any additional loadable sections + * that the linker may decide to insert in the binary image. Having +@@ -132,4 +139,4 @@ SECTIONS + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + } +-ASSERT(_edata_real == _edata, "error: zImage file size is incorrect"); ++ASSERT(_edata_real == _edata_dtb, "error: zImage file size is incorrect"); diff --git a/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch b/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch new file mode 100644 index 0000000000..71618a40f2 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch @@ -0,0 +1,66 @@ +From 11d6a6128a5a07c429941afc202b6e62a19771be Mon Sep 17 00:00:00 2001 +From: John Thomson +Date: Fri, 23 Oct 2020 19:42:36 +1000 +Subject: [PATCH 2/2] arm: compressed: set ipq40xx watchdog to allow boot + +For IPQ40XX systems where the SoC watchdog is activated before linux, +the watchdog timer may be too small for linux to finish uncompress, +boot, and watchdog management start. +If the watchdog is enabled, set the timeout for it to 30 seconds. +The functionality and offsets were copied from: +drivers/watchdog/qcom-wdt.c qcom_wdt_set_timeout & qcom_wdt_start +The watchdog memory address was taken from: +arch/arm/boot/dts/qcom-ipq4019.dtsi + +This was required on Mikrotik IPQ40XX consumer hardware using Mikrotik's +RouterBoot bootloader. + +Signed-off-by: John Thomson +--- + arch/arm/boot/compressed/head.S | 35 +++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -599,6 +599,41 @@ not_relocated: mov r0, #0 + bic r4, r4, #1 + blne cache_on + ++/* Set the Qualcom IPQ40xx watchdog timeout to 30 seconds ++ * if it is enabled, so that there is time for kernel ++ * to decompress, boot, and take over the watchdog. ++ * data and functionality from drivers/watchdog/qcom-wdt.c ++ * address from arch/arm/boot/dts/qcom-ipq4019.dtsi ++ */ ++#ifdef CONFIG_ARCH_IPQ40XX ++watchdog_set: ++ /* offsets: ++ * 0x04 reset (=1 resets countdown) ++ * 0x08 enable (=0 disables) ++ * 0x0c status (=1 when SoC was reset by watchdog) ++ * 0x10 bark (=timeout warning in ticks) ++ * 0x14 bite (=timeout reset in ticks) ++ * clock rate is 1<<15 hertz ++ */ ++ .equ watchdog, 0x0b017000 @Store watchdog base address ++ movw r0, #:lower16:watchdog ++ movt r0, #:upper16:watchdog ++ ldr r1, [r0, #0x08] @Get enabled? ++ cmp r1, #1 @If not enabled, do not change ++ bne watchdog_finished ++ mov r1, #0 ++ str r1, [r0, #0x08] @Disable the watchdog ++ mov r1, #1 ++ str r1, [r0, #0x04] @Pet the watchdog ++ mov r1, #30 @30 seconds timeout ++ lsl r1, r1, #15 @converted to ticks ++ str r1, [r0, #0x10] @Set the bark timeout ++ str r1, [r0, #0x14] @Set the bite timeout ++ mov r1, #1 ++ str r1, [r0, #0x08] @Enable the watchdog ++watchdog_finished: ++#endif /* CONFIG_ARCH_IPQ40XX */ ++ + /* + * The C runtime environment should now be setup sufficiently. + * Set up some pointers, and start decompressing. diff --git a/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch b/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch new file mode 100644 index 0000000000..e56ab6d0f1 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch @@ -0,0 +1,25 @@ +From 0e28623a11f3916c1fe5b7e789c7ab8ca932a929 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 22 Jan 2020 13:02:13 +0100 +Subject: [PATCH] mmc: sdhci: sdhci-msm: use sdhci_set_clock instead of + sdhci_msm_set_clock + +When using sdhci_msm_set_clock clock setting will fail, so lets +use the generic sdhci_set_clock. + +Signed-off-by: Robert Marko +--- + drivers/mmc/host/sdhci-msm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-msm.c ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -1746,7 +1746,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat + + static const struct sdhci_ops sdhci_msm_ops = { + .reset = sdhci_reset, +- .set_clock = sdhci_msm_set_clock, ++ .set_clock = sdhci_set_clock, + .get_min_clock = sdhci_msm_get_min_clock, + .get_max_clock = sdhci_msm_get_max_clock, + .set_bus_width = sdhci_set_bus_width, diff --git a/target/linux/ipq40xx/patches-5.10/702-dts-ipq4019-add-PHY-switch-nodes.patch b/target/linux/ipq40xx/patches-5.10/702-dts-ipq4019-add-PHY-switch-nodes.patch new file mode 100644 index 0000000000..cfbf7bd41f --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/702-dts-ipq4019-add-PHY-switch-nodes.patch @@ -0,0 +1,46 @@ +From 9deeec35dd3b628b95624e41d4e04acf728991ba Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 02:20:54 +0100 +Subject: [PATCH] dts: ipq4019: add PHY/switch nodes + +This patch adds both the "qcom,ess-switch" and "qcom,ess-psgmii" +nodes which are needed for the ar40xx.c driver to initialize the +switch. + +Signed-off-by: Christian Lamparter +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -616,6 +616,29 @@ + }; + }; + ++ ess-switch@c000000 { ++ compatible = "qcom,ess-switch"; ++ reg = <0xc000000 0x80000>; ++ switch_access_mode = "local bus"; ++ resets = <&gcc ESS_RESET>; ++ reset-names = "ess_rst"; ++ clocks = <&gcc GCC_ESS_CLK>; ++ clock-names = "ess_clk"; ++ switch_cpu_bmp = <0x1>; ++ switch_lan_bmp = <0x1e>; ++ switch_wan_bmp = <0x20>; ++ switch_mac_mode = <0>; /* PORT_WRAPPER_PSGMII */ ++ switch_initvlas = <0x7c 0x54>; ++ status = "disabled"; ++ }; ++ ++ ess-psgmii@98000 { ++ compatible = "qcom,ess-psgmii"; ++ reg = <0x98000 0x800>; ++ psgmii_access_mode = "local bus"; ++ status = "disabled"; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qcom,usb-ss-ipq4019-phy"; + #phy-cells = <0>; diff --git a/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch b/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch new file mode 100644 index 0000000000..167673bd11 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch @@ -0,0 +1,53 @@ +From 7c129254adb1093d10a62ed7bf7b956fcc6ffe34 Mon Sep 17 00:00:00 2001 +From: Rakesh Nair +Date: Wed, 20 Jul 2016 15:02:01 +0530 +Subject: [PATCH] net: IPQ4019 needs rfs/vlan_tag callbacks in + netdev_ops + +Add callback support to get default vlan tag and register +receive flow steering filter. + +Used by IPQ4019 ess-edma driver. + +BUG=chrome-os-partner:33096 +TEST=none + +Change-Id: I266070e4a0fbe4a0d9966fe79a71e50ec4f26c75 +Signed-off-by: Rakesh Nair +Reviewed-on: https://chromium-review.googlesource.com/362203 +Commit-Ready: Grant Grundler +Tested-by: Grant Grundler +Reviewed-by: Grant Grundler +--- + include/linux/netdevice.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -776,6 +776,16 @@ struct xps_map { + #define XPS_MIN_MAP_ALLOC ((L1_CACHE_ALIGN(offsetof(struct xps_map, queues[1])) \ + - sizeof(struct xps_map)) / sizeof(u16)) + ++#ifdef CONFIG_RFS_ACCEL ++typedef int (*set_rfs_filter_callback_t)(struct net_device *dev, ++ __be32 src, ++ __be32 dst, ++ __be16 sport, ++ __be16 dport, ++ u8 proto, ++ u16 rxq_index, ++ u32 action); ++#endif + /* + * This structure holds all XPS maps for device. Maps are indexed by CPU. + */ +@@ -1379,6 +1389,9 @@ struct net_device_ops { + const struct sk_buff *skb, + u16 rxq_index, + u32 flow_id); ++ int (*ndo_register_rfs_filter)(struct net_device *dev, ++ set_rfs_filter_callback_t set_filter); ++ int (*ndo_get_default_vlan_tag)(struct net_device *net); + #endif + int (*ndo_add_slave)(struct net_device *dev, + struct net_device *slave_dev, diff --git a/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch b/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch new file mode 100644 index 0000000000..9adddcabc3 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -584,6 +584,13 @@ config XILINX_GMII2RGMII + the Reduced Gigabit Media Independent Interface(RGMII) between + Ethernet physical media devices and the Gigabit Ethernet controller. + ++config AR40XX_PHY ++ tristate "Driver for Qualcomm Atheros IPQ40XX switches" ++ depends on HAS_IOMEM && OF && OF_MDIO ++ select SWCONFIG ++ help ++ This is the driver for Qualcomm Atheros IPQ40XX ESS switches. ++ + endif # PHYLIB + + config MICREL_KS8995MA +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -69,6 +69,7 @@ ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif + obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AR40XX_PHY) += ar40xx.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o diff --git a/target/linux/ipq40xx/patches-5.10/706-dt-bindings-net-add-QCA807x-PHY.patch b/target/linux/ipq40xx/patches-5.10/706-dt-bindings-net-add-QCA807x-PHY.patch new file mode 100644 index 0000000000..dfb8d692ab --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/706-dt-bindings-net-add-QCA807x-PHY.patch @@ -0,0 +1,61 @@ +From c66863c1ba8995b61e6d727d78a241c734f5bb57 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 1 Oct 2020 15:05:35 +0200 +Subject: [PATCH] dt-bindings: net: add QCA807x PHY + +Add DT bindings for Qualcomm QCA807x PHY series. + +Signed-off-by: Robert Marko +--- + include/dt-bindings/net/qcom-qca807x.h | 45 ++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + create mode 100644 include/dt-bindings/net/qcom-qca807x.h + +--- /dev/null ++++ b/include/dt-bindings/net/qcom-qca807x.h +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Device Tree constants for the Qualcomm QCA807X PHYs ++ */ ++ ++#ifndef _DT_BINDINGS_QCOM_QCA807X_H ++#define _DT_BINDINGS_QCOM_QCA807X_H ++ ++#define PSGMII_QSGMII_TX_DRIVER_140MV 0 ++#define PSGMII_QSGMII_TX_DRIVER_160MV 1 ++#define PSGMII_QSGMII_TX_DRIVER_180MV 2 ++#define PSGMII_QSGMII_TX_DRIVER_200MV 3 ++#define PSGMII_QSGMII_TX_DRIVER_220MV 4 ++#define PSGMII_QSGMII_TX_DRIVER_240MV 5 ++#define PSGMII_QSGMII_TX_DRIVER_260MV 6 ++#define PSGMII_QSGMII_TX_DRIVER_280MV 7 ++#define PSGMII_QSGMII_TX_DRIVER_300MV 8 ++#define PSGMII_QSGMII_TX_DRIVER_320MV 9 ++#define PSGMII_QSGMII_TX_DRIVER_400MV 10 ++#define PSGMII_QSGMII_TX_DRIVER_500MV 11 ++/* Default value */ ++#define PSGMII_QSGMII_TX_DRIVER_600MV 12 ++ ++/* Full amplitude, full bias current */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_BIAS 0 ++/* Amplitude follow DSP (amplitude is adjusted based on cable length), half bias current */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS 1 ++/* Full amplitude, bias current follow DSP (bias current is adjusted based on cable length) */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_DSP_BIAS 2 ++/* Both amplitude and bias current follow DSP */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_BIAS 3 ++/* Full amplitude, half bias current */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS 4 ++/* Amplitude follow DSP setting; 1/4 bias current when cable<10m, ++ * otherwise half bias current ++ */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS 5 ++/* Full amplitude; same bias current setting with “010” and “011”, ++ * but half more bias is reduced when cable <10m ++ */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS_SHORT 6 ++/* Amplitude follow DSP; same bias current setting with “110”, default value */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS_SHORT 7 ++ ++#endif diff --git a/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch b/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch new file mode 100644 index 0000000000..b71b28d941 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -0,0 +1,50 @@ +From f825cdc8bfde7616a14e2163f16303a8973031d2 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 7 Oct 2020 17:38:48 +0200 +Subject: [PATCH] net: phy: Add Qualcom QCA807x driver + +This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. + +They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, 100BASE-TX and 1000BASE-T PHY-s. + +They feature 2 SerDes, one for PSGMII or QSGMII connection with MAC, while second one is SGMII for connection to MAC or fiber. + +Both models have a combo port that supports 1000BASE-X and 100BASE-FX fiber. + +Each PHY inside of QCA807x series has 4 digitally controlled output only pins that natively drive LED-s. +But some vendors used these to driver generic LED-s controlled by userspace, +so lets enable registering each PHY as GPIO controller and add driver for it. + +These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x boards. + +Signed-off-by: Robert Marko +--- + drivers/net/phy/Kconfig | 6 ++++++ + drivers/net/phy/Makefile | 1 + + 2 files changed, 7 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -537,6 +537,12 @@ config NXP_TJA11XX_PHY + ---help--- + Currently supports the NXP TJA1100 and TJA1101 PHY. + ++config QCA807X_PHY ++ tristate "Qualcomm QCA807X PHYs" ++ depends on OF_MDIO ++ help ++ Currently supports the QCA8072 and QCA8075 models. ++ + config QSEMI_PHY + tristate "Quality Semiconductor PHYs" + ---help--- +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -103,6 +103,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc.o + obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-$(CONFIG_QSEMI_PHY) += qsemi.o ++obj-$(CONFIG_QCA807X_PHY) += qca807x.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch b/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch new file mode 100644 index 0000000000..4b04a3ce9a --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch @@ -0,0 +1,62 @@ +From e0fa88eaa3c176b71e563da68949ac2ab45aaa61 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 2 Oct 2020 10:43:26 +0200 +Subject: [PATCH] arm: dts: ipq4019: QCA807x properties + +This adds necessary DT properties for QCA807x PHY-s to IPQ4019 DTSI. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -597,22 +598,39 @@ + + ethphy0: ethernet-phy@0 { + reg = <0>; ++ ++ qcom,control-dac = ; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; ++ ++ qcom,control-dac = ; + }; + + ethphy2: ethernet-phy@2 { + reg = <2>; ++ ++ qcom,control-dac = ; + }; + + ethphy3: ethernet-phy@3 { + reg = <3>; ++ ++ qcom,control-dac = ; + }; + + ethphy4: ethernet-phy@4 { + reg = <4>; ++ ++ qcom,control-dac = ; ++ }; ++ ++ psgmiiphy: psgmii-phy@5 { ++ reg = <5>; ++ ++ qcom,tx-driver-strength = ; ++ qcom,psgmii-az; + }; + }; + diff --git a/target/linux/ipq40xx/patches-5.10/710-net-add-qualcomm-essedma-ethernet-driver.patch b/target/linux/ipq40xx/patches-5.10/710-net-add-qualcomm-essedma-ethernet-driver.patch new file mode 100644 index 0000000000..793ce72142 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/710-net-add-qualcomm-essedma-ethernet-driver.patch @@ -0,0 +1,37 @@ +From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Thu, 19 Jan 2017 02:01:31 +0100 +Subject: [PATCH 33/38] NET: add qualcomm essedma ethernet driver + +Signed-off-by: Christian Lamparter +--- + drivers/net/ethernet/qualcomm/Kconfig | 9 +++++++++ + drivers/net/ethernet/qualcomm/Makefile | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/net/ethernet/qualcomm/Kconfig ++++ b/drivers/net/ethernet/qualcomm/Kconfig +@@ -62,4 +62,14 @@ config QCOM_EMAC + + source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" + ++config ESSEDMA ++ tristate "Qualcomm Atheros ESS Edma support" ++ depends on OF_MDIO ++ help ++ This driver supports ethernet edma adapter. ++ Say Y to build this driver. ++ ++ To compile this driver as a module, choose M here. The module ++ will be called essedma.ko. ++ + endif # NET_VENDOR_QUALCOMM +--- a/drivers/net/ethernet/qualcomm/Makefile ++++ b/drivers/net/ethernet/qualcomm/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o + qcauart-objs := qca_uart.o + + obj-y += emac/ ++obj-$(CONFIG_ESSEDMA) += essedma/ + + obj-$(CONFIG_RMNET) += rmnet/ diff --git a/target/linux/ipq40xx/patches-5.10/711-dts-ipq4019-add-ethernet-essedma-node.patch b/target/linux/ipq40xx/patches-5.10/711-dts-ipq4019-add-ethernet-essedma-node.patch new file mode 100644 index 0000000000..7b2ddfe00d --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/711-dts-ipq4019-add-ethernet-essedma-node.patch @@ -0,0 +1,92 @@ +From c611d3780fa101662a822d10acf8feb04ca97409 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 01:01:10 +0100 +Subject: [PATCH] dts: ipq4019: add ethernet essedma node + +This patch adds the device-tree node for the ethernet +interfaces. + +Note: The driver isn't anywhere close to be upstream, +so the info might change. + +Signed-off-by: Christian Lamparter +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -39,6 +39,8 @@ + spi1 = &blsp1_spi2; + i2c0 = &blsp1_i2c3; + i2c1 = &blsp1_i2c4; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + }; + + cpus { +@@ -657,6 +659,64 @@ + status = "disabled"; + }; + ++ edma@c080000 { ++ compatible = "qcom,ess-edma"; ++ reg = <0xc080000 0x8000>; ++ qcom,page-mode = <0>; ++ qcom,rx_head_buf_size = <1540>; ++ qcom,mdio_supported; ++ qcom,poll_required = <1>; ++ qcom,num_gmac = <2>; ++ interrupts = <0 65 IRQ_TYPE_EDGE_RISING ++ 0 66 IRQ_TYPE_EDGE_RISING ++ 0 67 IRQ_TYPE_EDGE_RISING ++ 0 68 IRQ_TYPE_EDGE_RISING ++ 0 69 IRQ_TYPE_EDGE_RISING ++ 0 70 IRQ_TYPE_EDGE_RISING ++ 0 71 IRQ_TYPE_EDGE_RISING ++ 0 72 IRQ_TYPE_EDGE_RISING ++ 0 73 IRQ_TYPE_EDGE_RISING ++ 0 74 IRQ_TYPE_EDGE_RISING ++ 0 75 IRQ_TYPE_EDGE_RISING ++ 0 76 IRQ_TYPE_EDGE_RISING ++ 0 77 IRQ_TYPE_EDGE_RISING ++ 0 78 IRQ_TYPE_EDGE_RISING ++ 0 79 IRQ_TYPE_EDGE_RISING ++ 0 80 IRQ_TYPE_EDGE_RISING ++ 0 240 IRQ_TYPE_EDGE_RISING ++ 0 241 IRQ_TYPE_EDGE_RISING ++ 0 242 IRQ_TYPE_EDGE_RISING ++ 0 243 IRQ_TYPE_EDGE_RISING ++ 0 244 IRQ_TYPE_EDGE_RISING ++ 0 245 IRQ_TYPE_EDGE_RISING ++ 0 246 IRQ_TYPE_EDGE_RISING ++ 0 247 IRQ_TYPE_EDGE_RISING ++ 0 248 IRQ_TYPE_EDGE_RISING ++ 0 249 IRQ_TYPE_EDGE_RISING ++ 0 250 IRQ_TYPE_EDGE_RISING ++ 0 251 IRQ_TYPE_EDGE_RISING ++ 0 252 IRQ_TYPE_EDGE_RISING ++ 0 253 IRQ_TYPE_EDGE_RISING ++ 0 254 IRQ_TYPE_EDGE_RISING ++ 0 255 IRQ_TYPE_EDGE_RISING>; ++ ++ status = "disabled"; ++ ++ gmac0: gmac0 { ++ local-mac-address = [00 00 00 00 00 00]; ++ vlan_tag = <1 0x1f>; ++ }; ++ ++ gmac1: gmac1 { ++ local-mac-address = [00 00 00 00 00 00]; ++ qcom,phy_mdio_addr = <4>; ++ qcom,poll_required = <1>; ++ qcom,forced_speed = <1000>; ++ qcom,forced_duplex = <1>; ++ vlan_tag = <2 0x20>; ++ }; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qcom,usb-ss-ipq4019-phy"; + #phy-cells = <0>; diff --git a/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch b/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch new file mode 100644 index 0000000000..17e9047dfb --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch @@ -0,0 +1,180 @@ +From: Christian Lamparter +Subject: SoC: add qualcomm syscon +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o + obj-$(CONFIG_QCOM_SMSM) += smsm.o + obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o + obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o ++obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o + obj-$(CONFIG_QCOM_APR) += apr.o + obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o + obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -183,6 +183,13 @@ config QCOM_SOCINFO + Say yes here to support the Qualcomm socinfo driver, providing + information about the SoC to user space. + ++config QCOM_TCSR ++ tristate "QCOM Top Control and Status Registers" ++ depends on ARCH_QCOM ++ help ++ Say y here to enable TCSR support. The TCSR provides control ++ functions for various peripherals. ++ + config QCOM_WCNSS_CTRL + tristate "Qualcomm WCNSS control driver" + depends on ARCH_QCOM || COMPILE_TEST +--- /dev/null ++++ b/drivers/soc/qcom/qcom_tcsr.c +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (c) 2014, The Linux foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License rev 2 and ++ * only rev 2 as published by the free Software foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TCSR_USB_PORT_SEL 0xb0 ++#define TCSR_USB_HSPHY_CONFIG 0xC ++ ++#define TCSR_ESS_INTERFACE_SEL_OFFSET 0x0 ++#define TCSR_ESS_INTERFACE_SEL_MASK 0xf ++ ++#define TCSR_WIFI0_GLB_CFG_OFFSET 0x0 ++#define TCSR_WIFI1_GLB_CFG_OFFSET 0x4 ++#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2 0x4 ++ ++static int tcsr_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct device_node *node = pdev->dev.of_node; ++ void __iomem *base; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) { ++ dev_err(&pdev->dev, "setting usb port select = %d\n", val); ++ writel(val, base + TCSR_USB_PORT_SEL); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) { ++ dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val); ++ writel(val, base + TCSR_USB_HSPHY_CONFIG); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) { ++ u32 tmp = 0; ++ dev_info(&pdev->dev, "setting ess interface select = %x\n", val); ++ tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK); ++ tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK); ++ writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) { ++ dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val); ++ writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET); ++ writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) { ++ dev_info(&pdev->dev, ++ "setting wifi_noc_memtype_m0_m2 = %x\n", val); ++ writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id tcsr_dt_match[] = { ++ { .compatible = "qcom,tcsr", }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, tcsr_dt_match); ++ ++static struct platform_driver tcsr_driver = { ++ .driver = { ++ .name = "tcsr", ++ .owner = THIS_MODULE, ++ .of_match_table = tcsr_dt_match, ++ }, ++ .probe = tcsr_probe, ++}; ++ ++module_platform_driver(tcsr_driver); ++ ++MODULE_AUTHOR("Andy Gross "); ++MODULE_DESCRIPTION("QCOM TCSR driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/dt-bindings/soc/qcom,tcsr.h +@@ -0,0 +1,48 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __DT_BINDINGS_QCOM_TCSR_H ++#define __DT_BINDINGS_QCOM_TCSR_H ++ ++#define TCSR_USB_SELECT_USB3_P0 0x1 ++#define TCSR_USB_SELECT_USB3_P1 0x2 ++#define TCSR_USB_SELECT_USB3_DUAL 0x3 ++ ++/* IPQ40xx HS PHY Mode Select */ ++#define TCSR_USB_HSPHY_HOST_MODE 0x00E700E7 ++#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7 ++ ++/* IPQ40xx ess interface mode select */ ++#define TCSR_ESS_PSGMII 0 ++#define TCSR_ESS_PSGMII_RGMII5 1 ++#define TCSR_ESS_PSGMII_RMII0 2 ++#define TCSR_ESS_PSGMII_RMII1 4 ++#define TCSR_ESS_PSGMII_RMII0_RMII1 6 ++#define TCSR_ESS_PSGMII_RGMII4 9 ++ ++/* ++ * IPQ40xx WiFi Global Config ++ * Bit 30:AXID_EN ++ * Enable AXI master bus Axid translating to confirm all txn submitted by order ++ * Bit 24: Use locally generated socslv_wxi_bvalid ++ * 1: use locally generate socslv_wxi_bvalid for performance. ++ * 0: use SNOC socslv_wxi_bvalid. ++ */ ++#define TCSR_WIFI_GLB_CFG 0x41000000 ++ ++/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */ ++#define TCSR_WIFI_NOC_MEMTYPE_M0_M2 0x02222222 ++ ++/* TCSR A/B REG */ ++#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0 ++#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1 ++ ++#endif diff --git a/target/linux/ipq40xx/patches-5.10/900-dts-ipq4019-ap-dk01.1.patch b/target/linux/ipq40xx/patches-5.10/900-dts-ipq4019-ap-dk01.1.patch new file mode 100644 index 0000000000..5a245eb431 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/900-dts-ipq4019-ap-dk01.1.patch @@ -0,0 +1,176 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -15,6 +15,7 @@ + */ + + #include "qcom-ipq4019.dtsi" ++#include + + / { + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1"; +@@ -29,6 +30,32 @@ + }; + + soc { ++ tcsr@194b000 { ++ /* select hostmode */ ++ compatible = "qcom,tcsr"; ++ reg = <0x194b000 0x100>; ++ qcom,usb-hsphy-mode-select = ; ++ status = "okay"; ++ }; ++ ++ ess_tcsr@1953000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1953000 0x1000>; ++ qcom,ess-interface-select = ; ++ }; ++ ++ tcsr@1949000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1949000 0x100>; ++ qcom,wifi_glb_cfg = ; ++ }; ++ ++ tcsr@1957000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1957000 0x100>; ++ qcom,wifi_noc_memtype_m0_m2 = ; ++ }; ++ + rng@22000 { + status = "ok"; + }; +@@ -74,14 +101,6 @@ + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; +- +- mx25l25635e@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- reg = <0>; +- compatible = "mx25l25635e"; +- spi-max-frequency = <24000000>; +- }; + }; + + serial@78af000 { +@@ -109,5 +128,41 @@ + wifi@a800000 { + status = "ok"; + }; ++ ++ mdio@90000 { ++ status = "okay"; ++ }; ++ ++ ess-switch@c000000 { ++ status = "okay"; ++ }; ++ ++ ess-psgmii@98000 { ++ status = "okay"; ++ }; ++ ++ edma@c080000 { ++ status = "okay"; ++ }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ status = "okay"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ status = "okay"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ status = "okay"; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ status = "okay"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ status = "okay"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts +@@ -18,5 +18,73 @@ + + / { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; ++ compatible = "qcom,ap-dk01.1-c1", "qcom,ap-dk01.2-c1"; + ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; ++ }; ++}; ++ ++&blsp1_spi1 { ++ mx25l25635f@0 { ++ compatible = "mx25l25635f", "jedec,spi-nor"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0>; ++ spi-max-frequency = <24000000>; ++ ++ SBL1@0 { ++ label = "SBL1"; ++ reg = <0x0 0x40000>; ++ read-only; ++ }; ++ MIBIB@40000 { ++ label = "MIBIB"; ++ reg = <0x40000 0x20000>; ++ read-only; ++ }; ++ QSEE@60000 { ++ label = "QSEE"; ++ reg = <0x60000 0x60000>; ++ read-only; ++ }; ++ CDT@c0000 { ++ label = "CDT"; ++ reg = <0xc0000 0x10000>; ++ read-only; ++ }; ++ DDRPARAMS@d0000 { ++ label = "DDRPARAMS"; ++ reg = <0xd0000 0x10000>; ++ read-only; ++ }; ++ APPSBLENV@e0000 { ++ label = "APPSBLENV"; ++ reg = <0xe0000 0x10000>; ++ read-only; ++ }; ++ APPSBL@f0000 { ++ label = "APPSBL"; ++ reg = <0xf0000 0x80000>; ++ read-only; ++ }; ++ ART@170000 { ++ label = "ART"; ++ reg = <0x170000 0x10000>; ++ read-only; ++ }; ++ kernel@180000 { ++ label = "kernel"; ++ reg = <0x180000 0x400000>; ++ }; ++ rootfs@580000 { ++ label = "rootfs"; ++ reg = <0x580000 0x1600000>; ++ }; ++ firmware@180000 { ++ label = "firmware"; ++ reg = <0x180000 0x1a00000>; ++ }; ++ }; + }; diff --git a/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch new file mode 100644 index 0000000000..0447fb6012 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch @@ -0,0 +1,74 @@ +From a10fab12a927e60b7141a602e740d70cb4d09e4a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 9 Mar 2017 11:03:18 +0100 +Subject: [PATCH] arm: boot: add dts files + +Signed-off-by: John Crispin +--- + arch/arm/boot/dts/Makefile | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -837,11 +837,61 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-apq8074-dragonboard.dtb \ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ ++ qcom-ipq4018-a42.dtb \ ++ qcom-ipq4018-ap120c-ac.dtb \ ++ qcom-ipq4018-dap-2610.dtb \ ++ qcom-ipq4018-cs-w3-wd1200g-eup.dtb \ ++ qcom-ipq4018-magic-2-wifi-next.dtb \ ++ qcom-ipq4018-ea6350v3.dtb \ ++ qcom-ipq4018-eap1300.dtb \ ++ qcom-ipq4018-ecw5211.dtb \ ++ qcom-ipq4018-emd1.dtb \ ++ qcom-ipq4018-emr3500.dtb \ ++ qcom-ipq4018-ens620ext.dtb \ ++ qcom-ipq4018-ex6100v2.dtb \ ++ qcom-ipq4018-ex6150v2.dtb \ ++ qcom-ipq4018-fritzbox-4040.dtb \ ++ qcom-ipq4018-gl-ap1300.dtb \ ++ qcom-ipq4018-jalapeno.dtb \ ++ qcom-ipq4018-meshpoint-one.dtb \ ++ qcom-ipq4018-hap-ac2.dtb \ ++ qcom-ipq4018-sxtsq-5-ac.dtb \ ++ qcom-ipq4018-nbg6617.dtb \ ++ qcom-ipq4019-oap100.dtb \ ++ qcom-ipq4018-pa1200.dtb \ ++ qcom-ipq4018-rt-ac58u.dtb \ ++ qcom-ipq4018-wac510.dtb \ ++ qcom-ipq4018-wre6606.dtb \ ++ qcom-ipq4018-wrtq-329acn.dtb \ + qcom-ipq4019-ap.dk01.1-c1.dtb \ + qcom-ipq4019-ap.dk04.1-c1.dtb \ + qcom-ipq4019-ap.dk04.1-c3.dtb \ + qcom-ipq4019-ap.dk07.1-c1.dtb \ + qcom-ipq4019-ap.dk07.1-c2.dtb \ ++ qcom-ipq4019-a62.dtb \ ++ qcom-ipq4019-cm520-79f.dtb \ ++ qcom-ipq4019-ea8300.dtb \ ++ qcom-ipq4019-eap2200.dtb \ ++ qcom-ipq4019-fritzbox-7530.dtb \ ++ qcom-ipq4019-fritzrepeater-1200.dtb \ ++ qcom-ipq4019-fritzrepeater-3000.dtb \ ++ qcom-ipq4019-map-ac2200.dtb \ ++ qcom-ipq4019-mr8300.dtb \ ++ qcom-ipq4019-e2600ac-c1.dtb \ ++ qcom-ipq4019-e2600ac-c2.dtb \ ++ qcom-ipq4019-habanero-dvk.dtb \ ++ qcom-ipq4019-pa2200.dtb \ ++ qcom-ipq4019-rtl30vw.dtb \ ++ qcom-ipq4019-u4019-32m.dtb \ ++ qcom-ipq4019-wpj419.dtb \ ++ qcom-ipq4019-wtr-m2133hp.dtb \ ++ qcom-ipq4028-wpj428.dtb \ ++ qcom-ipq4029-ap-303.dtb \ ++ qcom-ipq4029-ap-303h.dtb \ ++ qcom-ipq4029-ap-365.dtb \ ++ qcom-ipq4029-gl-b1300.dtb \ ++ qcom-ipq4029-gl-s1300.dtb \ ++ qcom-ipq4029-mr33.dtb \ + qcom-ipq8064-ap148.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ diff --git a/target/linux/ipq40xx/patches-5.10/902-dts-ipq4019-ap-dk04.1.patch b/target/linux/ipq40xx/patches-5.10/902-dts-ipq4019-ap-dk04.1.patch new file mode 100644 index 0000000000..ca32144846 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/902-dts-ipq4019-ap-dk04.1.patch @@ -0,0 +1,167 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +@@ -17,53 +17,79 @@ + stdout-path = "serial0:115200n8"; + }; + +- memory { +- device_type = "memory"; +- reg = <0x80000000 0x10000000>; /* 256MB */ +- }; +- + soc { ++ rng@22000 { ++ status = "okay"; ++ }; ++ + pinctrl@1000000 { + serial_0_pins: serial0-pinmux { +- pins = "gpio16", "gpio17"; +- function = "blsp_uart0"; +- bias-disable; ++ mux { ++ pins = "gpio16", "gpio17"; ++ function = "blsp_uart0"; ++ bias-disable; ++ }; + }; + + serial_1_pins: serial1-pinmux { +- pins = "gpio8", "gpio9", +- "gpio10", "gpio11"; +- function = "blsp_uart1"; +- bias-disable; ++ mux { ++ pins = "gpio8", "gpio9"; ++ function = "blsp_uart1"; ++ bias-disable; ++ }; + }; + + spi_0_pins: spi-0-pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; +- bias-disable; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; ++ }; ++ pinconf { ++ pins = "gpio13", "gpio14", "gpio15"; ++ drive-strength = <12>; ++ bias-disable; ++ }; ++ pinconf_cs { ++ pins = "gpio12"; ++ drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c-0-pinmux { +- pins = "gpio20", "gpio21"; +- function = "blsp_i2c0"; +- bias-disable; ++ pinmux { ++ function = "blsp_i2c0"; ++ pins = "gpio10", "gpio11"; ++ }; ++ pinconf { ++ pins = "gpio10", "gpio11"; ++ drive-strength = <16>; ++ bias-disable; ++ }; + }; + + nand_pins: nand-pins { +- pins = "gpio53", "gpio55", "gpio56", +- "gpio57", "gpio58", "gpio59", +- "gpio60", "gpio62", "gpio63", +- "gpio64", "gpio65", "gpio66", +- "gpio67", "gpio68", "gpio69"; +- function = "qpic"; ++ pullups { ++ pins = "gpio52", "gpio53", "gpio58", ++ "gpio59"; ++ function = "qpic"; ++ bias-pull-up; ++ }; ++ ++ pulldowns { ++ pins = "gpio54", "gpio55", "gpio56", ++ "gpio57", "gpio60", "gpio61", ++ "gpio62", "gpio63", "gpio64", ++ "gpio65", "gpio66", "gpio67", ++ "gpio68", "gpio69"; ++ function = "qpic"; ++ bias-pull-down; ++ }; + }; + }; + +@@ -89,11 +115,11 @@ + status = "ok"; + cs-gpios = <&tlmm 12 0>; + +- m25p80@0 { ++ mx25l25635e@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; +- compatible = "n25q128a11"; ++ compatible = "mx25l25635e"; + spi-max-frequency = <24000000>; + }; + }; +@@ -103,9 +129,48 @@ + perst-gpio = <&tlmm 38 0x1>; + }; + ++ i2c0: i2c@78b7000 { /* BLSP1 QUP2 */ ++ pinctrl-0 = <&i2c_0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ }; ++ + qpic-nand@79b0000 { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ status = "okay"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ status = "okay"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ status = "okay"; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ status = "okay"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ status = "okay"; ++ }; ++ ++ cryptobam: dma@8e04000 { ++ status = "okay"; ++ }; ++ ++ crypto@8e3a000 { ++ status = "okay"; ++ }; ++ ++ watchdog@b017000 { ++ status = "okay"; ++ }; + }; + }; diff --git a/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch b/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch new file mode 100644 index 0000000000..3cc032fdd2 --- /dev/null +++ b/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch @@ -0,0 +1,12 @@ +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -1059,6 +1059,9 @@ int __init early_init_dt_scan_chosen(uns + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); ++ p = of_get_flat_dt_prop(node, "bootargs-append", &l); ++ if (p != NULL && l > 0) ++ strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE)); + + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else From 9fe5516ee569046b2e038b352f593d9ad7f8659f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 22:20:55 +0200 Subject: [PATCH 45/82] ipq40xx: 5.10: drop upstreamed patches Drop patches that have been upstreamed in before 5.10. Signed-off-by: Robert Marko --- ...5.7-ARM-qcom-Add-support-for-IPQ40xx.patch | 42 - ...r-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch | 153 --- ...om-ipq4019-Add-SDHCI-controller-node.patch | 36 - ...om-Add-nodes-for-SMP-boot-in-IPQ40xx.patch | 71 -- ...RM-dts-qcom-add-gpio-ranges-property.patch | 119 --- ...om-ipq4019-fix-high-resolution-timer.patch | 33 - ...net-phy-mdio-add-IPQ4019-MDIO-driver.patch | 210 ---- ...2-ARM-dts-qcom-ipq4019-add-MDIO-node.patch | 57 - ...add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch | 31 - ....5-crypto-qce-switch-to-skcipher-API.patch | 993 ------------------ ...ce-fix-ctr-aes-qce-block-chunk-sizes.patch | 43 - ...crypto-qce-fix-xts-aes-qce-key-sizes.patch | 60 -- ...-save-a-sg-table-slot-for-result-buf.patch | 85 -- ....6-crypto-qce-update-the-skcipher-IV.patch | 31 - ...qce-initialize-fallback-only-for-AES.patch | 54 - ...e-allow-building-only-hashes-ciphers.patch | 419 -------- ...e-use-cryptlen-when-adding-extra-sgl.patch | 89 -- ...-use-AES-fallback-for-small-requests.patch | 113 -- ...-handle-AES-XTS-cases-that-qce-fails.patch | 59 -- ...-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch | 197 ---- .../0018-v5.9-pinctrl-msm-open-drain.patch | 81 -- ...d-spi-nor-Add-support-for-mx25r3235f.patch | 29 - 22 files changed, 3005 deletions(-) delete mode 100644 target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch delete mode 100644 target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch diff --git a/target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch b/target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch deleted file mode 100644 index 8aa71f360f..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch +++ /dev/null @@ -1,42 +0,0 @@ -From f125e2d4339dda6937865f975470b29c84714c9b Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Mon, 6 Jan 2020 14:57:15 +0100 -Subject: [PATCH] ARM: qcom: Add support for IPQ40xx - -Add support for the Qualcomm IPQ40xx SoC in Kconfig. -Also add its appropriate textofs. - -Signed-off-by: Christian Lamparter -Signed-off-by: John Crispin -Tested-by: Robert Marko -Cc: Luka Perkov -Signed-off-by: Arnd Bergmann ---- - arch/arm/Makefile | 1 + - arch/arm/mach-qcom/Kconfig | 5 +++++ - 2 files changed, 6 insertions(+) - ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -152,6 +152,7 @@ textofs-$(CONFIG_PM_H1940) := 0x001 - ifeq ($(CONFIG_ARCH_SA1100),y) - textofs-$(CONFIG_SA1111) := 0x00208000 - endif -+textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000 - textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 - textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 - textofs-$(CONFIG_ARCH_MESON) := 0x00208000 ---- a/arch/arm/mach-qcom/Kconfig -+++ b/arch/arm/mach-qcom/Kconfig -@@ -12,6 +12,11 @@ menuconfig ARCH_QCOM - - if ARCH_QCOM - -+config ARCH_IPQ40XX -+ bool "Enable support for IPQ40XX" -+ select CLKSRC_QCOM -+ select HAVE_ARM_ARCH_TIMER -+ - config ARCH_MSM8X60 - bool "Enable support for MSM8X60" - select CLKSRC_QCOM diff --git a/target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch b/target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch deleted file mode 100644 index aaf8c807ed..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 97043d292365ae39d62b54a6d79dff98d048b501 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 22 Jan 2020 12:44:14 +0100 -Subject: [PATCH] From ebf652b408200504194be32ad0a3f5bb49d6000a Mon Sep 17 - 00:00:00 2001 From: Robert Marko Date: Sun, 12 Jan - 2020 12:30:01 +0100 Subject: [PATCH] regulator: add IPQ4019 SDHCI VQMMC LDO - driver - -This introduces the IPQ4019 VQMMC LDO driver needed for -the SD/EMMC driver I/O level operation. -This will enable introducing SD/EMMC support for the built-in controller. - -Signed-off-by: Mantas Pucka -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20200112113003.11110-1-robert.marko@sartura.hr -Signed-off-by: Mark Brown ---- - drivers/regulator/Kconfig | 7 ++ - drivers/regulator/Makefile | 1 + - drivers/regulator/vqmmc-ipq4019-regulator.c | 101 ++++++++++++++++++++ - 3 files changed, 109 insertions(+) - create mode 100644 drivers/regulator/vqmmc-ipq4019-regulator.c - ---- a/drivers/regulator/Kconfig -+++ b/drivers/regulator/Kconfig -@@ -1077,6 +1077,13 @@ config REGULATOR_VEXPRESS - This driver provides support for voltage regulators available - on the ARM Ltd's Versatile Express platform. - -+config REGULATOR_VQMMC_IPQ4019 -+ tristate "IPQ4019 VQMMC SD LDO regulator support" -+ depends on ARCH_QCOM -+ help -+ This driver provides support for the VQMMC LDO I/0 -+ voltage regulator of the IPQ4019 SD/EMMC controller. -+ - config REGULATOR_WM831X - tristate "Wolfson Microelectronics WM831x PMIC regulators" - depends on MFD_WM831X ---- a/drivers/regulator/Makefile -+++ b/drivers/regulator/Makefile -@@ -132,6 +132,7 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-r - obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o - obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o - obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o -+obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o - obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o - obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o - obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o ---- /dev/null -+++ b/drivers/regulator/vqmmc-ipq4019-regulator.c -@@ -0,0 +1,101 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// -+// Copyright (c) 2019 Mantas Pucka -+// Copyright (c) 2019 Robert Marko -+// -+// Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static const unsigned int ipq4019_vmmc_voltages[] = { -+ 1500000, 1800000, 2500000, 3000000, -+}; -+ -+static const struct regulator_ops ipq4019_regulator_voltage_ops = { -+ .list_voltage = regulator_list_voltage_table, -+ .map_voltage = regulator_map_voltage_ascend, -+ .get_voltage_sel = regulator_get_voltage_sel_regmap, -+ .set_voltage_sel = regulator_set_voltage_sel_regmap, -+}; -+ -+static const struct regulator_desc vmmc_regulator = { -+ .name = "vmmcq", -+ .ops = &ipq4019_regulator_voltage_ops, -+ .type = REGULATOR_VOLTAGE, -+ .owner = THIS_MODULE, -+ .volt_table = ipq4019_vmmc_voltages, -+ .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages), -+ .vsel_reg = 0, -+ .vsel_mask = 0x3, -+}; -+ -+static const struct regmap_config ipq4019_vmmcq_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+}; -+ -+static int ipq4019_regulator_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct regulator_init_data *init_data; -+ struct regulator_config cfg = {}; -+ struct regulator_dev *rdev; -+ struct resource *res; -+ struct regmap *rmap; -+ void __iomem *base; -+ -+ init_data = of_get_regulator_init_data(dev, dev->of_node, -+ &vmmc_regulator); -+ if (!init_data) -+ return -EINVAL; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config); -+ if (IS_ERR(rmap)) -+ return PTR_ERR(rmap); -+ -+ cfg.dev = dev; -+ cfg.init_data = init_data; -+ cfg.of_node = dev->of_node; -+ cfg.regmap = rmap; -+ -+ rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg); -+ if (IS_ERR(rdev)) { -+ dev_err(dev, "Failed to register regulator: %ld\n", -+ PTR_ERR(rdev)); -+ return PTR_ERR(rdev); -+ } -+ platform_set_drvdata(pdev, rdev); -+ -+ return 0; -+} -+ -+static const struct of_device_id regulator_ipq4019_of_match[] = { -+ { .compatible = "qcom,vqmmc-ipq4019-regulator", }, -+ {}, -+}; -+ -+static struct platform_driver ipq4019_regulator_driver = { -+ .probe = ipq4019_regulator_probe, -+ .driver = { -+ .name = "vqmmc-ipq4019-regulator", -+ .of_match_table = of_match_ptr(regulator_ipq4019_of_match), -+ }, -+}; -+module_platform_driver(ipq4019_regulator_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Mantas Pucka "); -+MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator"); diff --git a/target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch b/target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch deleted file mode 100644 index 25fce8daf0..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 04b3b72b5b8fdb883bfdc619cb29b03641b1cc6a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 15 Aug 2019 19:28:23 +0200 -Subject: [PATCH] ARM: dts: qcom: ipq4019: Add SDHCI controller node - -IPQ4019 has a built in SD/eMMC controller which is supported by the -SDHCI MSM driver, by the "qcom,sdhci-msm-v4" binding. -So lets add the appropriate node for it. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -206,6 +206,18 @@ - interrupts = ; - }; - -+ sdhci: sdhci@7824900 { -+ compatible = "qcom,sdhci-msm-v4"; -+ reg = <0x7824900 0x11c>, <0x7824000 0x800>; -+ interrupts = , ; -+ interrupt-names = "hc_irq", "pwr_irq"; -+ bus-width = <8>; -+ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>, -+ <&gcc GCC_DCD_XO_CLK>; -+ clock-names = "core", "iface", "xo"; -+ status = "disabled"; -+ }; -+ - blsp_dma: dma@7884000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x07884000 0x23000>; diff --git a/target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch b/target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch deleted file mode 100644 index 3a4127febf..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 5e4548922009870a38bcf1d887317676d4e08f54 Mon Sep 17 00:00:00 2001 -From: Damir Franusic -Date: Thu, 21 Nov 2019 16:29:02 +0100 -Subject: [PATCH] ARM: dts: qcom: Add nodes for SMP boot in IPQ40xx - -Add missing nodes and properties to enable SMP -support on IPQ40xx devices. - -Booting without "saw_l2" node: - -[ 0.001400] CPU: Testing write buffer coherency: ok -[ 0.001856] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 -[ 0.060163] Setting up static identity map for 0x80300000 - 0x80300060 -[ 0.080140] rcu: Hierarchical SRCU implementation. -[ 0.120258] smp: Bringing up secondary CPUs ... -[ 0.200540] CPU1: failed to boot: -19 -[ 0.280689] CPU2: failed to boot: -19 -[ 0.360874] CPU3: failed to boot: -19 -[ 0.360966] smp: Brought up 1 node, 1 CPU -[ 0.360979] SMP: Total of 1 processors activated (96.00 BogoMIPS). -[ 0.360988] CPU: All CPU(s) started in SVC mode. - -Then, booting with "saw_l2" node present (this patch applied): - -[ 0.001450] CPU: Testing write buffer coherency: ok -[ 0.001904] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 -[ 0.060161] Setting up static identity map for 0x80300000 - 0x80300060 -[ 0.080137] rcu: Hierarchical SRCU implementation. -[ 0.120252] smp: Bringing up secondary CPUs ... -[ 0.200958] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 -[ 0.281091] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002 -[ 0.361264] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003 -[ 0.361430] smp: Brought up 1 node, 4 CPUs -[ 0.361460] SMP: Total of 4 processors activated (384.00 BogoMIPS). -[ 0.361469] CPU: All CPU(s) started in SVC mode. - -Signed-off-by: Damir Franusic -Cc: Luka Perkov -Cc: Robert Marko -Cc: Andy Gross -Cc: Rob Herring -Cc: linux-arm-msm@vger.kernel.org -Link: https://lore.kernel.org/r/20191121152902.21394-1-damir.franusic@gmail.com -Signed-off-by: Bjorn Andersson ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -102,6 +102,7 @@ - L2: l2-cache { - compatible = "cache"; - cache-level = <2>; -+ qcom,saw = <&saw_l2>; - }; - }; - -@@ -353,6 +354,12 @@ - regulator; - }; - -+ saw_l2: regulator@b012000 { -+ compatible = "qcom,saw2"; -+ reg = <0xb012000 0x1000>; -+ regulator; -+ }; -+ - blsp1_uart1: serial@78af000 { - compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; - reg = <0x78af000 0x200>; diff --git a/target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch b/target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch deleted file mode 100644 index 6922bc8ff3..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 8b99dc0922618062a1589ebd74df6108b4f9ac22 Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Wed, 8 Jan 2020 13:54:55 +0100 -Subject: [PATCH] ARM: dts: qcom: add gpio-ranges property - -This patch adds the gpio-ranges property to almost all of -the Qualcomm ARM platforms that utilize the pinctrl-msm -framework. - -The gpio-ranges property is part of the gpiolib subsystem. -As a result, the binding text is available in section -"2.1 gpio- and pin-controller interaction" of -Documentation/devicetree/bindings/gpio/gpio.txt - -For more information please see the patch titled: -"pinctrl: msm: fix gpio-hog related boot issues" from -this series. - -Reported-by: Sven Eckelmann -Tested-by: Sven Eckelmann [ipq4019] -Reviewed-by: Bjorn Andersson -Reviewed-by: Linus Walleij -Signed-off-by: Christian Lamparter -Tested-by: Robert Marko [ipq4019] -Cc: Luka Perkov -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20200108125455.308969-1-robert.marko@sartura.hr -Signed-off-by: Bjorn Andersson ---- - arch/arm/boot/dts/qcom-apq8064.dtsi | 1 + - arch/arm/boot/dts/qcom-apq8084.dtsi | 1 + - arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + - arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 + - arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 + - arch/arm/boot/dts/qcom-msm8660.dtsi | 1 + - arch/arm/boot/dts/qcom-msm8960.dtsi | 1 + - arch/arm/boot/dts/qcom-msm8974.dtsi | 1 + - 8 files changed, 8 insertions(+) - ---- a/arch/arm/boot/dts/qcom-apq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi -@@ -350,6 +350,7 @@ - reg = <0x800000 0x4000>; - - gpio-controller; -+ gpio-ranges = <&tlmm_pinmux 0 0 90>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; ---- a/arch/arm/boot/dts/qcom-apq8084.dtsi -+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi -@@ -401,6 +401,7 @@ - compatible = "qcom,apq8084-pinctrl"; - reg = <0xfd510000 0x4000>; - gpio-controller; -+ gpio-ranges = <&tlmm 0 0 147>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -201,6 +201,7 @@ - compatible = "qcom,ipq4019-pinctrl"; - reg = <0x01000000 0x300000>; - gpio-controller; -+ gpio-ranges = <&tlmm 0 0 100>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -119,6 +119,7 @@ - reg = <0x800000 0x4000>; - - gpio-controller; -+ gpio-ranges = <&qcom_pinmux 0 0 69>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; ---- a/arch/arm/boot/dts/qcom-mdm9615.dtsi -+++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi -@@ -128,6 +128,7 @@ - msmgpio: pinctrl@800000 { - compatible = "qcom,mdm9615-pinctrl"; - gpio-controller; -+ gpio-ranges = <&msmgpio 0 0 88>; - #gpio-cells = <2>; - interrupts = ; - interrupt-controller; ---- a/arch/arm/boot/dts/qcom-msm8660.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi -@@ -115,6 +115,7 @@ - reg = <0x800000 0x4000>; - - gpio-controller; -+ gpio-ranges = <&tlmm 0 0 173>; - #gpio-cells = <2>; - interrupts = <0 16 0x4>; - interrupt-controller; ---- a/arch/arm/boot/dts/qcom-msm8960.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi -@@ -107,6 +107,7 @@ - msmgpio: pinctrl@800000 { - compatible = "qcom,msm8960-pinctrl"; - gpio-controller; -+ gpio-ranges = <&msmgpio 0 0 152>; - #gpio-cells = <2>; - interrupts = <0 16 0x4>; - interrupt-controller; ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -707,6 +707,7 @@ - compatible = "qcom,msm8974-pinctrl"; - reg = <0xfd510000 0x4000>; - gpio-controller; -+ gpio-ranges = <&msmgpio 0 0 146>; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; diff --git a/target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch b/target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch deleted file mode 100644 index f82021f4cd..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 8acc36189dcaf4487d8c6ba7445948f39b1d248a Mon Sep 17 00:00:00 2001 -From: Abhishek Sahu -Date: Fri, 3 Apr 2020 13:40:40 +0200 -Subject: [PATCH] ARM: dts: qcom: ipq4019: fix high resolution timer - -Cherry-picked from CAF QSDK repo. -Original commit message: -The kernel is failing in switching the timer for high resolution -mode and clock source operates in 10ms resolution. The always-on -property needs to be given for timer device tree node to make -clock source working in 1ns resolution. - -Signed-off-by: Abhishek Sahu -Signed-off-by: Pavel Kubelun -Signed-off-by: Christian Lamparter -Tested-by: Robert Marko -Cc: Luka Perkov -Link: https://lore.kernel.org/r/20200403114040.349787-1-robert.marko@sartura.hr -Signed-off-by: Bjorn Andersson ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -166,6 +166,7 @@ - <1 4 0xf08>, - <1 1 0xf08>; - clock-frequency = <48000000>; -+ always-on; - }; - - soc { diff --git a/target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch b/target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch deleted file mode 100644 index d678f761f5..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch +++ /dev/null @@ -1,210 +0,0 @@ -From 466ed24fb22342f3ae1c10758a6a0c6a8c081b2d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 30 Apr 2020 11:07:05 +0200 -Subject: [PATCH] net: phy: mdio: add IPQ4019 MDIO driver - -This patch adds the driver for the MDIO interface -inside of Qualcomm IPQ40xx series SoC-s. - -Signed-off-by: Christian Lamparter -Signed-off-by: Robert Marko -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Cc: Luka Perkov -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 7 ++ - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mdio-ipq4019.c | 160 +++++++++++++++++++++++++++++++++ - 3 files changed, 168 insertions(+) - create mode 100644 drivers/net/phy/mdio-ipq4019.c - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -156,6 +156,13 @@ config MDIO_I2C - - This is library mode. - -+config MDIO_IPQ4019 -+ tristate "Qualcomm IPQ4019 MDIO interface support" -+ depends on HAS_IOMEM && OF_MDIO -+ help -+ This driver supports the MDIO interface found in Qualcomm -+ IPQ40xx series Soc-s. -+ - config MDIO_MOXART - tristate "MOXA ART MDIO interface support" - depends on ARCH_MOXART || COMPILE_TEST ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium - obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o - obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o - obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o -+obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o - obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o - obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o - obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o ---- /dev/null -+++ b/drivers/net/phy/mdio-ipq4019.c -@@ -0,0 +1,160 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -+/* Copyright (c) 2015, The Linux Foundation. All rights reserved. */ -+/* Copyright (c) 2020 Sartura Ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MDIO_ADDR_REG 0x44 -+#define MDIO_DATA_WRITE_REG 0x48 -+#define MDIO_DATA_READ_REG 0x4c -+#define MDIO_CMD_REG 0x50 -+#define MDIO_CMD_ACCESS_BUSY BIT(16) -+#define MDIO_CMD_ACCESS_START BIT(8) -+#define MDIO_CMD_ACCESS_CODE_READ 0 -+#define MDIO_CMD_ACCESS_CODE_WRITE 1 -+ -+#define ipq4019_MDIO_TIMEOUT 10000 -+#define ipq4019_MDIO_SLEEP 10 -+ -+struct ipq4019_mdio_data { -+ void __iomem *membase; -+}; -+ -+static int ipq4019_mdio_wait_busy(struct mii_bus *bus) -+{ -+ struct ipq4019_mdio_data *priv = bus->priv; -+ unsigned int busy; -+ -+ return readl_poll_timeout(priv->membase + MDIO_CMD_REG, busy, -+ (busy & MDIO_CMD_ACCESS_BUSY) == 0, -+ ipq4019_MDIO_SLEEP, ipq4019_MDIO_TIMEOUT); -+} -+ -+static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -+{ -+ struct ipq4019_mdio_data *priv = bus->priv; -+ unsigned int cmd; -+ -+ /* Reject clause 45 */ -+ if (regnum & MII_ADDR_C45) -+ return -EOPNOTSUPP; -+ -+ if (ipq4019_mdio_wait_busy(bus)) -+ return -ETIMEDOUT; -+ -+ /* issue the phy address and reg */ -+ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); -+ -+ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ; -+ -+ /* issue read command */ -+ writel(cmd, priv->membase + MDIO_CMD_REG); -+ -+ /* Wait read complete */ -+ if (ipq4019_mdio_wait_busy(bus)) -+ return -ETIMEDOUT; -+ -+ /* Read and return data */ -+ return readl(priv->membase + MDIO_DATA_READ_REG); -+} -+ -+static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum, -+ u16 value) -+{ -+ struct ipq4019_mdio_data *priv = bus->priv; -+ unsigned int cmd; -+ -+ /* Reject clause 45 */ -+ if (regnum & MII_ADDR_C45) -+ return -EOPNOTSUPP; -+ -+ if (ipq4019_mdio_wait_busy(bus)) -+ return -ETIMEDOUT; -+ -+ /* issue the phy address and reg */ -+ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); -+ -+ /* issue write data */ -+ writel(value, priv->membase + MDIO_DATA_WRITE_REG); -+ -+ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE; -+ /* issue write command */ -+ writel(cmd, priv->membase + MDIO_CMD_REG); -+ -+ /* Wait write complete */ -+ if (ipq4019_mdio_wait_busy(bus)) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+static int ipq4019_mdio_probe(struct platform_device *pdev) -+{ -+ struct ipq4019_mdio_data *priv; -+ struct mii_bus *bus; -+ int ret; -+ -+ bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); -+ if (!bus) -+ return -ENOMEM; -+ -+ priv = bus->priv; -+ -+ priv->membase = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(priv->membase)) -+ return PTR_ERR(priv->membase); -+ -+ bus->name = "ipq4019_mdio"; -+ bus->read = ipq4019_mdio_read; -+ bus->write = ipq4019_mdio_write; -+ bus->parent = &pdev->dev; -+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id); -+ -+ ret = of_mdiobus_register(bus, pdev->dev.of_node); -+ if (ret) { -+ dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); -+ return ret; -+ } -+ -+ platform_set_drvdata(pdev, bus); -+ -+ return 0; -+} -+ -+static int ipq4019_mdio_remove(struct platform_device *pdev) -+{ -+ struct mii_bus *bus = platform_get_drvdata(pdev); -+ -+ mdiobus_unregister(bus); -+ -+ return 0; -+} -+ -+static const struct of_device_id ipq4019_mdio_dt_ids[] = { -+ { .compatible = "qcom,ipq4019-mdio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids); -+ -+static struct platform_driver ipq4019_mdio_driver = { -+ .probe = ipq4019_mdio_probe, -+ .remove = ipq4019_mdio_remove, -+ .driver = { -+ .name = "ipq4019-mdio", -+ .of_match_table = ipq4019_mdio_dt_ids, -+ }, -+}; -+ -+module_platform_driver(ipq4019_mdio_driver); -+ -+MODULE_DESCRIPTION("ipq4019 MDIO interface driver"); -+MODULE_AUTHOR("Qualcomm Atheros"); -+MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch b/target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch deleted file mode 100644 index 1976686e8f..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 9c8c0f70ec6fdac2398632c723c48277be09b7c0 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 30 Apr 2020 11:07:07 +0200 -Subject: [PATCH] ARM: dts: qcom: ipq4019: add MDIO node - -This patch adds the necessary MDIO interface node -to the Qualcomm IPQ4019 DTSI. - -Built-in QCA8337N switch is managed using it, -and since we have a driver for it lets add it. - -Signed-off-by: Christian Lamparter -Signed-off-by: Robert Marko -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Cc: Luka Perkov -Signed-off-by: David S. Miller ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -577,5 +577,33 @@ - "legacy"; - status = "disabled"; - }; -+ -+ mdio: mdio@90000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,ipq4019-mdio"; -+ reg = <0x90000 0x64>; -+ status = "disabled"; -+ -+ ethphy0: ethernet-phy@0 { -+ reg = <0>; -+ }; -+ -+ ethphy1: ethernet-phy@1 { -+ reg = <1>; -+ }; -+ -+ ethphy2: ethernet-phy@2 { -+ reg = <2>; -+ }; -+ -+ ethphy3: ethernet-phy@3 { -+ reg = <3>; -+ }; -+ -+ ethphy4: ethernet-phy@4 { -+ reg = <4>; -+ }; -+ }; - }; - }; diff --git a/target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch b/target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch deleted file mode 100644 index 415d6fff99..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Eneas U de Queiroz -Subject: [PATCH] crypto: qce - add CRYPTO_ALG_KERN_DRIVER_ONLY flag - -Set the CRYPTO_ALG_KERN_DRIVER_ONLY flag to all algorithms exposed by -the qce driver, since they are all hardware accelerated, accessible -through a kernel driver only, and not available directly to userspace. - -Signed-off-by: Eneas U de Queiroz - ---- a/drivers/crypto/qce/ablkcipher.c -+++ b/drivers/crypto/qce/ablkcipher.c -@@ -380,7 +380,7 @@ static int qce_ablkcipher_register_one(c - - alg->cra_priority = 300; - alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | -- CRYPTO_ALG_NEED_FALLBACK; -+ CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; - alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); - alg->cra_alignmask = 0; - alg->cra_type = &crypto_ablkcipher_type; ---- a/drivers/crypto/qce/sha.c -+++ b/drivers/crypto/qce/sha.c -@@ -495,7 +495,7 @@ static int qce_ahash_register_one(const - base = &alg->halg.base; - base->cra_blocksize = def->blocksize; - base->cra_priority = 300; -- base->cra_flags = CRYPTO_ALG_ASYNC; -+ base->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; - base->cra_ctxsize = sizeof(struct qce_sha_ctx); - base->cra_alignmask = 0; - base->cra_module = THIS_MODULE; diff --git a/target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch b/target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch deleted file mode 100644 index 4dcb942150..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch +++ /dev/null @@ -1,993 +0,0 @@ -From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel -Date: Tue, 5 Nov 2019 14:28:17 +0100 -Subject: [PATCH] crypto: qce - switch to skcipher API - -Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface") -dated 20 august 2015 introduced the new skcipher API which is supposed to -replace both blkcipher and ablkcipher. While all consumers of the API have -been converted long ago, some producers of the ablkcipher remain, forcing -us to keep the ablkcipher support routines alive, along with the matching -code to expose [a]blkciphers via the skcipher API. - -So switch this driver to the skcipher API, allowing us to finally drop the -blkcipher code in the near future. - -Reviewed-by: Stanimir Varbanov -Signed-off-by: Ard Biesheuvel -Backported-to-4.19-by: Eneas U de Queiroz - ---- a/drivers/crypto/qce/Makefile -+++ b/drivers/crypto/qce/Makefile -@@ -4,4 +4,4 @@ qcrypto-objs := core.o \ - common.o \ - dma.o \ - sha.o \ -- ablkcipher.o -+ skcipher.o ---- a/drivers/crypto/qce/cipher.h -+++ b/drivers/crypto/qce/cipher.h -@@ -45,12 +45,12 @@ struct qce_cipher_reqctx { - unsigned int cryptlen; - }; - --static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm) -+static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm) - { -- struct crypto_alg *alg = tfm->__crt_alg; -- return container_of(alg, struct qce_alg_template, alg.crypto); -+ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); -+ return container_of(alg, struct qce_alg_template, alg.skcipher); - } - --extern const struct qce_algo_ops ablkcipher_ops; -+extern const struct qce_algo_ops skcipher_ops; - - #endif /* _CIPHER_H_ */ ---- a/drivers/crypto/qce/common.c -+++ b/drivers/crypto/qce/common.c -@@ -304,13 +304,13 @@ go_proc: - return 0; - } - --static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req, -+static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, - u32 totallen, u32 offset) - { -- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); -- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); -+ struct skcipher_request *req = skcipher_request_cast(async_req); -+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); - struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm); -- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); -+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); - struct qce_device *qce = tmpl->qce; - __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0}; - __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0}; -@@ -389,8 +389,8 @@ int qce_start(struct crypto_async_reques - u32 offset) - { - switch (type) { -- case CRYPTO_ALG_TYPE_ABLKCIPHER: -- return qce_setup_regs_ablkcipher(async_req, totallen, offset); -+ case CRYPTO_ALG_TYPE_SKCIPHER: -+ return qce_setup_regs_skcipher(async_req, totallen, offset); - case CRYPTO_ALG_TYPE_AHASH: - return qce_setup_regs_ahash(async_req, totallen, offset); - default: ---- a/drivers/crypto/qce/common.h -+++ b/drivers/crypto/qce/common.h -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - /* key size in bytes */ - #define QCE_SHA_HMAC_KEY_SIZE 64 -@@ -79,7 +80,7 @@ struct qce_alg_template { - unsigned long alg_flags; - const u32 *std_iv; - union { -- struct crypto_alg crypto; -+ struct skcipher_alg skcipher; - struct ahash_alg ahash; - } alg; - struct qce_device *qce; ---- a/drivers/crypto/qce/core.c -+++ b/drivers/crypto/qce/core.c -@@ -22,7 +22,7 @@ - #define QCE_QUEUE_LENGTH 1 - - static const struct qce_algo_ops *qce_ops[] = { -- &ablkcipher_ops, -+ &skcipher_ops, - &ahash_ops, - }; - ---- a/drivers/crypto/qce/ablkcipher.c -+++ /dev/null -@@ -1,440 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0-only --/* -- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. -- */ -- --#include --#include --#include --#include --#include --#include -- --#include "cipher.h" -- --static LIST_HEAD(ablkcipher_algs); -- --static void qce_ablkcipher_done(void *data) --{ -- struct crypto_async_request *async_req = data; -- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); -- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); -- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); -- struct qce_device *qce = tmpl->qce; -- enum dma_data_direction dir_src, dir_dst; -- u32 status; -- int error; -- bool diff_dst; -- -- diff_dst = (req->src != req->dst) ? true : false; -- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; -- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; -- -- error = qce_dma_terminate_all(&qce->dma); -- if (error) -- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n", -- error); -- -- if (diff_dst) -- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); -- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); -- -- sg_free_table(&rctx->dst_tbl); -- -- error = qce_check_status(qce, &status); -- if (error < 0) -- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status); -- -- qce->async_req_done(tmpl->qce, error); --} -- --static int --qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) --{ -- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); -- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); -- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); -- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); -- struct qce_device *qce = tmpl->qce; -- enum dma_data_direction dir_src, dir_dst; -- struct scatterlist *sg; -- bool diff_dst; -- gfp_t gfp; -- int ret; -- -- rctx->iv = req->info; -- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher); -- rctx->cryptlen = req->nbytes; -- -- diff_dst = (req->src != req->dst) ? true : false; -- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; -- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; -- -- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes); -- if (diff_dst) -- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); -- else -- rctx->dst_nents = rctx->src_nents; -- if (rctx->src_nents < 0) { -- dev_err(qce->dev, "Invalid numbers of src SG.\n"); -- return rctx->src_nents; -- } -- if (rctx->dst_nents < 0) { -- dev_err(qce->dev, "Invalid numbers of dst SG.\n"); -- return -rctx->dst_nents; -- } -- -- rctx->dst_nents += 1; -- -- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -- GFP_KERNEL : GFP_ATOMIC; -- -- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); -- if (ret) -- return ret; -- -- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); -- -- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); -- if (IS_ERR(sg)) { -- ret = PTR_ERR(sg); -- goto error_free; -- } -- -- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); -- if (IS_ERR(sg)) { -- ret = PTR_ERR(sg); -- goto error_free; -- } -- -- sg_mark_end(sg); -- rctx->dst_sg = rctx->dst_tbl.sgl; -- -- ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); -- if (ret < 0) -- goto error_free; -- -- if (diff_dst) { -- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); -- if (ret < 0) -- goto error_unmap_dst; -- rctx->src_sg = req->src; -- } else { -- rctx->src_sg = rctx->dst_sg; -- } -- -- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, -- rctx->dst_sg, rctx->dst_nents, -- qce_ablkcipher_done, async_req); -- if (ret) -- goto error_unmap_src; -- -- qce_dma_issue_pending(&qce->dma); -- -- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0); -- if (ret) -- goto error_terminate; -- -- return 0; -- --error_terminate: -- qce_dma_terminate_all(&qce->dma); --error_unmap_src: -- if (diff_dst) -- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); --error_unmap_dst: -- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); --error_free: -- sg_free_table(&rctx->dst_tbl); -- return ret; --} -- --static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, -- unsigned int keylen) --{ -- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); -- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -- int ret; -- -- if (!key || !keylen) -- return -EINVAL; -- -- switch (keylen) { -- case AES_KEYSIZE_128: -- case AES_KEYSIZE_256: -- break; -- default: -- goto fallback; -- } -- -- ctx->enc_keylen = keylen; -- memcpy(ctx->enc_key, key, keylen); -- return 0; --fallback: -- ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); -- if (!ret) -- ctx->enc_keylen = keylen; -- return ret; --} -- --static int qce_des_setkey(struct crypto_ablkcipher *ablk, const u8 *key, -- unsigned int keylen) --{ -- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); -- int err; -- -- err = verify_ablkcipher_des_key(ablk, key); -- if (err) -- return err; -- -- ctx->enc_keylen = keylen; -- memcpy(ctx->enc_key, key, keylen); -- return 0; --} -- --static int qce_des3_setkey(struct crypto_ablkcipher *ablk, const u8 *key, -- unsigned int keylen) --{ -- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); -- int err; -- -- err = verify_ablkcipher_des3_key(ablk, key); -- if (err) -- return err; -- -- ctx->enc_keylen = keylen; -- memcpy(ctx->enc_key, key, keylen); -- return 0; --} -- --static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) --{ -- struct crypto_tfm *tfm = -- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); -- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); -- struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); -- int ret; -- -- rctx->flags = tmpl->alg_flags; -- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; -- -- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && -- ctx->enc_keylen != AES_KEYSIZE_256) { -- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); -- -- skcipher_request_set_sync_tfm(subreq, ctx->fallback); -- skcipher_request_set_callback(subreq, req->base.flags, -- NULL, NULL); -- skcipher_request_set_crypt(subreq, req->src, req->dst, -- req->nbytes, req->info); -- ret = encrypt ? crypto_skcipher_encrypt(subreq) : -- crypto_skcipher_decrypt(subreq); -- skcipher_request_zero(subreq); -- return ret; -- } -- -- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); --} -- --static int qce_ablkcipher_encrypt(struct ablkcipher_request *req) --{ -- return qce_ablkcipher_crypt(req, 1); --} -- --static int qce_ablkcipher_decrypt(struct ablkcipher_request *req) --{ -- return qce_ablkcipher_crypt(req, 0); --} -- --static int qce_ablkcipher_init(struct crypto_tfm *tfm) --{ -- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -- -- memset(ctx, 0, sizeof(*ctx)); -- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx); -- -- ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(tfm), -- 0, CRYPTO_ALG_NEED_FALLBACK); -- return PTR_ERR_OR_ZERO(ctx->fallback); --} -- --static void qce_ablkcipher_exit(struct crypto_tfm *tfm) --{ -- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -- -- crypto_free_sync_skcipher(ctx->fallback); --} -- --struct qce_ablkcipher_def { -- unsigned long flags; -- const char *name; -- const char *drv_name; -- unsigned int blocksize; -- unsigned int ivsize; -- unsigned int min_keysize; -- unsigned int max_keysize; --}; -- --static const struct qce_ablkcipher_def ablkcipher_def[] = { -- { -- .flags = QCE_ALG_AES | QCE_MODE_ECB, -- .name = "ecb(aes)", -- .drv_name = "ecb-aes-qce", -- .blocksize = AES_BLOCK_SIZE, -- .ivsize = AES_BLOCK_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_AES | QCE_MODE_CBC, -- .name = "cbc(aes)", -- .drv_name = "cbc-aes-qce", -- .blocksize = AES_BLOCK_SIZE, -- .ivsize = AES_BLOCK_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_AES | QCE_MODE_CTR, -- .name = "ctr(aes)", -- .drv_name = "ctr-aes-qce", -- .blocksize = AES_BLOCK_SIZE, -- .ivsize = AES_BLOCK_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_AES | QCE_MODE_XTS, -- .name = "xts(aes)", -- .drv_name = "xts-aes-qce", -- .blocksize = AES_BLOCK_SIZE, -- .ivsize = AES_BLOCK_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_DES | QCE_MODE_ECB, -- .name = "ecb(des)", -- .drv_name = "ecb-des-qce", -- .blocksize = DES_BLOCK_SIZE, -- .ivsize = 0, -- .min_keysize = DES_KEY_SIZE, -- .max_keysize = DES_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_DES | QCE_MODE_CBC, -- .name = "cbc(des)", -- .drv_name = "cbc-des-qce", -- .blocksize = DES_BLOCK_SIZE, -- .ivsize = DES_BLOCK_SIZE, -- .min_keysize = DES_KEY_SIZE, -- .max_keysize = DES_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_3DES | QCE_MODE_ECB, -- .name = "ecb(des3_ede)", -- .drv_name = "ecb-3des-qce", -- .blocksize = DES3_EDE_BLOCK_SIZE, -- .ivsize = 0, -- .min_keysize = DES3_EDE_KEY_SIZE, -- .max_keysize = DES3_EDE_KEY_SIZE, -- }, -- { -- .flags = QCE_ALG_3DES | QCE_MODE_CBC, -- .name = "cbc(des3_ede)", -- .drv_name = "cbc-3des-qce", -- .blocksize = DES3_EDE_BLOCK_SIZE, -- .ivsize = DES3_EDE_BLOCK_SIZE, -- .min_keysize = DES3_EDE_KEY_SIZE, -- .max_keysize = DES3_EDE_KEY_SIZE, -- }, --}; -- --static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def, -- struct qce_device *qce) --{ -- struct qce_alg_template *tmpl; -- struct crypto_alg *alg; -- int ret; -- -- tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); -- if (!tmpl) -- return -ENOMEM; -- -- alg = &tmpl->alg.crypto; -- -- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); -- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", -- def->drv_name); -- -- alg->cra_blocksize = def->blocksize; -- alg->cra_ablkcipher.ivsize = def->ivsize; -- alg->cra_ablkcipher.min_keysize = def->min_keysize; -- alg->cra_ablkcipher.max_keysize = def->max_keysize; -- alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? qce_des3_setkey : -- IS_DES(def->flags) ? qce_des_setkey : -- qce_ablkcipher_setkey; -- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt; -- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt; -- -- alg->cra_priority = 300; -- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | -- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; -- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); -- alg->cra_alignmask = 0; -- alg->cra_type = &crypto_ablkcipher_type; -- alg->cra_module = THIS_MODULE; -- alg->cra_init = qce_ablkcipher_init; -- alg->cra_exit = qce_ablkcipher_exit; -- -- INIT_LIST_HEAD(&tmpl->entry); -- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER; -- tmpl->alg_flags = def->flags; -- tmpl->qce = qce; -- -- ret = crypto_register_alg(alg); -- if (ret) { -- kfree(tmpl); -- dev_err(qce->dev, "%s registration failed\n", alg->cra_name); -- return ret; -- } -- -- list_add_tail(&tmpl->entry, &ablkcipher_algs); -- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name); -- return 0; --} -- --static void qce_ablkcipher_unregister(struct qce_device *qce) --{ -- struct qce_alg_template *tmpl, *n; -- -- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) { -- crypto_unregister_alg(&tmpl->alg.crypto); -- list_del(&tmpl->entry); -- kfree(tmpl); -- } --} -- --static int qce_ablkcipher_register(struct qce_device *qce) --{ -- int ret, i; -- -- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) { -- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce); -- if (ret) -- goto err; -- } -- -- return 0; --err: -- qce_ablkcipher_unregister(qce); -- return ret; --} -- --const struct qce_algo_ops ablkcipher_ops = { -- .type = CRYPTO_ALG_TYPE_ABLKCIPHER, -- .register_algs = qce_ablkcipher_register, -- .unregister_algs = qce_ablkcipher_unregister, -- .async_req_handle = qce_ablkcipher_async_req_handle, --}; ---- /dev/null -+++ b/drivers/crypto/qce/skcipher.c -@@ -0,0 +1,440 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cipher.h" -+ -+static LIST_HEAD(skcipher_algs); -+ -+static void qce_skcipher_done(void *data) -+{ -+ struct crypto_async_request *async_req = data; -+ struct skcipher_request *req = skcipher_request_cast(async_req); -+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); -+ struct qce_device *qce = tmpl->qce; -+ enum dma_data_direction dir_src, dir_dst; -+ u32 status; -+ int error; -+ bool diff_dst; -+ -+ diff_dst = (req->src != req->dst) ? true : false; -+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; -+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; -+ -+ error = qce_dma_terminate_all(&qce->dma); -+ if (error) -+ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", -+ error); -+ -+ if (diff_dst) -+ dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); -+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); -+ -+ sg_free_table(&rctx->dst_tbl); -+ -+ error = qce_check_status(qce, &status); -+ if (error < 0) -+ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); -+ -+ qce->async_req_done(tmpl->qce, error); -+} -+ -+static int -+qce_skcipher_async_req_handle(struct crypto_async_request *async_req) -+{ -+ struct skcipher_request *req = skcipher_request_cast(async_req); -+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); -+ struct qce_device *qce = tmpl->qce; -+ enum dma_data_direction dir_src, dir_dst; -+ struct scatterlist *sg; -+ bool diff_dst; -+ gfp_t gfp; -+ int ret; -+ -+ rctx->iv = req->iv; -+ rctx->ivsize = crypto_skcipher_ivsize(skcipher); -+ rctx->cryptlen = req->cryptlen; -+ -+ diff_dst = (req->src != req->dst) ? true : false; -+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; -+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; -+ -+ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); -+ if (diff_dst) -+ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); -+ else -+ rctx->dst_nents = rctx->src_nents; -+ if (rctx->src_nents < 0) { -+ dev_err(qce->dev, "Invalid numbers of src SG.\n"); -+ return rctx->src_nents; -+ } -+ if (rctx->dst_nents < 0) { -+ dev_err(qce->dev, "Invalid numbers of dst SG.\n"); -+ return -rctx->dst_nents; -+ } -+ -+ rctx->dst_nents += 1; -+ -+ gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ -+ ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); -+ if (ret) -+ return ret; -+ -+ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); -+ -+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); -+ if (IS_ERR(sg)) { -+ ret = PTR_ERR(sg); -+ goto error_free; -+ } -+ -+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); -+ if (IS_ERR(sg)) { -+ ret = PTR_ERR(sg); -+ goto error_free; -+ } -+ -+ sg_mark_end(sg); -+ rctx->dst_sg = rctx->dst_tbl.sgl; -+ -+ ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); -+ if (ret < 0) -+ goto error_free; -+ -+ if (diff_dst) { -+ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); -+ if (ret < 0) -+ goto error_unmap_dst; -+ rctx->src_sg = req->src; -+ } else { -+ rctx->src_sg = rctx->dst_sg; -+ } -+ -+ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, -+ rctx->dst_sg, rctx->dst_nents, -+ qce_skcipher_done, async_req); -+ if (ret) -+ goto error_unmap_src; -+ -+ qce_dma_issue_pending(&qce->dma); -+ -+ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); -+ if (ret) -+ goto error_terminate; -+ -+ return 0; -+ -+error_terminate: -+ qce_dma_terminate_all(&qce->dma); -+error_unmap_src: -+ if (diff_dst) -+ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); -+error_unmap_dst: -+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); -+error_free: -+ sg_free_table(&rctx->dst_tbl); -+ return ret; -+} -+ -+static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, -+ unsigned int keylen) -+{ -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); -+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ if (!key || !keylen) -+ return -EINVAL; -+ -+ switch (keylen) { -+ case AES_KEYSIZE_128: -+ case AES_KEYSIZE_256: -+ break; -+ default: -+ goto fallback; -+ } -+ -+ ctx->enc_keylen = keylen; -+ memcpy(ctx->enc_key, key, keylen); -+ return 0; -+fallback: -+ ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); -+ if (!ret) -+ ctx->enc_keylen = keylen; -+ return ret; -+} -+ -+static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, -+ unsigned int keylen) -+{ -+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); -+ int err; -+ -+ err = verify_skcipher_des_key(ablk, key); -+ if (err) -+ return err; -+ -+ ctx->enc_keylen = keylen; -+ memcpy(ctx->enc_key, key, keylen); -+ return 0; -+} -+ -+static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, -+ unsigned int keylen) -+{ -+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); -+ int err; -+ -+ err = verify_skcipher_des3_key(ablk, key); -+ if (err) -+ return err; -+ -+ ctx->enc_keylen = keylen; -+ memcpy(ctx->enc_key, key, keylen); -+ return 0; -+} -+ -+static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) -+{ -+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); -+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); -+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); -+ int ret; -+ -+ rctx->flags = tmpl->alg_flags; -+ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; -+ -+ if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && -+ ctx->enc_keylen != AES_KEYSIZE_256) { -+ SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); -+ -+ skcipher_request_set_sync_tfm(subreq, ctx->fallback); -+ skcipher_request_set_callback(subreq, req->base.flags, -+ NULL, NULL); -+ skcipher_request_set_crypt(subreq, req->src, req->dst, -+ req->cryptlen, req->iv); -+ ret = encrypt ? crypto_skcipher_encrypt(subreq) : -+ crypto_skcipher_decrypt(subreq); -+ skcipher_request_zero(subreq); -+ return ret; -+ } -+ -+ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); -+} -+ -+static int qce_skcipher_encrypt(struct skcipher_request *req) -+{ -+ return qce_skcipher_crypt(req, 1); -+} -+ -+static int qce_skcipher_decrypt(struct skcipher_request *req) -+{ -+ return qce_skcipher_crypt(req, 0); -+} -+ -+static int qce_skcipher_init(struct crypto_skcipher *tfm) -+{ -+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); -+ -+ memset(ctx, 0, sizeof(*ctx)); -+ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); -+ -+ ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), -+ 0, CRYPTO_ALG_NEED_FALLBACK); -+ return PTR_ERR_OR_ZERO(ctx->fallback); -+} -+ -+static void qce_skcipher_exit(struct crypto_skcipher *tfm) -+{ -+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); -+ -+ crypto_free_sync_skcipher(ctx->fallback); -+} -+ -+struct qce_skcipher_def { -+ unsigned long flags; -+ const char *name; -+ const char *drv_name; -+ unsigned int blocksize; -+ unsigned int ivsize; -+ unsigned int min_keysize; -+ unsigned int max_keysize; -+}; -+ -+static const struct qce_skcipher_def skcipher_def[] = { -+ { -+ .flags = QCE_ALG_AES | QCE_MODE_ECB, -+ .name = "ecb(aes)", -+ .drv_name = "ecb-aes-qce", -+ .blocksize = AES_BLOCK_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_AES | QCE_MODE_CBC, -+ .name = "cbc(aes)", -+ .drv_name = "cbc-aes-qce", -+ .blocksize = AES_BLOCK_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_AES | QCE_MODE_CTR, -+ .name = "ctr(aes)", -+ .drv_name = "ctr-aes-qce", -+ .blocksize = AES_BLOCK_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_AES | QCE_MODE_XTS, -+ .name = "xts(aes)", -+ .drv_name = "xts-aes-qce", -+ .blocksize = AES_BLOCK_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_DES | QCE_MODE_ECB, -+ .name = "ecb(des)", -+ .drv_name = "ecb-des-qce", -+ .blocksize = DES_BLOCK_SIZE, -+ .ivsize = 0, -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_DES | QCE_MODE_CBC, -+ .name = "cbc(des)", -+ .drv_name = "cbc-des-qce", -+ .blocksize = DES_BLOCK_SIZE, -+ .ivsize = DES_BLOCK_SIZE, -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_3DES | QCE_MODE_ECB, -+ .name = "ecb(des3_ede)", -+ .drv_name = "ecb-3des-qce", -+ .blocksize = DES3_EDE_BLOCK_SIZE, -+ .ivsize = 0, -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ }, -+ { -+ .flags = QCE_ALG_3DES | QCE_MODE_CBC, -+ .name = "cbc(des3_ede)", -+ .drv_name = "cbc-3des-qce", -+ .blocksize = DES3_EDE_BLOCK_SIZE, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ }, -+}; -+ -+static int qce_skcipher_register_one(const struct qce_skcipher_def *def, -+ struct qce_device *qce) -+{ -+ struct qce_alg_template *tmpl; -+ struct skcipher_alg *alg; -+ int ret; -+ -+ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); -+ if (!tmpl) -+ return -ENOMEM; -+ -+ alg = &tmpl->alg.skcipher; -+ -+ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); -+ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", -+ def->drv_name); -+ -+ alg->base.cra_blocksize = def->blocksize; -+ alg->ivsize = def->ivsize; -+ alg->min_keysize = def->min_keysize; -+ alg->max_keysize = def->max_keysize; -+ alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : -+ IS_DES(def->flags) ? qce_des_setkey : -+ qce_skcipher_setkey; -+ alg->encrypt = qce_skcipher_encrypt; -+ alg->decrypt = qce_skcipher_decrypt; -+ -+ alg->base.cra_priority = 300; -+ alg->base.cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK | -+ CRYPTO_ALG_KERN_DRIVER_ONLY; -+ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); -+ alg->base.cra_alignmask = 0; -+ alg->base.cra_module = THIS_MODULE; -+ -+ alg->init = qce_skcipher_init; -+ alg->exit = qce_skcipher_exit; -+ -+ INIT_LIST_HEAD(&tmpl->entry); -+ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; -+ tmpl->alg_flags = def->flags; -+ tmpl->qce = qce; -+ -+ ret = crypto_register_skcipher(alg); -+ if (ret) { -+ kfree(tmpl); -+ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); -+ return ret; -+ } -+ -+ list_add_tail(&tmpl->entry, &skcipher_algs); -+ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); -+ return 0; -+} -+ -+static void qce_skcipher_unregister(struct qce_device *qce) -+{ -+ struct qce_alg_template *tmpl, *n; -+ -+ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { -+ crypto_unregister_skcipher(&tmpl->alg.skcipher); -+ list_del(&tmpl->entry); -+ kfree(tmpl); -+ } -+} -+ -+static int qce_skcipher_register(struct qce_device *qce) -+{ -+ int ret, i; -+ -+ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { -+ ret = qce_skcipher_register_one(&skcipher_def[i], qce); -+ if (ret) -+ goto err; -+ } -+ -+ return 0; -+err: -+ qce_skcipher_unregister(qce); -+ return ret; -+} -+ -+const struct qce_algo_ops skcipher_ops = { -+ .type = CRYPTO_ALG_TYPE_SKCIPHER, -+ .register_algs = qce_skcipher_register, -+ .unregister_algs = qce_skcipher_unregister, -+ .async_req_handle = qce_skcipher_async_req_handle, -+}; diff --git a/target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch b/target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch deleted file mode 100644 index ac4f163f4a..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch +++ /dev/null @@ -1,43 +0,0 @@ -From bb5c863b3d3cbd10e80b2ebf409934a091058f54 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 20 Dec 2019 16:02:13 -0300 -Subject: [PATCH 02/11] crypto: qce - fix ctr-aes-qce block, chunk sizes - -Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher, -adding the definition for chucksize instead, where the underlying block -size belongs. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/skcipher.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -270,6 +270,7 @@ struct qce_skcipher_def { - const char *name; - const char *drv_name; - unsigned int blocksize; -+ unsigned int chunksize; - unsigned int ivsize; - unsigned int min_keysize; - unsigned int max_keysize; -@@ -298,7 +299,8 @@ static const struct qce_skcipher_def skc - .flags = QCE_ALG_AES | QCE_MODE_CTR, - .name = "ctr(aes)", - .drv_name = "ctr-aes-qce", -- .blocksize = AES_BLOCK_SIZE, -+ .blocksize = 1, -+ .chunksize = AES_BLOCK_SIZE, - .ivsize = AES_BLOCK_SIZE, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, -@@ -368,6 +370,7 @@ static int qce_skcipher_register_one(con - def->drv_name); - - alg->base.cra_blocksize = def->blocksize; -+ alg->chunksize = def->chunksize; - alg->ivsize = def->ivsize; - alg->min_keysize = def->min_keysize; - alg->max_keysize = def->max_keysize; diff --git a/target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch b/target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch deleted file mode 100644 index 4dcf1ac726..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 7de4c2bd196f111e39cc60f6197654aff23ba2b4 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 20 Dec 2019 16:02:14 -0300 -Subject: [PATCH 03/11] crypto: qce - fix xts-aes-qce key sizes - -XTS-mode uses two keys, so the keysizes should be doubled in -skcipher_def, and halved when checking if it is AES-128/192/256. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/skcipher.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -154,12 +154,13 @@ static int qce_skcipher_setkey(struct cr - { - struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); - struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; - int ret; - - if (!key || !keylen) - return -EINVAL; - -- switch (keylen) { -+ switch (IS_XTS(flags) ? keylen >> 1 : keylen) { - case AES_KEYSIZE_128: - case AES_KEYSIZE_256: - break; -@@ -213,13 +214,15 @@ static int qce_skcipher_crypt(struct skc - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); - struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); - struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); -+ int keylen; - int ret; - - rctx->flags = tmpl->alg_flags; - rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; -+ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; - -- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && -- ctx->enc_keylen != AES_KEYSIZE_256) { -+ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && -+ keylen != AES_KEYSIZE_256) { - SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - - skcipher_request_set_sync_tfm(subreq, ctx->fallback); -@@ -311,8 +314,8 @@ static const struct qce_skcipher_def skc - .drv_name = "xts-aes-qce", - .blocksize = AES_BLOCK_SIZE, - .ivsize = AES_BLOCK_SIZE, -- .min_keysize = AES_MIN_KEY_SIZE, -- .max_keysize = AES_MAX_KEY_SIZE, -+ .min_keysize = AES_MIN_KEY_SIZE * 2, -+ .max_keysize = AES_MAX_KEY_SIZE * 2, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_ECB, diff --git a/target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch b/target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch deleted file mode 100644 index 2385d483f2..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 3ee50c896d712dc2fc8f34c2cd1918d035e74045 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 20 Dec 2019 16:02:15 -0300 -Subject: [PATCH 04/11] crypto: qce - save a sg table slot for result buf - -When ctr-aes-qce is used for gcm-mode, an extra sg entry for the -authentication tag is present, causing trouble when the qce driver -prepares the dst-results sg table for dma. - -It computes the number of entries needed with sg_nents_for_len, leaving -out the tag entry. Then it creates a sg table with that number plus -one, used to store a result buffer. - -When copying the sg table, there's no limit to the number of entries -copied, so the extra slot is filled with the authentication tag sg. -When the driver tries to add the result sg, the list is full, and it -returns EINVAL. - -By limiting the number of sg entries copied to the dest table, the slot -for the result buffer is guaranteed to be unused. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/dma.c | 6 ++++-- - drivers/crypto/qce/dma.h | 3 ++- - drivers/crypto/qce/skcipher.c | 4 ++-- - 3 files changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/crypto/qce/dma.c -+++ b/drivers/crypto/qce/dma.c -@@ -47,7 +47,8 @@ void qce_dma_release(struct qce_dma_data - } - - struct scatterlist * --qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) -+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, -+ int max_ents) - { - struct scatterlist *sg = sgt->sgl, *sg_last = NULL; - -@@ -60,12 +61,13 @@ qce_sgtable_add(struct sg_table *sgt, st - if (!sg) - return ERR_PTR(-EINVAL); - -- while (new_sgl && sg) { -+ while (new_sgl && sg && max_ents) { - sg_set_page(sg, sg_page(new_sgl), new_sgl->length, - new_sgl->offset); - sg_last = sg; - sg = sg_next(sg); - new_sgl = sg_next(new_sgl); -+ max_ents--; - } - - return sg_last; ---- a/drivers/crypto/qce/dma.h -+++ b/drivers/crypto/qce/dma.h -@@ -42,6 +42,7 @@ int qce_dma_prep_sgs(struct qce_dma_data - void qce_dma_issue_pending(struct qce_dma_data *dma); - int qce_dma_terminate_all(struct qce_dma_data *dma); - struct scatterlist * --qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add); -+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, -+ int max_ents); - - #endif /* _DMA_H_ */ ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -95,13 +95,13 @@ qce_skcipher_async_req_handle(struct cry - - sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); - -- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); -+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); - if (IS_ERR(sg)) { - ret = PTR_ERR(sg); - goto error_free; - } - -- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); -+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); - if (IS_ERR(sg)) { - ret = PTR_ERR(sg); - goto error_free; diff --git a/target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch b/target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch deleted file mode 100644 index 5efdb72c44..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 3e806a12d10af2581aa26c37b58439286eab9782 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 20 Dec 2019 16:02:16 -0300 -Subject: [PATCH 05/11] crypto: qce - update the skcipher IV - -Update the IV after the completion of each cipher operation. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/skcipher.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -21,6 +21,7 @@ static void qce_skcipher_done(void *data - struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); - struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); - struct qce_device *qce = tmpl->qce; -+ struct qce_result_dump *result_buf = qce->dma.result_buf; - enum dma_data_direction dir_src, dir_dst; - u32 status; - int error; -@@ -45,6 +46,7 @@ static void qce_skcipher_done(void *data - if (error < 0) - dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); - -+ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); - qce->async_req_done(tmpl->qce, error); - } - diff --git a/target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch b/target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch deleted file mode 100644 index 84aef04ef4..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 8ceda883205db6dfedb82e39f67feae3b50c95a1 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 20 Dec 2019 16:02:17 -0300 -Subject: [PATCH 06/11] crypto: qce - initialize fallback only for AES - -Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where -AES-192 is not handled by the qce hardware, and don't allocate & free -the fallback skcipher for other algorithms. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/skcipher.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -257,7 +257,14 @@ static int qce_skcipher_init(struct cryp - - memset(ctx, 0, sizeof(*ctx)); - crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); -+ return 0; -+} -+ -+static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) -+{ -+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); - -+ qce_skcipher_init(tfm); - ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), - 0, CRYPTO_ALG_NEED_FALLBACK); - return PTR_ERR_OR_ZERO(ctx->fallback); -@@ -387,14 +394,18 @@ static int qce_skcipher_register_one(con - - alg->base.cra_priority = 300; - alg->base.cra_flags = CRYPTO_ALG_ASYNC | -- CRYPTO_ALG_NEED_FALLBACK | - CRYPTO_ALG_KERN_DRIVER_ONLY; - alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); - alg->base.cra_alignmask = 0; - alg->base.cra_module = THIS_MODULE; - -- alg->init = qce_skcipher_init; -- alg->exit = qce_skcipher_exit; -+ if (IS_AES(def->flags)) { -+ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; -+ alg->init = qce_skcipher_init_fallback; -+ alg->exit = qce_skcipher_exit; -+ } else { -+ alg->init = qce_skcipher_init; -+ } - - INIT_LIST_HEAD(&tmpl->entry); - tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; diff --git a/target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch b/target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch deleted file mode 100644 index 5b1372d08f..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch +++ /dev/null @@ -1,419 +0,0 @@ -From 59e056cda4beb5412e3653e6360c2eb0fa770baa Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 20 Dec 2019 16:02:18 -0300 -Subject: [PATCH 07/11] crypto: qce - allow building only hashes/ciphers - -Allow the user to choose whether to build support for all algorithms -(default), hashes-only, or skciphers-only. - -The QCE engine does not appear to scale as well as the CPU to handle -multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the -QCE handles only 2 requests in parallel. - -Ipsec throughput seems to improve when disabling either family of -algorithms, sharing the load with the CPU. Enabling skciphers-only -appears to work best. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - ---- a/drivers/crypto/Kconfig -+++ b/drivers/crypto/Kconfig -@@ -617,6 +617,14 @@ config CRYPTO_DEV_QCE - tristate "Qualcomm crypto engine accelerator" - depends on ARCH_QCOM || COMPILE_TEST - depends on HAS_IOMEM -+ help -+ This driver supports Qualcomm crypto engine accelerator -+ hardware. To compile this driver as a module, choose M here. The -+ module will be called qcrypto. -+ -+config CRYPTO_DEV_QCE_SKCIPHER -+ bool -+ depends on CRYPTO_DEV_QCE - select CRYPTO_AES - select CRYPTO_LIB_DES - select CRYPTO_ECB -@@ -624,10 +632,57 @@ config CRYPTO_DEV_QCE - select CRYPTO_XTS - select CRYPTO_CTR - select CRYPTO_BLKCIPHER -+ -+config CRYPTO_DEV_QCE_SHA -+ bool -+ depends on CRYPTO_DEV_QCE -+ -+choice -+ prompt "Algorithms enabled for QCE acceleration" -+ default CRYPTO_DEV_QCE_ENABLE_ALL -+ depends on CRYPTO_DEV_QCE - help -- This driver supports Qualcomm crypto engine accelerator -- hardware. To compile this driver as a module, choose M here. The -- module will be called qcrypto. -+ This option allows to choose whether to build support for all algorihtms -+ (default), hashes-only, or skciphers-only. -+ -+ The QCE engine does not appear to scale as well as the CPU to handle -+ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the -+ QCE handles only 2 requests in parallel. -+ -+ Ipsec throughput seems to improve when disabling either family of -+ algorithms, sharing the load with the CPU. Enabling skciphers-only -+ appears to work best. -+ -+ config CRYPTO_DEV_QCE_ENABLE_ALL -+ bool "All supported algorithms" -+ select CRYPTO_DEV_QCE_SKCIPHER -+ select CRYPTO_DEV_QCE_SHA -+ help -+ Enable all supported algorithms: -+ - AES (CBC, CTR, ECB, XTS) -+ - 3DES (CBC, ECB) -+ - DES (CBC, ECB) -+ - SHA1, HMAC-SHA1 -+ - SHA256, HMAC-SHA256 -+ -+ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER -+ bool "Symmetric-key ciphers only" -+ select CRYPTO_DEV_QCE_SKCIPHER -+ help -+ Enable symmetric-key ciphers only: -+ - AES (CBC, CTR, ECB, XTS) -+ - 3DES (ECB, CBC) -+ - DES (ECB, CBC) -+ -+ config CRYPTO_DEV_QCE_ENABLE_SHA -+ bool "Hash/HMAC only" -+ select CRYPTO_DEV_QCE_SHA -+ help -+ Enable hashes/HMAC algorithms only: -+ - SHA1, HMAC-SHA1 -+ - SHA256, HMAC-SHA256 -+ -+endchoice - - config CRYPTO_DEV_QCOM_RNG - tristate "Qualcomm Random Number Generator Driver" ---- a/drivers/crypto/qce/Makefile -+++ b/drivers/crypto/qce/Makefile -@@ -2,6 +2,7 @@ - obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o - qcrypto-objs := core.o \ - common.o \ -- dma.o \ -- sha.o \ -- skcipher.o -+ dma.o -+ -+qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o -+qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o ---- a/drivers/crypto/qce/common.c -+++ b/drivers/crypto/qce/common.c -@@ -45,52 +45,56 @@ qce_clear_array(struct qce_device *qce, - qce_write(qce, offset + i * sizeof(u32), 0); - } - --static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) -+static u32 qce_config_reg(struct qce_device *qce, int little) - { -- u32 cfg = 0; -+ u32 beats = (qce->burst_size >> 3) - 1; -+ u32 pipe_pair = qce->pipe_pair_id; -+ u32 config; - -- if (IS_AES(flags)) { -- if (aes_key_size == AES_KEYSIZE_128) -- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; -- else if (aes_key_size == AES_KEYSIZE_256) -- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; -- } -+ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; -+ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | -+ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); -+ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; -+ config &= ~HIGH_SPD_EN_N_SHIFT; - -- if (IS_AES(flags)) -- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; -- else if (IS_DES(flags) || IS_3DES(flags)) -- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; -+ if (little) -+ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); - -- if (IS_DES(flags)) -- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; -+ return config; -+} - -- if (IS_3DES(flags)) -- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; -+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) -+{ -+ __be32 *d = dst; -+ const u8 *s = src; -+ unsigned int n; - -- switch (flags & QCE_MODE_MASK) { -- case QCE_MODE_ECB: -- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; -- break; -- case QCE_MODE_CBC: -- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; -- break; -- case QCE_MODE_CTR: -- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; -- break; -- case QCE_MODE_XTS: -- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; -- break; -- case QCE_MODE_CCM: -- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; -- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; -- break; -- default: -- return ~0; -+ n = len / sizeof(u32); -+ for (; n > 0; n--) { -+ *d = cpu_to_be32p((const __u32 *) s); -+ s += sizeof(__u32); -+ d++; - } -+} - -- return cfg; -+static void qce_setup_config(struct qce_device *qce) -+{ -+ u32 config; -+ -+ /* get big endianness */ -+ config = qce_config_reg(qce, 0); -+ -+ /* clear status */ -+ qce_write(qce, REG_STATUS, 0); -+ qce_write(qce, REG_CONFIG, config); -+} -+ -+static inline void qce_crypto_go(struct qce_device *qce) -+{ -+ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); - } - -+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA - static u32 qce_auth_cfg(unsigned long flags, u32 key_size) - { - u32 cfg = 0; -@@ -137,88 +141,6 @@ static u32 qce_auth_cfg(unsigned long fl - return cfg; - } - --static u32 qce_config_reg(struct qce_device *qce, int little) --{ -- u32 beats = (qce->burst_size >> 3) - 1; -- u32 pipe_pair = qce->pipe_pair_id; -- u32 config; -- -- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; -- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | -- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); -- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; -- config &= ~HIGH_SPD_EN_N_SHIFT; -- -- if (little) -- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); -- -- return config; --} -- --void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) --{ -- __be32 *d = dst; -- const u8 *s = src; -- unsigned int n; -- -- n = len / sizeof(u32); -- for (; n > 0; n--) { -- *d = cpu_to_be32p((const __u32 *) s); -- s += sizeof(__u32); -- d++; -- } --} -- --static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) --{ -- u8 swap[QCE_AES_IV_LENGTH]; -- u32 i, j; -- -- if (ivsize > QCE_AES_IV_LENGTH) -- return; -- -- memset(swap, 0, QCE_AES_IV_LENGTH); -- -- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; -- i < QCE_AES_IV_LENGTH; i++, j--) -- swap[i] = src[j]; -- -- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); --} -- --static void qce_xtskey(struct qce_device *qce, const u8 *enckey, -- unsigned int enckeylen, unsigned int cryptlen) --{ -- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; -- unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); -- unsigned int xtsdusize; -- -- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, -- enckeylen / 2); -- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); -- -- /* xts du size 512B */ -- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); -- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); --} -- --static void qce_setup_config(struct qce_device *qce) --{ -- u32 config; -- -- /* get big endianness */ -- config = qce_config_reg(qce, 0); -- -- /* clear status */ -- qce_write(qce, REG_STATUS, 0); -- qce_write(qce, REG_CONFIG, config); --} -- --static inline void qce_crypto_go(struct qce_device *qce) --{ -- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); --} -- - static int qce_setup_regs_ahash(struct crypto_async_request *async_req, - u32 totallen, u32 offset) - { -@@ -303,6 +225,87 @@ go_proc: - - return 0; - } -+#endif -+ -+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER -+static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) -+{ -+ u32 cfg = 0; -+ -+ if (IS_AES(flags)) { -+ if (aes_key_size == AES_KEYSIZE_128) -+ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; -+ else if (aes_key_size == AES_KEYSIZE_256) -+ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; -+ } -+ -+ if (IS_AES(flags)) -+ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; -+ else if (IS_DES(flags) || IS_3DES(flags)) -+ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; -+ -+ if (IS_DES(flags)) -+ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; -+ -+ if (IS_3DES(flags)) -+ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; -+ -+ switch (flags & QCE_MODE_MASK) { -+ case QCE_MODE_ECB: -+ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; -+ break; -+ case QCE_MODE_CBC: -+ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; -+ break; -+ case QCE_MODE_CTR: -+ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; -+ break; -+ case QCE_MODE_XTS: -+ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; -+ break; -+ case QCE_MODE_CCM: -+ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; -+ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; -+ break; -+ default: -+ return ~0; -+ } -+ -+ return cfg; -+} -+ -+static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) -+{ -+ u8 swap[QCE_AES_IV_LENGTH]; -+ u32 i, j; -+ -+ if (ivsize > QCE_AES_IV_LENGTH) -+ return; -+ -+ memset(swap, 0, QCE_AES_IV_LENGTH); -+ -+ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; -+ i < QCE_AES_IV_LENGTH; i++, j--) -+ swap[i] = src[j]; -+ -+ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); -+} -+ -+static void qce_xtskey(struct qce_device *qce, const u8 *enckey, -+ unsigned int enckeylen, unsigned int cryptlen) -+{ -+ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; -+ unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); -+ unsigned int xtsdusize; -+ -+ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, -+ enckeylen / 2); -+ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); -+ -+ /* xts du size 512B */ -+ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); -+ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); -+} - - static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, - u32 totallen, u32 offset) -@@ -384,15 +387,20 @@ static int qce_setup_regs_skcipher(struc - - return 0; - } -+#endif - - int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, - u32 offset) - { - switch (type) { -+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER - case CRYPTO_ALG_TYPE_SKCIPHER: - return qce_setup_regs_skcipher(async_req, totallen, offset); -+#endif -+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA - case CRYPTO_ALG_TYPE_AHASH: - return qce_setup_regs_ahash(async_req, totallen, offset); -+#endif - default: - return -EINVAL; - } ---- a/drivers/crypto/qce/core.c -+++ b/drivers/crypto/qce/core.c -@@ -22,8 +22,12 @@ - #define QCE_QUEUE_LENGTH 1 - - static const struct qce_algo_ops *qce_ops[] = { -+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER - &skcipher_ops, -+#endif -+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA - &ahash_ops, -+#endif - }; - - static void qce_unregister_algs(struct qce_device *qce) diff --git a/target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch b/target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch deleted file mode 100644 index 160420b485..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch +++ /dev/null @@ -1,89 +0,0 @@ -From d6364b8128439a8c0e381f80c38667de9f15eef8 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 7 Feb 2020 12:02:25 -0300 -Subject: [PATCH 09/11] crypto: qce - use cryptlen when adding extra sgl - -The qce crypto driver appends an extra entry to the dst sgl, to maintain -private state information. - -When the gcm driver sends requests to the ctr skcipher, it passes the -authentication tag after the actual crypto payload, but it must not be -touched. - -Commit 1336c2221bee ("crypto: qce - save a sg table slot for result -buf") limited the destination sgl to avoid overwriting the -authentication tag but it assumed the tag would be in a separate sgl -entry. - -This is not always the case, so it is better to limit the length of the -destination buffer to req->cryptlen before appending the result buf. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/dma.c | 11 ++++++----- - drivers/crypto/qce/dma.h | 2 +- - drivers/crypto/qce/skcipher.c | 5 +++-- - 3 files changed, 10 insertions(+), 8 deletions(-) - ---- a/drivers/crypto/qce/dma.c -+++ b/drivers/crypto/qce/dma.c -@@ -48,9 +48,10 @@ void qce_dma_release(struct qce_dma_data - - struct scatterlist * - qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, -- int max_ents) -+ unsigned int max_len) - { - struct scatterlist *sg = sgt->sgl, *sg_last = NULL; -+ unsigned int new_len; - - while (sg) { - if (!sg_page(sg)) -@@ -61,13 +62,13 @@ qce_sgtable_add(struct sg_table *sgt, st - if (!sg) - return ERR_PTR(-EINVAL); - -- while (new_sgl && sg && max_ents) { -- sg_set_page(sg, sg_page(new_sgl), new_sgl->length, -- new_sgl->offset); -+ while (new_sgl && sg && max_len) { -+ new_len = new_sgl->length > max_len ? max_len : new_sgl->length; -+ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset); - sg_last = sg; - sg = sg_next(sg); - new_sgl = sg_next(new_sgl); -- max_ents--; -+ max_len -= new_len; - } - - return sg_last; ---- a/drivers/crypto/qce/dma.h -+++ b/drivers/crypto/qce/dma.h -@@ -43,6 +43,6 @@ void qce_dma_issue_pending(struct qce_dm - int qce_dma_terminate_all(struct qce_dma_data *dma); - struct scatterlist * - qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, -- int max_ents); -+ unsigned int max_len); - - #endif /* _DMA_H_ */ ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -97,13 +97,14 @@ qce_skcipher_async_req_handle(struct cry - - sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); - -- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); -+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); - if (IS_ERR(sg)) { - ret = PTR_ERR(sg); - goto error_free; - } - -- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); -+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, -+ QCE_RESULT_BUF_SZ); - if (IS_ERR(sg)) { - ret = PTR_ERR(sg); - goto error_free; diff --git a/target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch b/target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch deleted file mode 100644 index 0b5c8c6d66..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch +++ /dev/null @@ -1,113 +0,0 @@ -From ce163ba0bf298f1707321ac025ef639f88e62801 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 7 Feb 2020 12:02:26 -0300 -Subject: [PATCH 10/11] crypto: qce - use AES fallback for small requests - -Process small blocks using the fallback cipher, as a workaround for an -observed failure (DMA-related, apparently) when computing the GCM ghash -key. This brings a speed gain as well, since it avoids the latency of -using the hardware engine to process small blocks. - -Using software for all 16-byte requests would be enough to make GCM -work, but to increase performance, a larger threshold would be better. -Measuring the performance of supported ciphers with openssl speed, -software matches hardware at around 768-1024 bytes. - -Considering the 256-bit ciphers, software is 2-3 times faster than qce -at 256-bytes, 30% faster at 512, and about even at 768-bytes. With -128-bit keys, the break-even point would be around 1024-bytes. - -This adds the 'aes_sw_max_len' parameter, to set the largest request -length processed by the software fallback. Its default is being set to -512 bytes, a little lower than the break-even point, to balance the cost -in CPU usage. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - ---- a/drivers/crypto/Kconfig -+++ b/drivers/crypto/Kconfig -@@ -684,6 +684,29 @@ choice - - endchoice - -+config CRYPTO_DEV_QCE_SW_MAX_LEN -+ int "Default maximum request size to use software for AES" -+ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER -+ default 512 -+ help -+ This sets the default maximum request size to perform AES requests -+ using software instead of the crypto engine. It can be changed by -+ setting the aes_sw_max_len parameter. -+ -+ Small blocks are processed faster in software than hardware. -+ Considering the 256-bit ciphers, software is 2-3 times faster than -+ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes. -+ With 128-bit keys, the break-even point would be around 1024-bytes. -+ -+ The default is set a little lower, to 512 bytes, to balance the -+ cost in CPU usage. The minimum recommended setting is 16-bytes -+ (1 AES block), since AES-GCM will fail if you set it lower. -+ Setting this to zero will send all requests to the hardware. -+ -+ Note that 192-bit keys are not supported by the hardware and are -+ always processed by the software fallback, and all DES requests -+ are done by the hardware. -+ - config CRYPTO_DEV_QCOM_RNG - tristate "Qualcomm Random Number Generator Driver" - depends on ARCH_QCOM || COMPILE_TEST ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -5,6 +5,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -12,6 +13,13 @@ - - #include "cipher.h" - -+static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; -+module_param(aes_sw_max_len, uint, 0644); -+MODULE_PARM_DESC(aes_sw_max_len, -+ "Only use hardware for AES requests larger than this " -+ "[0=always use hardware; anything <16 breaks AES-GCM; default=" -+ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]"); -+ - static LIST_HEAD(skcipher_algs); - - static void qce_skcipher_done(void *data) -@@ -166,15 +174,10 @@ static int qce_skcipher_setkey(struct cr - switch (IS_XTS(flags) ? keylen >> 1 : keylen) { - case AES_KEYSIZE_128: - case AES_KEYSIZE_256: -+ memcpy(ctx->enc_key, key, keylen); - break; -- default: -- goto fallback; - } - -- ctx->enc_keylen = keylen; -- memcpy(ctx->enc_key, key, keylen); -- return 0; --fallback: - ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); - if (!ret) - ctx->enc_keylen = keylen; -@@ -224,8 +227,9 @@ static int qce_skcipher_crypt(struct skc - rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; - keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; - -- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && -- keylen != AES_KEYSIZE_256) { -+ if (IS_AES(rctx->flags) && -+ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || -+ req->cryptlen <= aes_sw_max_len)) { - SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - - skcipher_request_set_sync_tfm(subreq, ctx->fallback); diff --git a/target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch b/target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch deleted file mode 100644 index 18beda6296..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 7f19380b2cfd412dcef2facefb3f6c62788864d7 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Fri, 7 Feb 2020 12:02:27 -0300 -Subject: [PATCH 11/11] crypto: qce - handle AES-XTS cases that qce fails - -QCE hangs when presented with an AES-XTS request whose length is larger -than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the -fallback cipher handle them. - -Signed-off-by: Eneas U de Queiroz -Signed-off-by: Herbert Xu ---- - drivers/crypto/qce/common.c | 2 -- - drivers/crypto/qce/common.h | 3 +++ - drivers/crypto/qce/skcipher.c | 9 +++++++-- - 3 files changed, 10 insertions(+), 4 deletions(-) - ---- a/drivers/crypto/qce/common.c -+++ b/drivers/crypto/qce/common.c -@@ -15,8 +15,6 @@ - #include "regs-v5.h" - #include "sha.h" - --#define QCE_SECTOR_SIZE 512 -- - static inline u32 qce_read(struct qce_device *qce, u32 offset) - { - return readl(qce->base + offset); ---- a/drivers/crypto/qce/common.h -+++ b/drivers/crypto/qce/common.h -@@ -12,6 +12,9 @@ - #include - #include - -+/* xts du size */ -+#define QCE_SECTOR_SIZE 512 -+ - /* key size in bytes */ - #define QCE_SHA_HMAC_KEY_SIZE 64 - #define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256 ---- a/drivers/crypto/qce/skcipher.c -+++ b/drivers/crypto/qce/skcipher.c -@@ -227,9 +227,14 @@ static int qce_skcipher_crypt(struct skc - rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; - keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; - -+ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and -+ * is not a multiple of it; pass such requests to the fallback -+ */ - if (IS_AES(rctx->flags) && -- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || -- req->cryptlen <= aes_sw_max_len)) { -+ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || -+ req->cryptlen <= aes_sw_max_len) || -+ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && -+ req->cryptlen % QCE_SECTOR_SIZE))) { - SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - - skcipher_request_set_sync_tfm(subreq, ctx->fallback); diff --git a/target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch b/target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch deleted file mode 100644 index ad09a9f250..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 3c9d8f6c03a2cda1849ec3c84f82ec030d1f49ef Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 3 May 2020 22:18:22 +0200 -Subject: [PATCH] phy: add driver for Qualcomm IPQ40xx USB PHY - -Add a driver to setup the USB PHY-s on Qualcom m IPQ40xx series SoCs. -The driver sets up HS and SS phys. - -Signed-off-by: John Crispin -Signed-off-by: Robert Marko -Cc: Luka Perkov -Link: https://lore.kernel.org/r/20200503201823.531757-1-robert.marko@sartura.hr -Signed-off-by: Vinod Koul ---- - drivers/phy/qualcomm/Kconfig | 7 + - drivers/phy/qualcomm/Makefile | 1 + - drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c | 148 ++++++++++++++++++++ - 3 files changed, 156 insertions(+) - create mode 100644 drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c - ---- a/drivers/phy/qualcomm/Kconfig -+++ b/drivers/phy/qualcomm/Kconfig -@@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA - depends on OF - select GENERIC_PHY - -+config PHY_QCOM_IPQ4019_USB -+ tristate "Qualcomm IPQ4019 USB PHY driver" -+ depends on OF && (ARCH_QCOM || COMPILE_TEST) -+ select GENERIC_PHY -+ help -+ Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. -+ - config PHY_QCOM_IPQ806X_SATA - tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" - depends on ARCH_QCOM ---- a/drivers/phy/qualcomm/Makefile -+++ b/drivers/phy/qualcomm/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o - obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o -+obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o - obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o - obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o - obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o ---- /dev/null -+++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c -@@ -0,0 +1,148 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * Based on code from -+ * Allwinner Technology Co., Ltd. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct ipq4019_usb_phy { -+ struct device *dev; -+ struct phy *phy; -+ void __iomem *base; -+ struct reset_control *por_rst; -+ struct reset_control *srif_rst; -+}; -+ -+static int ipq4019_ss_phy_power_off(struct phy *_phy) -+{ -+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); -+ -+ reset_control_assert(phy->por_rst); -+ msleep(10); -+ -+ return 0; -+} -+ -+static int ipq4019_ss_phy_power_on(struct phy *_phy) -+{ -+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); -+ -+ ipq4019_ss_phy_power_off(_phy); -+ -+ reset_control_deassert(phy->por_rst); -+ -+ return 0; -+} -+ -+static struct phy_ops ipq4019_usb_ss_phy_ops = { -+ .power_on = ipq4019_ss_phy_power_on, -+ .power_off = ipq4019_ss_phy_power_off, -+}; -+ -+static int ipq4019_hs_phy_power_off(struct phy *_phy) -+{ -+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); -+ -+ reset_control_assert(phy->por_rst); -+ msleep(10); -+ -+ reset_control_assert(phy->srif_rst); -+ msleep(10); -+ -+ return 0; -+} -+ -+static int ipq4019_hs_phy_power_on(struct phy *_phy) -+{ -+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); -+ -+ ipq4019_hs_phy_power_off(_phy); -+ -+ reset_control_deassert(phy->srif_rst); -+ msleep(10); -+ -+ reset_control_deassert(phy->por_rst); -+ -+ return 0; -+} -+ -+static struct phy_ops ipq4019_usb_hs_phy_ops = { -+ .power_on = ipq4019_hs_phy_power_on, -+ .power_off = ipq4019_hs_phy_power_off, -+}; -+ -+static const struct of_device_id ipq4019_usb_phy_of_match[] = { -+ { .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops}, -+ { .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops}, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match); -+ -+static int ipq4019_usb_phy_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ struct phy_provider *phy_provider; -+ struct ipq4019_usb_phy *phy; -+ -+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); -+ if (!phy) -+ return -ENOMEM; -+ -+ phy->dev = &pdev->dev; -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ phy->base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(phy->base)) { -+ dev_err(dev, "failed to remap register memory\n"); -+ return PTR_ERR(phy->base); -+ } -+ -+ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst"); -+ if (IS_ERR(phy->por_rst)) { -+ if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER) -+ dev_err(dev, "POR reset is missing\n"); -+ return PTR_ERR(phy->por_rst); -+ } -+ -+ phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst"); -+ if (IS_ERR(phy->srif_rst)) -+ return PTR_ERR(phy->srif_rst); -+ -+ phy->phy = devm_phy_create(dev, NULL, of_device_get_match_data(dev)); -+ if (IS_ERR(phy->phy)) { -+ dev_err(dev, "failed to create PHY\n"); -+ return PTR_ERR(phy->phy); -+ } -+ phy_set_drvdata(phy->phy, phy); -+ -+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); -+ -+ return PTR_ERR_OR_ZERO(phy_provider); -+} -+ -+static struct platform_driver ipq4019_usb_phy_driver = { -+ .probe = ipq4019_usb_phy_probe, -+ .driver = { -+ .of_match_table = ipq4019_usb_phy_of_match, -+ .name = "ipq4019-usb-phy", -+ } -+}; -+module_platform_driver(ipq4019_usb_phy_driver); -+ -+MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver"); -+MODULE_AUTHOR("John Crispin "); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch b/target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch deleted file mode 100644 index 5cd4ccc30f..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0018-v5.9-pinctrl-msm-open-drain.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 5b08c1d567ee8e6af94696b3e549997cbdb2bb80 Mon Sep 17 00:00:00 2001 -From: Jaiganesh Narayanan -Date: Thu, 1 Sep 2016 10:40:38 +0530 -Subject: [PATCH] pinctrl: qcom: ipq4019: add open drain support - -Signed-off-by: Jaiganesh Narayanan -[ Brian: adapted from from the Chromium OS kernel used on IPQ4019-based - WiFi APs. ] -Signed-off-by: Brian Norris ---- -https://lore.kernel.org/linux-gpio/20200703080646.23233-1-computersforpeace@gmail.com/ - - drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1 + - drivers/pinctrl/qcom/pinctrl-msm.c | 13 +++++++++++++ - drivers/pinctrl/qcom/pinctrl-msm.h | 2 ++ - 3 files changed, 16 insertions(+) - ---- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c -+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c -@@ -254,6 +254,7 @@ DECLARE_QCA_GPIO_PINS(99); - .mux_bit = 2, \ - .pull_bit = 0, \ - .drv_bit = 6, \ -+ .od_bit = 12, \ - .oe_bit = 9, \ - .in_bit = 0, \ - .out_bit = 1, \ ---- a/drivers/pinctrl/qcom/pinctrl-msm.c -+++ b/drivers/pinctrl/qcom/pinctrl-msm.c -@@ -225,6 +225,10 @@ static int msm_config_reg(struct msm_pin - *bit = g->pull_bit; - *mask = 3; - break; -+ case PIN_CONFIG_DRIVE_OPEN_DRAIN: -+ *bit = g->od_bit; -+ *mask = 1; -+ break; - case PIN_CONFIG_DRIVE_STRENGTH: - *bit = g->drv_bit; - *mask = 7; -@@ -302,6 +306,12 @@ static int msm_config_group_get(struct p - if (!arg) - return -EINVAL; - break; -+ case PIN_CONFIG_DRIVE_OPEN_DRAIN: -+ /* Pin is not open-drain */ -+ if (!arg) -+ return -EINVAL; -+ arg = 1; -+ break; - case PIN_CONFIG_DRIVE_STRENGTH: - arg = msm_regval_to_drive(arg); - break; -@@ -374,6 +384,9 @@ static int msm_config_group_set(struct p - else - arg = MSM_PULL_UP; - break; -+ case PIN_CONFIG_DRIVE_OPEN_DRAIN: -+ arg = 1; -+ break; - case PIN_CONFIG_DRIVE_STRENGTH: - /* Check for invalid values */ - if (arg > 16 || arg < 2 || (arg % 2) != 0) ---- a/drivers/pinctrl/qcom/pinctrl-msm.h -+++ b/drivers/pinctrl/qcom/pinctrl-msm.h -@@ -38,6 +38,7 @@ struct msm_function { - * @mux_bit: Offset in @ctl_reg for the pinmux function selection. - * @pull_bit: Offset in @ctl_reg for the bias configuration. - * @drv_bit: Offset in @ctl_reg for the drive strength configuration. -+ * @od_bit: Offset in @ctl_reg for controlling open drain. - * @oe_bit: Offset in @ctl_reg for controlling output enable. - * @in_bit: Offset in @io_reg for the input bit value. - * @out_bit: Offset in @io_reg for the output bit value. -@@ -75,6 +76,7 @@ struct msm_pingroup { - unsigned pull_bit:5; - unsigned drv_bit:5; - -+ unsigned od_bit:5; - unsigned oe_bit:5; - unsigned in_bit:5; - unsigned out_bit:5; diff --git a/target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch b/target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch deleted file mode 100644 index f1be01c8e1..0000000000 --- a/target/linux/ipq40xx/patches-5.10/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 707745e8d4e75b638b990d67950ab292b3b8ea2a Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Mon, 16 Dec 2019 01:36:46 +0100 -Subject: [PATCH] mtd: spi-nor: Add support for mx25r3235f - -Add MTD support for the Macronix MX25R3235F SPI NOR chip from Macronix. -The chip has 4MB of total capacity, divided into a total of 64 sectors, -each 64KB sized. The chip also supports 4KB large sectors. -Additionally, it supports dual and quad read modes. - -Functionality was verified on an HPE/Aruba AP-303 board. - -Signed-off-by: David Bauer -Signed-off-by: Tudor Ambarus ---- - drivers/mtd/spi-nor/spi-nor.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2353,6 +2353,8 @@ static const struct flash_info spi_nor_i - { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, - { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, - { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, -+ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64, -+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, From 75a90f161e5993b3007d48628b61b22e95c07627 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 22:33:36 +0200 Subject: [PATCH 46/82] ipq40xx: 5.10: remove duplicate GPIO export patch Its in the generic target already, so remove the duplicate as it breaks compilation. Signed-off-by: Robert Marko --- .../100-GPIO-add-named-gpio-exports.patch | 165 ------------------ 1 file changed, 165 deletions(-) delete mode 100644 target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch diff --git a/target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch b/target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch deleted file mode 100644 index 805836fcca..0000000000 --- a/target/linux/ipq40xx/patches-5.10/100-GPIO-add-named-gpio-exports.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 12 Aug 2014 20:49:27 +0200 -Subject: [PATCH 24/53] GPIO: add named gpio exports - -Signed-off-by: John Crispin ---- - drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ - drivers/gpio/gpiolib-sysfs.c | 10 +++++- - include/asm-generic/gpio.h | 6 ++++ - include/linux/gpio/consumer.h | 8 +++++ - 4 files changed, 91 insertions(+), 1 deletion(-) - ---- a/drivers/gpio/gpiolib-of.c -+++ b/drivers/gpio/gpiolib-of.c -@@ -19,6 +19,8 @@ - #include - #include - #include -+#include -+#include - - #include "gpiolib.h" - #include "gpiolib-of.h" -@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip - { - of_node_put(chip->of_node); - } -+ -+static struct of_device_id gpio_export_ids[] = { -+ { .compatible = "gpio-export" }, -+ { /* sentinel */ } -+}; -+ -+static int of_gpio_export_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *cnp; -+ u32 val; -+ int nb = 0; -+ -+ for_each_child_of_node(np, cnp) { -+ const char *name = NULL; -+ int gpio; -+ bool dmc; -+ int max_gpio = 1; -+ int i; -+ -+ of_property_read_string(cnp, "gpio-export,name", &name); -+ -+ if (!name) -+ max_gpio = of_gpio_count(cnp); -+ -+ for (i = 0; i < max_gpio; i++) { -+ unsigned flags = 0; -+ enum of_gpio_flags of_flags; -+ -+ gpio = of_get_gpio_flags(cnp, i, &of_flags); -+ if (!gpio_is_valid(gpio)) -+ return gpio; -+ -+ if (of_flags == OF_GPIO_ACTIVE_LOW) -+ flags |= GPIOF_ACTIVE_LOW; -+ -+ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) -+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; -+ else -+ flags |= GPIOF_IN; -+ -+ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) -+ continue; -+ -+ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); -+ gpio_export_with_name(gpio, dmc, name); -+ nb++; -+ } -+ } -+ -+ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); -+ -+ return 0; -+} -+ -+static struct platform_driver gpio_export_driver = { -+ .driver = { -+ .name = "gpio-export", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(gpio_export_ids), -+ }, -+ .probe = of_gpio_export_probe, -+}; -+ -+module_platform_driver(gpio_export_driver); ---- a/drivers/gpio/gpiolib-sysfs.c -+++ b/drivers/gpio/gpiolib-sysfs.c -@@ -571,7 +571,7 @@ static struct class gpio_class = { - * - * Returns zero on success, else an error. - */ --int gpiod_export(struct gpio_desc *desc, bool direction_may_change) -+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) - { - struct gpio_chip *chip; - struct gpio_device *gdev; -@@ -633,6 +633,8 @@ int gpiod_export(struct gpio_desc *desc, - offset = gpio_chip_hwgpio(desc); - if (chip->names && chip->names[offset]) - ioname = chip->names[offset]; -+ if (name) -+ ioname = name; - - dev = device_create_with_groups(&gpio_class, &gdev->dev, - MKDEV(0, 0), data, gpio_groups, -@@ -654,6 +656,12 @@ err_unlock: - gpiod_dbg(desc, "%s: status %d\n", __func__, status); - return status; - } -+EXPORT_SYMBOL_GPL(__gpiod_export); -+ -+int gpiod_export(struct gpio_desc *desc, bool direction_may_change) -+{ -+ return __gpiod_export(desc, direction_may_change, NULL); -+} - EXPORT_SYMBOL_GPL(gpiod_export); - - static int match_export(struct device *dev, const void *desc) ---- a/include/asm-generic/gpio.h -+++ b/include/asm-generic/gpio.h -@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g - return gpiod_export(gpio_to_desc(gpio), direction_may_change); - } - -+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); -+static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) -+{ -+ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); -+} -+ - static inline int gpio_export_link(struct device *dev, const char *name, - unsigned gpio) - { ---- a/include/linux/gpio/consumer.h -+++ b/include/linux/gpio/consumer.h -@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_ - - #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) - -+int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); - int gpiod_export(struct gpio_desc *desc, bool direction_may_change); - int gpiod_export_link(struct device *dev, const char *name, - struct gpio_desc *desc); -@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de - - #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ - -+static inline int _gpiod_export(struct gpio_desc *desc, -+ bool direction_may_change, -+ const char *name) -+{ -+ return -ENOSYS; -+} -+ - static inline int gpiod_export(struct gpio_desc *desc, - bool direction_may_change) - { From fec22cfa59b34efeb2dc00eda15262a2982aa6b4 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 22:34:43 +0200 Subject: [PATCH 47/82] ipq40xx: 5.10: replace patches with upstreamed versions USB and SDHCI LDO DTS patches have been upstreamed into 5.12, so replace the local versions with upstreamed ones. Reorder, and clearly mark the kernel version. Signed-off-by: Robert Marko --- ...-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch} | 8 +++++--- ...v5.12-ARM-dts-qcom-ipq4019-add-more-labels.patch} | 12 +++++++----- ...-dts-qcom-ipq4019-add-SDHCI-VQMMC-LDO-node.patch} | 9 ++++++--- 3 files changed, 18 insertions(+), 11 deletions(-) rename target/linux/ipq40xx/patches-5.10/{102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch => 0001-v5.12-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch} (91%) rename target/linux/ipq40xx/patches-5.10/{103-arm-dts-qcom-ipq4019-add-more-labels.patch => 0002-v5.12-ARM-dts-qcom-ipq4019-add-more-labels.patch} (74%) rename target/linux/ipq40xx/patches-5.10/{101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch => 0003-v5.12-ARM-dts-qcom-ipq4019-add-SDHCI-VQMMC-LDO-node.patch} (71%) diff --git a/target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch b/target/linux/ipq40xx/patches-5.10/0001-v5.12-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch similarity index 91% rename from target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch rename to target/linux/ipq40xx/patches-5.10/0001-v5.12-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch index b033a1baee..890611387c 100644 --- a/target/linux/ipq40xx/patches-5.10/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch +++ b/target/linux/ipq40xx/patches-5.10/0001-v5.12-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch @@ -1,6 +1,6 @@ -From 193856b5fe11c50a0b6ff22457dd674c1a45fec6 Mon Sep 17 00:00:00 2001 +From b8afc254b40167fd37b4d4263e750dab1f9ef157 Mon Sep 17 00:00:00 2001 From: John Crispin -Date: Wed, 9 Sep 2020 18:31:03 +0200 +Date: Wed, 9 Sep 2020 18:38:31 +0200 Subject: [PATCH] ARM: dts: qcom: ipq4019: add USB devicetree nodes Since we now have driver for the USB PHY, and USB controller is already supported by the DWC3 driver lets add the necessary nodes to DTSI. @@ -9,13 +9,15 @@ Signed-off-by: John Crispin Signed-off-by: Robert Marko Cc: Luka Perkov Reviewed-by: Vinod Koul +Link: https://lore.kernel.org/r/20200909163831.1894142-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -615,5 +615,79 @@ +@@ -605,5 +605,79 @@ reg = <4>; }; }; diff --git a/target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch b/target/linux/ipq40xx/patches-5.10/0002-v5.12-ARM-dts-qcom-ipq4019-add-more-labels.patch similarity index 74% rename from target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch rename to target/linux/ipq40xx/patches-5.10/0002-v5.12-ARM-dts-qcom-ipq4019-add-more-labels.patch index 0e215ee7cf..d623a9c7b3 100644 --- a/target/linux/ipq40xx/patches-5.10/103-arm-dts-qcom-ipq4019-add-more-labels.patch +++ b/target/linux/ipq40xx/patches-5.10/0002-v5.12-ARM-dts-qcom-ipq4019-add-more-labels.patch @@ -1,12 +1,14 @@ -From caa3ee6b094ee18021943504c938919fcac325ec Mon Sep 17 00:00:00 2001 +From d1ae4c808e7802008225078d93fbadd4aeea1e2d Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Wed, 9 Sep 2020 20:40:33 +0200 -Subject: [PATCH] arm: dts: qcom: ipq4019: add more labels +Date: Wed, 9 Sep 2020 21:56:37 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: add more labels Lets add labels to more commonly used nodes for easier modification in board DTS files. Signed-off-by: Robert Marko Cc: Luka Perkov +Link: https://lore.kernel.org/r/20200909195640.3127341-2-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -22,7 +24,7 @@ Cc: Luka Perkov compatible = "qcom,prng"; reg = <0x22000 0x140>; clocks = <&gcc GCC_PRNG_AHB_CLK>; -@@ -310,7 +310,7 @@ +@@ -300,7 +300,7 @@ status = "disabled"; }; @@ -31,7 +33,7 @@ Cc: Luka Perkov compatible = "qcom,crypto-v5.1"; reg = <0x08e3a000 0x6000>; clocks = <&gcc GCC_CRYPTO_AHB_CLK>, -@@ -396,7 +396,7 @@ +@@ -386,7 +386,7 @@ dma-names = "rx", "tx"; }; diff --git a/target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch b/target/linux/ipq40xx/patches-5.10/0003-v5.12-ARM-dts-qcom-ipq4019-add-SDHCI-VQMMC-LDO-node.patch similarity index 71% rename from target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch rename to target/linux/ipq40xx/patches-5.10/0003-v5.12-ARM-dts-qcom-ipq4019-add-SDHCI-VQMMC-LDO-node.patch index 14affc28c1..1d93fb800a 100644 --- a/target/linux/ipq40xx/patches-5.10/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch +++ b/target/linux/ipq40xx/patches-5.10/0003-v5.12-ARM-dts-qcom-ipq4019-add-SDHCI-VQMMC-LDO-node.patch @@ -1,12 +1,15 @@ -From 77d9b11ae7269dcf376c3b9493209f712524e986 Mon Sep 17 00:00:00 2001 +From e14775aa2feac18e7378cb8009b55c13d4236b50 Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Wed, 22 Jan 2020 12:56:35 +0100 -Subject: [PATCH] arm: dts: IPQ4019: add SDHCI VQMMC LDO node +Date: Mon, 7 Sep 2020 12:19:37 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: add SDHCI VQMMC LDO node Since we now have driver for the SDHCI VQMMC LDO needed for I/0 voltage levels lets introduce the necessary node for it. Signed-off-by: Robert Marko +Cc: Luka Perkov +Link: https://lore.kernel.org/r/20200907101937.10155-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) From e9559182b9061121975285956f19bee06076365a Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 22:36:12 +0200 Subject: [PATCH 48/82] ipq40xx: 5.10: refresh patches to apply Refresh the kernel patches on top of 5.10 so they apply. Manually fixup the 705-net-add-qualcomm-ar40xx-phy.patch to apply. Signed-off-by: Robert Marko --- ...-arm-compressed-add-appended-DTB-section.patch | 8 ++++---- ...essed-set-ipq40xx-watchdog-to-allow-boot.patch | 2 +- ...hci-msm-use-sdhci_set_clock-instead-of-s.patch | 15 +++++++-------- ...-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch | 4 ++-- .../705-net-add-qualcomm-ar40xx-phy.patch | 8 ++++---- .../707-net-phy-Add-Qualcom-QCA807x-driver.patch | 10 +++++----- .../850-soc-add-qualcomm-syscon.patch | 8 ++++---- .../patches-5.10/901-arm-boot-add-dts-files.patch | 4 ++-- .../patches-5.10/997-device_tree_cmdline.patch | 2 +- 9 files changed, 30 insertions(+), 31 deletions(-) diff --git a/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch b/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch index 7e6184fc73..99e33632c4 100644 --- a/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch +++ b/target/linux/ipq40xx/patches-5.10/301-arm-compressed-add-appended-DTB-section.patch @@ -26,7 +26,7 @@ Signed-off-by: Robert Marko --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S -@@ -93,6 +93,13 @@ SECTIONS +@@ -101,6 +101,13 @@ SECTIONS _edata = .; @@ -40,9 +40,9 @@ Signed-off-by: Robert Marko /* * The image_end section appears after any additional loadable sections * that the linker may decide to insert in the binary image. Having -@@ -132,4 +139,4 @@ SECTIONS - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } +@@ -138,4 +145,4 @@ SECTIONS + + ARM_ASSERTS } -ASSERT(_edata_real == _edata, "error: zImage file size is incorrect"); +ASSERT(_edata_real == _edata_dtb, "error: zImage file size is incorrect"); diff --git a/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch b/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch index 71618a40f2..b2239d82dc 100644 --- a/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch +++ b/target/linux/ipq40xx/patches-5.10/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch @@ -22,7 +22,7 @@ Signed-off-by: John Thomson --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S -@@ -599,6 +599,41 @@ not_relocated: mov r0, #0 +@@ -601,6 +601,41 @@ not_relocated: mov r0, #0 bic r4, r4, #1 blne cache_on diff --git a/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch b/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch index e56ab6d0f1..fd46d54916 100644 --- a/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch +++ b/target/linux/ipq40xx/patches-5.10/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch @@ -1,23 +1,22 @@ -From 0e28623a11f3916c1fe5b7e789c7ab8ca932a929 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 22 Jan 2020 13:02:13 +0100 -Subject: [PATCH] mmc: sdhci: sdhci-msm: use sdhci_set_clock instead of - sdhci_msm_set_clock +From f63ea127643a605da97090ce585fdd7c2d17fa42 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 14 Dec 2020 13:35:35 +0100 +Subject: [PATCH] mmc: sdhci-msm: use sdhci_set_clock When using sdhci_msm_set_clock clock setting will fail, so lets use the generic sdhci_set_clock. -Signed-off-by: Robert Marko +Signed-off-by: Robert Marko --- drivers/mmc/host/sdhci-msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c -@@ -1746,7 +1746,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat +@@ -2191,7 +2191,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat static const struct sdhci_ops sdhci_msm_ops = { - .reset = sdhci_reset, + .reset = sdhci_msm_reset, - .set_clock = sdhci_msm_set_clock, + .set_clock = sdhci_set_clock, .get_min_clock = sdhci_msm_get_min_clock, diff --git a/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch b/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch index 167673bd11..c0d99594da 100644 --- a/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch +++ b/target/linux/ipq40xx/patches-5.10/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch @@ -24,7 +24,7 @@ Reviewed-by: Grant Grundler --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -776,6 +776,16 @@ struct xps_map { +@@ -765,6 +765,16 @@ struct xps_map { #define XPS_MIN_MAP_ALLOC ((L1_CACHE_ALIGN(offsetof(struct xps_map, queues[1])) \ - sizeof(struct xps_map)) / sizeof(u16)) @@ -41,7 +41,7 @@ Reviewed-by: Grant Grundler /* * This structure holds all XPS maps for device. Maps are indexed by CPU. */ -@@ -1379,6 +1389,9 @@ struct net_device_ops { +@@ -1445,6 +1455,9 @@ struct net_device_ops { const struct sk_buff *skb, u16 rxq_index, u32 flow_id); diff --git a/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch b/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch index 9adddcabc3..6b0272bd72 100644 --- a/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch +++ b/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -584,6 +584,13 @@ config XILINX_GMII2RGMII +@@ -388,6 +388,13 @@ config XILINX_GMII2RGMII the Reduced Gigabit Media Independent Interface(RGMII) between Ethernet physical media devices and the Gigabit Ethernet controller. @@ -16,11 +16,11 @@ config MICREL_KS8995MA --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -69,6 +69,7 @@ ifdef CONFIG_HWMON +@@ -50,6 +50,7 @@ ifdef CONFIG_HWMON aquantia-objs += aquantia_hwmon.o endif obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o +obj-$(CONFIG_AR40XX_PHY) += ar40xx.o - obj-$(CONFIG_AX88796B_PHY) += ax88796b.o obj-$(CONFIG_AT803X_PHY) += at803x.o - obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o diff --git a/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch b/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch index b71b28d941..55b74d1e56 100644 --- a/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch +++ b/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -25,9 +25,9 @@ Signed-off-by: Robert Marko --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -537,6 +537,12 @@ config NXP_TJA11XX_PHY - ---help--- - Currently supports the NXP TJA1100 and TJA1101 PHY. +@@ -314,6 +314,12 @@ config AT803X_PHY + help + Currently supports the AR8030, AR8031, AR8033 and AR8035 model +config QCA807X_PHY + tristate "Qualcomm QCA807X PHYs" @@ -37,10 +37,10 @@ Signed-off-by: Robert Marko + config QSEMI_PHY tristate "Quality Semiconductor PHYs" - ---help--- + help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -103,6 +103,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc.o +@@ -86,6 +86,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc/ obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o diff --git a/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch b/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch index 17e9047dfb..df0b70d72e 100644 --- a/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch +++ b/target/linux/ipq40xx/patches-5.10/850-soc-add-qualcomm-syscon.patch @@ -2,17 +2,17 @@ From: Christian Lamparter Subject: SoC: add qualcomm syscon --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile -@@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o +@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o +obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o obj-$(CONFIG_QCOM_APR) += apr.o - obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o - obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o + obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o + obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig -@@ -183,6 +183,13 @@ config QCOM_SOCINFO +@@ -189,6 +189,13 @@ config QCOM_SOCINFO Say yes here to support the Qualcomm socinfo driver, providing information about the SoC to user space. diff --git a/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch index 0447fb6012..aef58ee50e 100644 --- a/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch +++ b/target/linux/ipq40xx/patches-5.10/901-arm-boot-add-dts-files.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -837,11 +837,61 @@ dtb-$(CONFIG_ARCH_QCOM) += \ +@@ -902,11 +902,61 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-apq8074-dragonboard.dtb \ qcom-apq8084-ifc6540.dtb \ qcom-apq8084-mtp.dtb \ @@ -70,5 +70,5 @@ Signed-off-by: John Crispin + qcom-ipq4029-gl-s1300.dtb \ + qcom-ipq4029-mr33.dtb \ qcom-ipq8064-ap148.dtb \ + qcom-ipq8064-rb3011.dtb \ qcom-msm8660-surf.dtb \ - qcom-msm8960-cdp.dtb \ diff --git a/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch b/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch index 3cc032fdd2..27d4d7f1e5 100644 --- a/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch +++ b/target/linux/ipq40xx/patches-5.10/997-device_tree_cmdline.patch @@ -1,6 +1,6 @@ --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c -@@ -1059,6 +1059,9 @@ int __init early_init_dt_scan_chosen(uns +@@ -1055,6 +1055,9 @@ int __init early_init_dt_scan_chosen(uns p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); From 80f007fdb203022f632c4e7bb7ff78b1fde80b63 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 22:40:39 +0200 Subject: [PATCH 49/82] ipq40xx: 5.10: add kernel config Copy config from 5.4 and run "make kernel_oldconfig". Select default ("N") for all new symbols. Signed-off-by: Robert Marko [make commit message more explicit] Signed-off-by: Adrian Schmutzler --- target/linux/ipq40xx/config-5.10 | 493 +++++++++++++++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 target/linux/ipq40xx/config-5.10 diff --git a/target/linux/ipq40xx/config-5.10 b/target/linux/ipq40xx/config-5.10 new file mode 100644 index 0000000000..3a78123d52 --- /dev/null +++ b/target/linux/ipq40xx/config-5.10 @@ -0,0 +1,493 @@ +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_APQ_GCC_8084 is not set +# CONFIG_APQ_MMCC_8084 is not set +CONFIG_AR40XX_PHY=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_IPQ40XX=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +# CONFIG_ARCH_MDM9615 is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_ARCH_MSM8960 is not set +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MSM8X60 is not set +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +# CONFIG_ARM_QCOM_CPUFREQ_HW is not set +# CONFIG_ARM_QCOM_CPUFREQ_NVMEM is not set +# CONFIG_ARM_QCOM_SPM_CPUIDLE is not set +# CONFIG_ARM_SMMU is not set +CONFIG_ARM_THUMB=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_AT803X_PHY=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BCH=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_QCOM=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_QCE=y +# CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL is not set +# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set +CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER=y +CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y +CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512 +CONFIG_CRYPTO_DEV_QCOM_RNG=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_REMAP=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_ESSEDMA=y +CONFIG_EXTCON=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_VDSO_32=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_74X164=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_OPTEE=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +# CONFIG_I2C_QCOM_CCI is not set +CONFIG_I2C_QUP=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IO_URING=y +# CONFIG_IPQ_APSS_PLL is not set +CONFIG_IPQ_GCC_4019=y +# CONFIG_IPQ_GCC_6018 is not set +# CONFIG_IPQ_GCC_806X is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_IPQ_LCC_806X is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_KPSS_XCC is not set +# CONFIG_KRAITCC is not set +CONFIG_LEDS_LP5523=y +CONFIG_LEDS_LP5562=y +CONFIG_LEDS_LP55XX_COMMON=y +CONFIG_LIBFDT=y +CONFIG_LLD_VERSION=0 +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_GPIO=y +CONFIG_MDIO_IPQ4019=y +# CONFIG_MDM_GCC_9615 is not set +# CONFIG_MDM_LCC_9615 is not set +CONFIG_MEMFD_CREATE=y +# CONFIG_MFD_HI6421_SPMI is not set +# CONFIG_MFD_QCOM_RPM is not set +# CONFIG_MFD_SPMI_PMIC is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_MSM=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8939 is not set +# CONFIG_MSM_GCC_8960 is not set +# CONFIG_MSM_GCC_8974 is not set +# CONFIG_MSM_GCC_8994 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_GCC_8998 is not set +# CONFIG_MSM_GPUCC_8998 is not set +# CONFIG_MSM_LCC_8960 is not set +# CONFIG_MSM_MMCC_8960 is not set +# CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_MMCC_8996 is not set +# CONFIG_MSM_MMCC_8998 is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_BCH=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_QCOM=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_SPLIT_WRGG_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NLS=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +# CONFIG_NVMEM_SPMI_SDAM is not set +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OPTEE=y +CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1 +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_QCOM=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +CONFIG_PHY_QCOM_IPQ4019_USB=y +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_IPQ806X_USB is not set +# CONFIG_PHY_QCOM_PCIE2 is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 is not set +# CONFIG_PHY_QCOM_USB_HS_28NM is not set +# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set +# CONFIG_PHY_QCOM_USB_SS is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_APQ8084 is not set +CONFIG_PINCTRL_IPQ4019=y +# CONFIG_PINCTRL_IPQ6018 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_MDM9615 is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8226 is not set +# CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8976 is not set +# CONFIG_PINCTRL_MSM8994 is not set +# CONFIG_PINCTRL_MSM8996 is not set +# CONFIG_PINCTRL_MSM8998 is not set +# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +# CONFIG_PINCTRL_QCS404 is not set +# CONFIG_PINCTRL_SC7180 is not set +# CONFIG_PINCTRL_SDM660 is not set +# CONFIG_PINCTRL_SDM845 is not set +# CONFIG_PINCTRL_SM8150 is not set +# CONFIG_PINCTRL_SM8250 is not set +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_QCA807X_PHY=y +CONFIG_QCOM_A53PLL=y +CONFIG_QCOM_BAM_DMA=y +# CONFIG_QCOM_COMMAND_DB is not set +# CONFIG_QCOM_CPR is not set +# CONFIG_QCOM_EBI2 is not set +# CONFIG_QCOM_GENI_SE is not set +# CONFIG_QCOM_GSBI is not set +# CONFIG_QCOM_HFPLL is not set +# CONFIG_QCOM_IOMMU is not set +# CONFIG_QCOM_LLCC is not set +# CONFIG_QCOM_OCMEM is not set +# CONFIG_QCOM_PDC is not set +CONFIG_QCOM_QFPROM=y +# CONFIG_QCOM_RMTFS_MEM is not set +# CONFIG_QCOM_RPMH is not set +CONFIG_QCOM_SCM=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set +CONFIG_QCOM_SMEM=y +# CONFIG_QCOM_SMSM is not set +# CONFIG_QCOM_SOCINFO is not set +CONFIG_QCOM_TCSR=y +# CONFIG_QCOM_TSENS is not set +CONFIG_QCOM_WDT=y +# CONFIG_QCS_GCC_404 is not set +# CONFIG_QCS_Q6SSTOP_404 is not set +# CONFIG_QCS_TURING_404 is not set +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_QCOM_LABIBB is not set +# CONFIG_REGULATOR_QCOM_SPMI is not set +# CONFIG_REGULATOR_QCOM_USB_VBUS is not set +CONFIG_REGULATOR_VCTRL=y +CONFIG_REGULATOR_VQMMC_IPQ4019=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_QCOM_AOSS is not set +# CONFIG_RESET_QCOM_PDC is not set +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +# CONFIG_SC_DISPCC_7180 is not set +# CONFIG_SC_GCC_7180 is not set +# CONFIG_SC_GPUCC_7180 is not set +# CONFIG_SC_LPASS_CORECC_7180 is not set +# CONFIG_SC_MSS_7180 is not set +# CONFIG_SC_VIDEOCC_7180 is not set +# CONFIG_SDM_CAMCC_845 is not set +# CONFIG_SDM_DISPCC_845 is not set +# CONFIG_SDM_GCC_660 is not set +# CONFIG_SDM_GCC_845 is not set +# CONFIG_SDM_GPUCC_845 is not set +# CONFIG_SDM_LPASSCC_845 is not set +# CONFIG_SDM_VIDEOCC_845 is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +# CONFIG_SM_GCC_8150 is not set +# CONFIG_SM_GCC_8250 is not set +# CONFIG_SM_GPUCC_8150 is not set +# CONFIG_SM_GPUCC_8250 is not set +# CONFIG_SM_VIDEOCC_8150 is not set +# CONFIG_SM_VIDEOCC_8250 is not set +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_QUP=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +CONFIG_SPMI_MSM_PMIC_ARB=y +# CONFIG_SPMI_PMIC_CLKDIV is not set +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_LEDS=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_TEE=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y From 603848cad86538061c245004a39e0d5c77cc05d2 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 23:00:51 +0200 Subject: [PATCH 50/82] ipq40xx: net: ethernet: edma: update of_get_phy_mode() for 5.10 In kernel v5.5 of_get_phy_mode had its API changed, so its now returning 0 or errors instead of phymode. Phymode is now returning by passing a pointer to phy_interface_t where it will be stored. Signed-off-by: Robert Marko --- .../drivers/net/ethernet/qualcomm/essedma/edma_axi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c index b5ca99598d..e6739261c3 100644 --- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "edma.h" #include "ess_edma.h" @@ -1184,10 +1185,17 @@ static int edma_axi_probe(struct platform_device *pdev) for (i = 0; i < edma_cinfo->num_gmac; i++) { if (adapter[i]->poll_required) { - int phy_mode = of_get_phy_mode(np); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0) + phy_interface_t phy_mode; + err = of_get_phy_mode(np, &phy_mode); + if (err) + phy_mode = PHY_INTERFACE_MODE_SGMII; +#else + int phy_mode = of_get_phy_mode(np); if (phy_mode < 0) phy_mode = PHY_INTERFACE_MODE_SGMII; +#endif adapter[i]->phydev = phy_connect(edma_netdev[i], (const char *)adapter[i]->phy_id, From ccf214a408592f1783be6e20175105c64b5ddb81 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 23:26:59 +0200 Subject: [PATCH 51/82] ipq40xx: net: ethernet: edma: reject unsupported coalescing params Set ethtool_ops->supported_coalesce_params to let the core reject unsupported coalescing parameters. This driver did not previously reject unsupported parameters. This is a required ethtool op since kernel 5.7. Signed-off-by: Robert Marko --- .../drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c index ac5cb50961..f84cd5aa62 100644 --- a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c +++ b/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "edma.h" struct edma_ethtool_stats { @@ -308,6 +309,9 @@ static void edma_get_ringparam(struct net_device *netdev, /* Ethtool operations */ static const struct ethtool_ops edma_ethtool_ops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0) + .supported_coalesce_params = ETHTOOL_COALESCE_USECS, +#endif .get_drvinfo = &edma_get_drvinfo, .get_link = ðtool_op_get_link, .get_msglevel = &edma_get_msglevel, From f4fb63d2ab4f152fa2950ce7a77cabd16f757d06 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 23:50:20 +0200 Subject: [PATCH 52/82] ipq40xx: 5.10: move AR40xx to MDIO drivers MDIO drivers were moved into their own sub directory of networking drivers. This has caused the AR40xx driver to probe before MDIO drivers and that wont work as it depends on the MDIO bus to be up so it can be fetched. Lets solve it by moving the AR40xx into MDIO folder so they get probed like before. Signed-off-by: Robert Marko --- .../drivers/net/mdio}/ar40xx.c | 0 .../drivers/net/mdio}/ar40xx.h | 0 .../files-5.4/drivers/net/phy/ar40xx.c | 1890 +++++++++++++++++ .../files-5.4/drivers/net/phy/ar40xx.h | 342 +++ .../705-net-add-qualcomm-ar40xx-phy.patch | 45 +- ...7-net-phy-Add-Qualcom-QCA807x-driver.patch | 2 +- 6 files changed, 2256 insertions(+), 23 deletions(-) rename target/linux/ipq40xx/{files/drivers/net/phy => files-5.10/drivers/net/mdio}/ar40xx.c (100%) rename target/linux/ipq40xx/{files/drivers/net/phy => files-5.10/drivers/net/mdio}/ar40xx.h (100%) create mode 100644 target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.c create mode 100644 target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.h diff --git a/target/linux/ipq40xx/files/drivers/net/phy/ar40xx.c b/target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.c similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/phy/ar40xx.c rename to target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.c diff --git a/target/linux/ipq40xx/files/drivers/net/phy/ar40xx.h b/target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.h similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/phy/ar40xx.h rename to target/linux/ipq40xx/files-5.10/drivers/net/mdio/ar40xx.h diff --git a/target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.c b/target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.c new file mode 100644 index 0000000000..f7ce42b9ff --- /dev/null +++ b/target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.c @@ -0,0 +1,1890 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ar40xx.h" + +static struct ar40xx_priv *ar40xx_priv; + +#define MIB_DESC(_s , _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +static const struct ar40xx_mib_desc ar40xx_mibs[] = { + MIB_DESC(1, AR40XX_STATS_RXBROAD, "RxBroad"), + MIB_DESC(1, AR40XX_STATS_RXPAUSE, "RxPause"), + MIB_DESC(1, AR40XX_STATS_RXMULTI, "RxMulti"), + MIB_DESC(1, AR40XX_STATS_RXFCSERR, "RxFcsErr"), + MIB_DESC(1, AR40XX_STATS_RXALIGNERR, "RxAlignErr"), + MIB_DESC(1, AR40XX_STATS_RXRUNT, "RxRunt"), + MIB_DESC(1, AR40XX_STATS_RXFRAGMENT, "RxFragment"), + MIB_DESC(1, AR40XX_STATS_RX64BYTE, "Rx64Byte"), + MIB_DESC(1, AR40XX_STATS_RX128BYTE, "Rx128Byte"), + MIB_DESC(1, AR40XX_STATS_RX256BYTE, "Rx256Byte"), + MIB_DESC(1, AR40XX_STATS_RX512BYTE, "Rx512Byte"), + MIB_DESC(1, AR40XX_STATS_RX1024BYTE, "Rx1024Byte"), + MIB_DESC(1, AR40XX_STATS_RX1518BYTE, "Rx1518Byte"), + MIB_DESC(1, AR40XX_STATS_RXMAXBYTE, "RxMaxByte"), + MIB_DESC(1, AR40XX_STATS_RXTOOLONG, "RxTooLong"), + MIB_DESC(2, AR40XX_STATS_RXGOODBYTE, "RxGoodByte"), + MIB_DESC(2, AR40XX_STATS_RXBADBYTE, "RxBadByte"), + MIB_DESC(1, AR40XX_STATS_RXOVERFLOW, "RxOverFlow"), + MIB_DESC(1, AR40XX_STATS_FILTERED, "Filtered"), + MIB_DESC(1, AR40XX_STATS_TXBROAD, "TxBroad"), + MIB_DESC(1, AR40XX_STATS_TXPAUSE, "TxPause"), + MIB_DESC(1, AR40XX_STATS_TXMULTI, "TxMulti"), + MIB_DESC(1, AR40XX_STATS_TXUNDERRUN, "TxUnderRun"), + MIB_DESC(1, AR40XX_STATS_TX64BYTE, "Tx64Byte"), + MIB_DESC(1, AR40XX_STATS_TX128BYTE, "Tx128Byte"), + MIB_DESC(1, AR40XX_STATS_TX256BYTE, "Tx256Byte"), + MIB_DESC(1, AR40XX_STATS_TX512BYTE, "Tx512Byte"), + MIB_DESC(1, AR40XX_STATS_TX1024BYTE, "Tx1024Byte"), + MIB_DESC(1, AR40XX_STATS_TX1518BYTE, "Tx1518Byte"), + MIB_DESC(1, AR40XX_STATS_TXMAXBYTE, "TxMaxByte"), + MIB_DESC(1, AR40XX_STATS_TXOVERSIZE, "TxOverSize"), + MIB_DESC(2, AR40XX_STATS_TXBYTE, "TxByte"), + MIB_DESC(1, AR40XX_STATS_TXCOLLISION, "TxCollision"), + MIB_DESC(1, AR40XX_STATS_TXABORTCOL, "TxAbortCol"), + MIB_DESC(1, AR40XX_STATS_TXMULTICOL, "TxMultiCol"), + MIB_DESC(1, AR40XX_STATS_TXSINGLECOL, "TxSingleCol"), + MIB_DESC(1, AR40XX_STATS_TXEXCDEFER, "TxExcDefer"), + MIB_DESC(1, AR40XX_STATS_TXDEFER, "TxDefer"), + MIB_DESC(1, AR40XX_STATS_TXLATECOL, "TxLateCol"), +}; + +static u32 +ar40xx_read(struct ar40xx_priv *priv, int reg) +{ + return readl(priv->hw_addr + reg); +} + +static u32 +ar40xx_psgmii_read(struct ar40xx_priv *priv, int reg) +{ + return readl(priv->psgmii_hw_addr + reg); +} + +static void +ar40xx_write(struct ar40xx_priv *priv, int reg, u32 val) +{ + writel(val, priv->hw_addr + reg); +} + +static u32 +ar40xx_rmw(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) +{ + u32 ret; + + ret = ar40xx_read(priv, reg); + ret &= ~mask; + ret |= val; + ar40xx_write(priv, reg, ret); + return ret; +} + +static void +ar40xx_psgmii_write(struct ar40xx_priv *priv, int reg, u32 val) +{ + writel(val, priv->psgmii_hw_addr + reg); +} + +static void +ar40xx_phy_dbg_write(struct ar40xx_priv *priv, int phy_addr, + u16 dbg_addr, u16 dbg_data) +{ + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); + bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA, dbg_data); + mutex_unlock(&bus->mdio_lock); +} + +static void +ar40xx_phy_dbg_read(struct ar40xx_priv *priv, int phy_addr, + u16 dbg_addr, u16 *dbg_data) +{ + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); + *dbg_data = bus->read(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA); + mutex_unlock(&bus->mdio_lock); +} + +static void +ar40xx_phy_mmd_write(struct ar40xx_priv *priv, u32 phy_id, + u16 mmd_num, u16 reg_id, u16 reg_val) +{ + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, mmd_num); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_DATA, reg_id); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, + 0x4000 | mmd_num); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_DATA, reg_val); + mutex_unlock(&bus->mdio_lock); +} + +static u16 +ar40xx_phy_mmd_read(struct ar40xx_priv *priv, u32 phy_id, + u16 mmd_num, u16 reg_id) +{ + u16 value; + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, mmd_num); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_DATA, reg_id); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, + 0x4000 | mmd_num); + value = bus->read(bus, phy_id, AR40XX_MII_ATH_MMD_DATA); + mutex_unlock(&bus->mdio_lock); + return value; +} + +/* Start of swconfig support */ + +static void +ar40xx_phy_poll_reset(struct ar40xx_priv *priv) +{ + u32 i, in_reset, retries = 500; + struct mii_bus *bus = priv->mii_bus; + + /* Assume RESET was recently issued to some or all of the phys */ + in_reset = GENMASK(AR40XX_NUM_PHYS - 1, 0); + + while (retries--) { + /* 1ms should be plenty of time. + * 802.3 spec allows for a max wait time of 500ms + */ + usleep_range(1000, 2000); + + for (i = 0; i < AR40XX_NUM_PHYS; i++) { + int val; + + /* skip devices which have completed reset */ + if (!(in_reset & BIT(i))) + continue; + + val = mdiobus_read(bus, i, MII_BMCR); + if (val < 0) + continue; + + /* mark when phy is no longer in reset state */ + if (!(val & BMCR_RESET)) + in_reset &= ~BIT(i); + } + + if (!in_reset) + return; + } + + dev_warn(&bus->dev, "Failed to reset all phys! (in_reset: 0x%x)\n", + in_reset); +} + +static void +ar40xx_phy_init(struct ar40xx_priv *priv) +{ + int i; + struct mii_bus *bus; + u16 val; + + bus = priv->mii_bus; + for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { + ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); + val &= ~AR40XX_PHY_MANU_CTRL_EN; + ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); + mdiobus_write(bus, i, + MII_ADVERTISE, ADVERTISE_ALL | + ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); + mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + } + + ar40xx_phy_poll_reset(priv); +} + +static void +ar40xx_port_phy_linkdown(struct ar40xx_priv *priv) +{ + struct mii_bus *bus; + int i; + u16 val; + + bus = priv->mii_bus; + for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { + mdiobus_write(bus, i, MII_CTRL1000, 0); + mdiobus_write(bus, i, MII_ADVERTISE, 0); + mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); + val |= AR40XX_PHY_MANU_CTRL_EN; + ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); + /* disable transmit */ + ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_2, &val); + val &= 0xf00f; + ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_2, val); + } +} + +static void +ar40xx_set_mirror_regs(struct ar40xx_priv *priv) +{ + int port; + + /* reset all mirror registers */ + ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, + AR40XX_FWD_CTRL0_MIRROR_PORT, + (0xF << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); + for (port = 0; port < AR40XX_NUM_PORTS; port++) { + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(port), + AR40XX_PORT_LOOKUP_ING_MIRROR_EN, 0); + + ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(port), + AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); + } + + /* now enable mirroring if necessary */ + if (priv->source_port >= AR40XX_NUM_PORTS || + priv->monitor_port >= AR40XX_NUM_PORTS || + priv->source_port == priv->monitor_port) { + return; + } + + ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, + AR40XX_FWD_CTRL0_MIRROR_PORT, + (priv->monitor_port << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); + + if (priv->mirror_rx) + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(priv->source_port), 0, + AR40XX_PORT_LOOKUP_ING_MIRROR_EN); + + if (priv->mirror_tx) + ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(priv->source_port), + 0, AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN); +} + +static int +ar40xx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u8 ports = priv->vlan_table[val->port_vlan]; + int i; + + val->len = 0; + for (i = 0; i < dev->ports; i++) { + struct switch_port *p; + + if (!(ports & BIT(i))) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + if ((priv->vlan_tagged & BIT(i)) || + (priv->pvid[i] != val->port_vlan)) + p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); + else + p->flags = 0; + } + return 0; +} + +static int +ar40xx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u8 *vt = &priv->vlan_table[val->port_vlan]; + int i; + + *vt = 0; + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + + if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { + if (val->port_vlan == priv->pvid[p->id]) + priv->vlan_tagged |= BIT(p->id); + } else { + priv->vlan_tagged &= ~BIT(p->id); + priv->pvid[p->id] = val->port_vlan; + } + + *vt |= BIT(p->id); + } + return 0; +} + +static int +ar40xx_reg_wait(struct ar40xx_priv *priv, u32 reg, u32 mask, u32 val, + unsigned timeout) +{ + int i; + + for (i = 0; i < timeout; i++) { + u32 t; + + t = ar40xx_read(priv, reg); + if ((t & mask) == val) + return 0; + + usleep_range(1000, 2000); + } + + return -ETIMEDOUT; +} + +static int +ar40xx_mib_op(struct ar40xx_priv *priv, u32 op) +{ + int ret; + + lockdep_assert_held(&priv->mib_lock); + + /* Capture the hardware statistics for all ports */ + ar40xx_rmw(priv, AR40XX_REG_MIB_FUNC, + AR40XX_MIB_FUNC, (op << AR40XX_MIB_FUNC_S)); + + /* Wait for the capturing to complete. */ + ret = ar40xx_reg_wait(priv, AR40XX_REG_MIB_FUNC, + AR40XX_MIB_BUSY, 0, 10); + + return ret; +} + +static void +ar40xx_mib_fetch_port_stat(struct ar40xx_priv *priv, int port, bool flush) +{ + unsigned int base; + u64 *mib_stats; + int i; + u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); + + WARN_ON(port >= priv->dev.ports); + + lockdep_assert_held(&priv->mib_lock); + + base = AR40XX_REG_PORT_STATS_START + + AR40XX_REG_PORT_STATS_LEN * port; + + mib_stats = &priv->mib_stats[port * num_mibs]; + if (flush) { + u32 len; + + len = num_mibs * sizeof(*mib_stats); + memset(mib_stats, 0, len); + return; + } + for (i = 0; i < num_mibs; i++) { + const struct ar40xx_mib_desc *mib; + u64 t; + + mib = &ar40xx_mibs[i]; + t = ar40xx_read(priv, base + mib->offset); + if (mib->size == 2) { + u64 hi; + + hi = ar40xx_read(priv, base + mib->offset + 4); + t |= hi << 32; + } + + mib_stats[i] += t; + } +} + +static int +ar40xx_mib_capture(struct ar40xx_priv *priv) +{ + return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_CAPTURE); +} + +static int +ar40xx_mib_flush(struct ar40xx_priv *priv) +{ + return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_FLUSH); +} + +static int +ar40xx_sw_set_reset_mibs(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + unsigned int len; + int ret; + u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); + + mutex_lock(&priv->mib_lock); + + len = priv->dev.ports * num_mibs * sizeof(*priv->mib_stats); + memset(priv->mib_stats, 0, len); + ret = ar40xx_mib_flush(priv); + + mutex_unlock(&priv->mib_lock); + return ret; +} + +static int +ar40xx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + priv->vlan = !!val->value.i; + return 0; +} + +static int +ar40xx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + val->value.i = priv->vlan; + return 0; +} + +static int +ar40xx_sw_set_mirror_rx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->mirror_rx = !!val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_rx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->mirror_rx; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_mirror_tx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->mirror_tx = !!val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_tx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->mirror_tx; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_mirror_monitor_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->monitor_port = val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_monitor_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->monitor_port; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_mirror_source_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->source_port = val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_source_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->source_port; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_linkdown(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + if (val->value.i == 1) + ar40xx_port_phy_linkdown(priv); + else + ar40xx_phy_init(priv); + + return 0; +} + +static int +ar40xx_sw_set_port_reset_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + int port; + int ret; + + port = val->port_vlan; + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->mib_lock); + ret = ar40xx_mib_capture(priv); + if (ret) + goto unlock; + + ar40xx_mib_fetch_port_stat(priv, port, true); + +unlock: + mutex_unlock(&priv->mib_lock); + return ret; +} + +static int +ar40xx_sw_get_port_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u64 *mib_stats; + int port; + int ret; + char *buf = priv->buf; + int i, len = 0; + u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); + + port = val->port_vlan; + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->mib_lock); + ret = ar40xx_mib_capture(priv); + if (ret) + goto unlock; + + ar40xx_mib_fetch_port_stat(priv, port, false); + + len += snprintf(buf + len, sizeof(priv->buf) - len, + "Port %d MIB counters\n", + port); + + mib_stats = &priv->mib_stats[port * num_mibs]; + for (i = 0; i < num_mibs; i++) + len += snprintf(buf + len, sizeof(priv->buf) - len, + "%-12s: %llu\n", + ar40xx_mibs[i].name, + mib_stats[i]); + + val->value.s = buf; + val->len = len; + +unlock: + mutex_unlock(&priv->mib_lock); + return ret; +} + +static int +ar40xx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + priv->vlan_id[val->port_vlan] = val->value.i; + return 0; +} + +static int +ar40xx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + val->value.i = priv->vlan_id[val->port_vlan]; + return 0; +} + +static int +ar40xx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + *vlan = priv->pvid[port]; + return 0; +} + +static int +ar40xx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + /* make sure no invalid PVIDs get set */ + if (vlan >= dev->vlans) + return -EINVAL; + + priv->pvid[port] = vlan; + return 0; +} + +static void +ar40xx_read_port_link(struct ar40xx_priv *priv, int port, + struct switch_port_link *link) +{ + u32 status; + u32 speed; + + memset(link, 0, sizeof(*link)); + + status = ar40xx_read(priv, AR40XX_REG_PORT_STATUS(port)); + + link->aneg = !!(status & AR40XX_PORT_AUTO_LINK_EN); + if (link->aneg || (port != AR40XX_PORT_CPU)) + link->link = !!(status & AR40XX_PORT_STATUS_LINK_UP); + else + link->link = true; + + if (!link->link) + return; + + link->duplex = !!(status & AR40XX_PORT_DUPLEX); + link->tx_flow = !!(status & AR40XX_PORT_STATUS_TXFLOW); + link->rx_flow = !!(status & AR40XX_PORT_STATUS_RXFLOW); + + speed = (status & AR40XX_PORT_SPEED) >> + AR40XX_PORT_STATUS_SPEED_S; + + switch (speed) { + case AR40XX_PORT_SPEED_10M: + link->speed = SWITCH_PORT_SPEED_10; + break; + case AR40XX_PORT_SPEED_100M: + link->speed = SWITCH_PORT_SPEED_100; + break; + case AR40XX_PORT_SPEED_1000M: + link->speed = SWITCH_PORT_SPEED_1000; + break; + default: + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } +} + +static int +ar40xx_sw_get_port_link(struct switch_dev *dev, int port, + struct switch_port_link *link) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + ar40xx_read_port_link(priv, port, link); + return 0; +} + +static const struct switch_attr ar40xx_sw_attr_globals[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "Enable VLAN mode", + .set = ar40xx_sw_set_vlan, + .get = ar40xx_sw_get_vlan, + .max = 1 + }, + { + .type = SWITCH_TYPE_NOVAL, + .name = "reset_mibs", + .description = "Reset all MIB counters", + .set = ar40xx_sw_set_reset_mibs, + }, + { + .type = SWITCH_TYPE_INT, + .name = "enable_mirror_rx", + .description = "Enable mirroring of RX packets", + .set = ar40xx_sw_set_mirror_rx_enable, + .get = ar40xx_sw_get_mirror_rx_enable, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "enable_mirror_tx", + .description = "Enable mirroring of TX packets", + .set = ar40xx_sw_set_mirror_tx_enable, + .get = ar40xx_sw_get_mirror_tx_enable, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "mirror_monitor_port", + .description = "Mirror monitor port", + .set = ar40xx_sw_set_mirror_monitor_port, + .get = ar40xx_sw_get_mirror_monitor_port, + .max = AR40XX_NUM_PORTS - 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "mirror_source_port", + .description = "Mirror source port", + .set = ar40xx_sw_set_mirror_source_port, + .get = ar40xx_sw_get_mirror_source_port, + .max = AR40XX_NUM_PORTS - 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "linkdown", + .description = "Link down all the PHYs", + .set = ar40xx_sw_set_linkdown, + .max = 1 + }, +}; + +static const struct switch_attr ar40xx_sw_attr_port[] = { + { + .type = SWITCH_TYPE_NOVAL, + .name = "reset_mib", + .description = "Reset single port MIB counters", + .set = ar40xx_sw_set_port_reset_mib, + }, + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get port's MIB counters", + .set = NULL, + .get = ar40xx_sw_get_port_mib, + }, +}; + +const struct switch_attr ar40xx_sw_attr_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = ar40xx_sw_set_vid, + .get = ar40xx_sw_get_vid, + .max = 4094, + }, +}; + +/* End of swconfig support */ + +static int +ar40xx_wait_bit(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) +{ + int timeout = 20; + u32 t; + + while (1) { + t = ar40xx_read(priv, reg); + if ((t & mask) == val) + return 0; + + if (timeout-- <= 0) + break; + + usleep_range(10, 20); + } + + pr_err("ar40xx: timeout for reg %08x: %08x & %08x != %08x\n", + (unsigned int)reg, t, mask, val); + return -ETIMEDOUT; +} + +static int +ar40xx_atu_flush(struct ar40xx_priv *priv) +{ + int ret; + + ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_BUSY, 0); + if (!ret) + ar40xx_write(priv, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_OP_FLUSH | + AR40XX_ATU_FUNC_BUSY); + + return ret; +} + +static void +ar40xx_ess_reset(struct ar40xx_priv *priv) +{ + reset_control_assert(priv->ess_rst); + mdelay(10); + reset_control_deassert(priv->ess_rst); + /* Waiting for all inner tables init done. + * It cost 5~10ms. + */ + mdelay(10); + + pr_info("ESS reset ok!\n"); +} + +/* Start of psgmii self test */ + +static void +ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) +{ + u32 n; + struct mii_bus *bus = priv->mii_bus; + /* reset phy psgmii */ + /* fix phy psgmii RX 20bit */ + mdiobus_write(bus, 5, 0x0, 0x005b); + /* reset phy psgmii */ + mdiobus_write(bus, 5, 0x0, 0x001b); + /* release reset phy psgmii */ + mdiobus_write(bus, 5, 0x0, 0x005b); + + for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { + u16 status; + + status = ar40xx_phy_mmd_read(priv, 5, 1, 0x28); + if (status & BIT(0)) + break; + /* Polling interval to check PSGMII PLL in malibu is ready + * the worst time is 8.67ms + * for 25MHz reference clock + * [512+(128+2048)*49]*80ns+100us + */ + mdelay(2); + } + + /*check malibu psgmii calibration done end..*/ + + /*freeze phy psgmii RX CDR*/ + mdiobus_write(bus, 5, 0x1a, 0x2230); + + ar40xx_ess_reset(priv); + + /*check psgmii calibration done start*/ + for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { + u32 status; + + status = ar40xx_psgmii_read(priv, 0xa0); + if (status & BIT(0)) + break; + /* Polling interval to check PSGMII PLL in ESS is ready */ + mdelay(2); + } + + /* check dakota psgmii calibration done end..*/ + + /* relesae phy psgmii RX CDR */ + mdiobus_write(bus, 5, 0x1a, 0x3230); + /* release phy psgmii RX 20bit */ + mdiobus_write(bus, 5, 0x0, 0x005f); +} + +static void +ar40xx_psgmii_single_phy_testing(struct ar40xx_priv *priv, int phy) +{ + int j; + u32 tx_ok, tx_error; + u32 rx_ok, rx_error; + u32 tx_ok_high16; + u32 rx_ok_high16; + u32 tx_all_ok, rx_all_ok; + struct mii_bus *bus = priv->mii_bus; + + mdiobus_write(bus, phy, 0x0, 0x9000); + mdiobus_write(bus, phy, 0x0, 0x4140); + + for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { + u16 status; + + status = mdiobus_read(bus, phy, 0x11); + if (status & AR40XX_PHY_SPEC_STATUS_LINK) + break; + /* the polling interval to check if the PHY link up or not + * maxwait_timer: 750 ms +/-10 ms + * minwait_timer : 1 us +/- 0.1us + * time resides in minwait_timer ~ maxwait_timer + * see IEEE 802.3 section 40.4.5.2 + */ + mdelay(8); + } + + /* enable check */ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0000); + ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0003); + + /* start traffic */ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8020, 0xa000); + /* wait for all traffic end + * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms + */ + mdelay(50); + + /* check counter */ + tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); + tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); + tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); + rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); + rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); + rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); + tx_all_ok = tx_ok + (tx_ok_high16 << 16); + rx_all_ok = rx_ok + (rx_ok_high16 << 16); + if (tx_all_ok == 0x1000 && tx_error == 0) { + /* success */ + priv->phy_t_status &= (~BIT(phy)); + } else { + pr_info("PHY %d single test PSGMII issue happen!\n", phy); + priv->phy_t_status |= BIT(phy); + } + + mdiobus_write(bus, phy, 0x0, 0x1840); +} + +static void +ar40xx_psgmii_all_phy_testing(struct ar40xx_priv *priv) +{ + int phy, j; + struct mii_bus *bus = priv->mii_bus; + + mdiobus_write(bus, 0x1f, 0x0, 0x9000); + mdiobus_write(bus, 0x1f, 0x0, 0x4140); + + for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + u16 status; + + status = mdiobus_read(bus, phy, 0x11); + if (!(status & BIT(10))) + break; + } + + if (phy >= (AR40XX_NUM_PORTS - 1)) + break; + /* The polling interva to check if the PHY link up or not */ + mdelay(8); + } + /* enable check */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0000); + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0003); + + /* start traffic */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0xa000); + /* wait for all traffic end + * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms + */ + mdelay(50); + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + u32 tx_ok, tx_error; + u32 rx_ok, rx_error; + u32 tx_ok_high16; + u32 rx_ok_high16; + u32 tx_all_ok, rx_all_ok; + + /* check counter */ + tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); + tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); + tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); + rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); + rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); + rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); + tx_all_ok = tx_ok + (tx_ok_high16<<16); + rx_all_ok = rx_ok + (rx_ok_high16<<16); + if (tx_all_ok == 0x1000 && tx_error == 0) { + /* success */ + priv->phy_t_status &= ~BIT(phy + 8); + } else { + pr_info("PHY%d test see issue!\n", phy); + priv->phy_t_status |= BIT(phy + 8); + } + } + + pr_debug("PHY all test 0x%x \r\n", priv->phy_t_status); +} + +void +ar40xx_psgmii_self_test(struct ar40xx_priv *priv) +{ + u32 i, phy; + struct mii_bus *bus = priv->mii_bus; + + ar40xx_malibu_psgmii_ess_reset(priv); + + /* switch to access MII reg for copper */ + mdiobus_write(bus, 4, 0x1f, 0x8500); + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + /*enable phy mdio broadcast write*/ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x801f); + } + /* force no link by power down */ + mdiobus_write(bus, 0x1f, 0x0, 0x1840); + /*packet number*/ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x1000); + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8062, 0x05e0); + + /*fix mdi status */ + mdiobus_write(bus, 0x1f, 0x10, 0x6800); + for (i = 0; i < AR40XX_PSGMII_CALB_NUM; i++) { + priv->phy_t_status = 0; + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), + AR40XX_PORT_LOOKUP_LOOPBACK, + AR40XX_PORT_LOOKUP_LOOPBACK); + } + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) + ar40xx_psgmii_single_phy_testing(priv, phy); + + ar40xx_psgmii_all_phy_testing(priv); + + if (priv->phy_t_status) + ar40xx_malibu_psgmii_ess_reset(priv); + else + break; + } + + if (i >= AR40XX_PSGMII_CALB_NUM) + pr_info("PSGMII cannot recover\n"); + else + pr_debug("PSGMII recovered after %d times reset\n", i); + + /* configuration recover */ + /* packet number */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x0); + /* disable check */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0); + /* disable traffic */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0x0); +} + +void +ar40xx_psgmii_self_test_clean(struct ar40xx_priv *priv) +{ + int phy; + struct mii_bus *bus = priv->mii_bus; + + /* disable phy internal loopback */ + mdiobus_write(bus, 0x1f, 0x10, 0x6860); + mdiobus_write(bus, 0x1f, 0x0, 0x9040); + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + /* disable mac loop back */ + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), + AR40XX_PORT_LOOKUP_LOOPBACK, 0); + /* disable phy mdio broadcast write */ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x001f); + } + + /* clear fdb entry */ + ar40xx_atu_flush(priv); +} + +/* End of psgmii self test */ + +static void +ar40xx_mac_mode_init(struct ar40xx_priv *priv, u32 mode) +{ + if (mode == PORT_WRAPPER_PSGMII) { + ar40xx_psgmii_write(priv, AR40XX_PSGMII_MODE_CONTROL, 0x2200); + ar40xx_psgmii_write(priv, AR40XX_PSGMIIPHY_TX_CONTROL, 0x8380); + } +} + +static +int ar40xx_cpuport_setup(struct ar40xx_priv *priv) +{ + u32 t; + + t = AR40XX_PORT_STATUS_TXFLOW | + AR40XX_PORT_STATUS_RXFLOW | + AR40XX_PORT_TXHALF_FLOW | + AR40XX_PORT_DUPLEX | + AR40XX_PORT_SPEED_1000M; + ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); + usleep_range(10, 20); + + t |= AR40XX_PORT_TX_EN | + AR40XX_PORT_RX_EN; + ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); + + return 0; +} + +static void +ar40xx_init_port(struct ar40xx_priv *priv, int port) +{ + u32 t; + + ar40xx_write(priv, AR40XX_REG_PORT_STATUS(port), 0); + + ar40xx_write(priv, AR40XX_REG_PORT_HEADER(port), 0); + + ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), 0); + + t = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH << AR40XX_PORT_VLAN1_OUT_MODE_S; + ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); + + t = AR40XX_PORT_LOOKUP_LEARN; + t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; + ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); +} + +void +ar40xx_init_globals(struct ar40xx_priv *priv) +{ + u32 t; + + /* enable CPU port and disable mirror port */ + t = AR40XX_FWD_CTRL0_CPU_PORT_EN | + AR40XX_FWD_CTRL0_MIRROR_PORT; + ar40xx_write(priv, AR40XX_REG_FWD_CTRL0, t); + + /* forward multicast and broadcast frames to CPU */ + t = (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_UC_FLOOD_S) | + (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_MC_FLOOD_S) | + (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_BC_FLOOD_S); + ar40xx_write(priv, AR40XX_REG_FWD_CTRL1, t); + + /* enable jumbo frames */ + ar40xx_rmw(priv, AR40XX_REG_MAX_FRAME_SIZE, + AR40XX_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); + + /* Enable MIB counters */ + ar40xx_rmw(priv, AR40XX_REG_MODULE_EN, 0, + AR40XX_MODULE_EN_MIB); + + /* Disable AZ */ + ar40xx_write(priv, AR40XX_REG_EEE_CTRL, 0); + + /* set flowctrl thershold for cpu port */ + t = (AR40XX_PORT0_FC_THRESH_ON_DFLT << 16) | + AR40XX_PORT0_FC_THRESH_OFF_DFLT; + ar40xx_write(priv, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), t); +} + +static int +ar40xx_hw_init(struct ar40xx_priv *priv) +{ + u32 i; + + ar40xx_ess_reset(priv); + + if (!priv->mii_bus) + return -1; + + ar40xx_psgmii_self_test(priv); + ar40xx_psgmii_self_test_clean(priv); + + ar40xx_mac_mode_init(priv, priv->mac_mode); + + for (i = 0; i < priv->dev.ports; i++) + ar40xx_init_port(priv, i); + + ar40xx_init_globals(priv); + + return 0; +} + +/* Start of qm error WAR */ + +static +int ar40xx_force_1g_full(struct ar40xx_priv *priv, u32 port_id) +{ + u32 reg; + + if (port_id < 0 || port_id > 6) + return -1; + + reg = AR40XX_REG_PORT_STATUS(port_id); + return ar40xx_rmw(priv, reg, AR40XX_PORT_SPEED, + (AR40XX_PORT_SPEED_1000M | AR40XX_PORT_DUPLEX)); +} + +static +int ar40xx_get_qm_status(struct ar40xx_priv *priv, + u32 port_id, u32 *qm_buffer_err) +{ + u32 reg; + u32 qm_val; + + if (port_id < 1 || port_id > 5) { + *qm_buffer_err = 0; + return -1; + } + + if (port_id < 4) { + reg = AR40XX_REG_QM_PORT0_3_QNUM; + ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); + qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); + /* every 8 bits for each port */ + *qm_buffer_err = (qm_val >> (port_id * 8)) & 0xFF; + } else { + reg = AR40XX_REG_QM_PORT4_6_QNUM; + ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); + qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); + /* every 8 bits for each port */ + *qm_buffer_err = (qm_val >> ((port_id-4) * 8)) & 0xFF; + } + + return 0; +} + +static void +ar40xx_sw_mac_polling_task(struct ar40xx_priv *priv) +{ + static int task_count; + u32 i; + u32 reg, value; + u32 link, speed, duplex; + u32 qm_buffer_err; + u16 port_phy_status[AR40XX_NUM_PORTS]; + static u32 qm_err_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; + static u32 link_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; + struct mii_bus *bus = NULL; + + if (!priv || !priv->mii_bus) + return; + + bus = priv->mii_bus; + + ++task_count; + + for (i = 1; i < AR40XX_NUM_PORTS; ++i) { + port_phy_status[i] = + mdiobus_read(bus, i-1, AR40XX_PHY_SPEC_STATUS); + + speed = FIELD_GET(AR40XX_PHY_SPEC_STATUS_SPEED, + port_phy_status[i]); + link = FIELD_GET(AR40XX_PHY_SPEC_STATUS_LINK, + port_phy_status[i]); + duplex = FIELD_GET(AR40XX_PHY_SPEC_STATUS_DUPLEX, + port_phy_status[i]); + + if (link != priv->ar40xx_port_old_link[i]) { + ++link_cnt[i]; + /* Up --> Down */ + if ((priv->ar40xx_port_old_link[i] == + AR40XX_PORT_LINK_UP) && + (link == AR40XX_PORT_LINK_DOWN)) { + /* LINK_EN disable(MAC force mode)*/ + reg = AR40XX_REG_PORT_STATUS(i); + ar40xx_rmw(priv, reg, + AR40XX_PORT_AUTO_LINK_EN, 0); + + /* Check queue buffer */ + qm_err_cnt[i] = 0; + ar40xx_get_qm_status(priv, i, &qm_buffer_err); + if (qm_buffer_err) { + priv->ar40xx_port_qm_buf[i] = + AR40XX_QM_NOT_EMPTY; + } else { + u16 phy_val = 0; + + priv->ar40xx_port_qm_buf[i] = + AR40XX_QM_EMPTY; + ar40xx_force_1g_full(priv, i); + /* Ref:QCA8337 Datasheet,Clearing + * MENU_CTRL_EN prevents phy to + * stuck in 100BT mode when + * bringing up the link + */ + ar40xx_phy_dbg_read(priv, i-1, + AR40XX_PHY_DEBUG_0, + &phy_val); + phy_val &= (~AR40XX_PHY_MANU_CTRL_EN); + ar40xx_phy_dbg_write(priv, i-1, + AR40XX_PHY_DEBUG_0, + phy_val); + } + priv->ar40xx_port_old_link[i] = link; + } else if ((priv->ar40xx_port_old_link[i] == + AR40XX_PORT_LINK_DOWN) && + (link == AR40XX_PORT_LINK_UP)) { + /* Down --> Up */ + if (priv->port_link_up[i] < 1) { + ++priv->port_link_up[i]; + } else { + /* Change port status */ + reg = AR40XX_REG_PORT_STATUS(i); + value = ar40xx_read(priv, reg); + priv->port_link_up[i] = 0; + + value &= ~(AR40XX_PORT_DUPLEX | + AR40XX_PORT_SPEED); + value |= speed | (duplex ? BIT(6) : 0); + ar40xx_write(priv, reg, value); + /* clock switch need such time + * to avoid glitch + */ + usleep_range(100, 200); + + value |= AR40XX_PORT_AUTO_LINK_EN; + ar40xx_write(priv, reg, value); + /* HW need such time to make sure link + * stable before enable MAC + */ + usleep_range(100, 200); + + if (speed == AR40XX_PORT_SPEED_100M) { + u16 phy_val = 0; + /* Enable @100M, if down to 10M + * clock will change smoothly + */ + ar40xx_phy_dbg_read(priv, i-1, + 0, + &phy_val); + phy_val |= + AR40XX_PHY_MANU_CTRL_EN; + ar40xx_phy_dbg_write(priv, i-1, + 0, + phy_val); + } + priv->ar40xx_port_old_link[i] = link; + } + } + } + + if (priv->ar40xx_port_qm_buf[i] == AR40XX_QM_NOT_EMPTY) { + /* Check QM */ + ar40xx_get_qm_status(priv, i, &qm_buffer_err); + if (qm_buffer_err) { + ++qm_err_cnt[i]; + } else { + priv->ar40xx_port_qm_buf[i] = + AR40XX_QM_EMPTY; + qm_err_cnt[i] = 0; + ar40xx_force_1g_full(priv, i); + } + } + } +} + +static void +ar40xx_qm_err_check_work_task(struct work_struct *work) +{ + struct ar40xx_priv *priv = container_of(work, struct ar40xx_priv, + qm_dwork.work); + + mutex_lock(&priv->qm_lock); + + ar40xx_sw_mac_polling_task(priv); + + mutex_unlock(&priv->qm_lock); + + schedule_delayed_work(&priv->qm_dwork, + msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); +} + +static int +ar40xx_qm_err_check_work_start(struct ar40xx_priv *priv) +{ + mutex_init(&priv->qm_lock); + + INIT_DELAYED_WORK(&priv->qm_dwork, ar40xx_qm_err_check_work_task); + + schedule_delayed_work(&priv->qm_dwork, + msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); + + return 0; +} + +/* End of qm error WAR */ + +static int +ar40xx_vlan_init(struct ar40xx_priv *priv) +{ + int port; + unsigned long bmp; + + /* By default Enable VLAN */ + priv->vlan = 1; + priv->vlan_table[AR40XX_LAN_VLAN] = priv->cpu_bmp | priv->lan_bmp; + priv->vlan_table[AR40XX_WAN_VLAN] = priv->cpu_bmp | priv->wan_bmp; + priv->vlan_tagged = priv->cpu_bmp; + bmp = priv->lan_bmp; + for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) + priv->pvid[port] = AR40XX_LAN_VLAN; + + bmp = priv->wan_bmp; + for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) + priv->pvid[port] = AR40XX_WAN_VLAN; + + return 0; +} + +static void +ar40xx_mib_work_func(struct work_struct *work) +{ + struct ar40xx_priv *priv; + int err; + + priv = container_of(work, struct ar40xx_priv, mib_work.work); + + mutex_lock(&priv->mib_lock); + + err = ar40xx_mib_capture(priv); + if (err) + goto next_port; + + ar40xx_mib_fetch_port_stat(priv, priv->mib_next_port, false); + +next_port: + priv->mib_next_port++; + if (priv->mib_next_port >= priv->dev.ports) + priv->mib_next_port = 0; + + mutex_unlock(&priv->mib_lock); + + schedule_delayed_work(&priv->mib_work, + msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); +} + +static void +ar40xx_setup_port(struct ar40xx_priv *priv, int port, u32 members) +{ + u32 t; + u32 egress, ingress; + u32 pvid = priv->vlan_id[priv->pvid[port]]; + + if (priv->vlan) { + egress = AR40XX_PORT_VLAN1_OUT_MODE_UNMOD; + + ingress = AR40XX_IN_SECURE; + } else { + egress = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH; + ingress = AR40XX_IN_PORT_ONLY; + } + + t = pvid << AR40XX_PORT_VLAN0_DEF_SVID_S; + t |= pvid << AR40XX_PORT_VLAN0_DEF_CVID_S; + ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), t); + + t = AR40XX_PORT_VLAN1_PORT_VLAN_PROP; + t |= egress << AR40XX_PORT_VLAN1_OUT_MODE_S; + + ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); + + t = members; + t |= AR40XX_PORT_LOOKUP_LEARN; + t |= ingress << AR40XX_PORT_LOOKUP_IN_MODE_S; + t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; + ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); +} + +static void +ar40xx_vtu_op(struct ar40xx_priv *priv, u32 op, u32 val) +{ + if (ar40xx_wait_bit(priv, AR40XX_REG_VTU_FUNC1, + AR40XX_VTU_FUNC1_BUSY, 0)) + return; + + if ((op & AR40XX_VTU_FUNC1_OP) == AR40XX_VTU_FUNC1_OP_LOAD) + ar40xx_write(priv, AR40XX_REG_VTU_FUNC0, val); + + op |= AR40XX_VTU_FUNC1_BUSY; + ar40xx_write(priv, AR40XX_REG_VTU_FUNC1, op); +} + +static void +ar40xx_vtu_load_vlan(struct ar40xx_priv *priv, u32 vid, u32 port_mask) +{ + u32 op; + u32 val; + int i; + + op = AR40XX_VTU_FUNC1_OP_LOAD | (vid << AR40XX_VTU_FUNC1_VID_S); + val = AR40XX_VTU_FUNC0_VALID | AR40XX_VTU_FUNC0_IVL; + for (i = 0; i < AR40XX_NUM_PORTS; i++) { + u32 mode; + + if ((port_mask & BIT(i)) == 0) + mode = AR40XX_VTU_FUNC0_EG_MODE_NOT; + else if (priv->vlan == 0) + mode = AR40XX_VTU_FUNC0_EG_MODE_KEEP; + else if ((priv->vlan_tagged & BIT(i)) || + (priv->vlan_id[priv->pvid[i]] != vid)) + mode = AR40XX_VTU_FUNC0_EG_MODE_TAG; + else + mode = AR40XX_VTU_FUNC0_EG_MODE_UNTAG; + + val |= mode << AR40XX_VTU_FUNC0_EG_MODE_S(i); + } + ar40xx_vtu_op(priv, op, val); +} + +static void +ar40xx_vtu_flush(struct ar40xx_priv *priv) +{ + ar40xx_vtu_op(priv, AR40XX_VTU_FUNC1_OP_FLUSH, 0); +} + +static int +ar40xx_sw_hw_apply(struct switch_dev *dev) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u8 portmask[AR40XX_NUM_PORTS]; + int i, j; + + mutex_lock(&priv->reg_mutex); + /* flush all vlan entries */ + ar40xx_vtu_flush(priv); + + memset(portmask, 0, sizeof(portmask)); + if (priv->vlan) { + for (j = 0; j < AR40XX_MAX_VLANS; j++) { + u8 vp = priv->vlan_table[j]; + + if (!vp) + continue; + + for (i = 0; i < dev->ports; i++) { + u8 mask = BIT(i); + + if (vp & mask) + portmask[i] |= vp & ~mask; + } + + ar40xx_vtu_load_vlan(priv, priv->vlan_id[j], + priv->vlan_table[j]); + } + } else { + /* 8021q vlan disabled */ + for (i = 0; i < dev->ports; i++) { + if (i == AR40XX_PORT_CPU) + continue; + + portmask[i] = BIT(AR40XX_PORT_CPU); + portmask[AR40XX_PORT_CPU] |= BIT(i); + } + } + + /* update the port destination mask registers and tag settings */ + for (i = 0; i < dev->ports; i++) + ar40xx_setup_port(priv, i, portmask[i]); + + ar40xx_set_mirror_regs(priv); + + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_reset_switch(struct switch_dev *dev) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + int i, rv; + + mutex_lock(&priv->reg_mutex); + memset(&priv->vlan, 0, sizeof(struct ar40xx_priv) - + offsetof(struct ar40xx_priv, vlan)); + + for (i = 0; i < AR40XX_MAX_VLANS; i++) + priv->vlan_id[i] = i; + + ar40xx_vlan_init(priv); + + priv->mirror_rx = false; + priv->mirror_tx = false; + priv->source_port = 0; + priv->monitor_port = 0; + + mutex_unlock(&priv->reg_mutex); + + rv = ar40xx_sw_hw_apply(dev); + return rv; +} + +static int +ar40xx_start(struct ar40xx_priv *priv) +{ + int ret; + + ret = ar40xx_hw_init(priv); + if (ret) + return ret; + + ret = ar40xx_sw_reset_switch(&priv->dev); + if (ret) + return ret; + + /* at last, setup cpu port */ + ret = ar40xx_cpuport_setup(priv); + if (ret) + return ret; + + schedule_delayed_work(&priv->mib_work, + msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); + + ar40xx_qm_err_check_work_start(priv); + + return 0; +} + +static const struct switch_dev_ops ar40xx_sw_ops = { + .attr_global = { + .attr = ar40xx_sw_attr_globals, + .n_attr = ARRAY_SIZE(ar40xx_sw_attr_globals), + }, + .attr_port = { + .attr = ar40xx_sw_attr_port, + .n_attr = ARRAY_SIZE(ar40xx_sw_attr_port), + }, + .attr_vlan = { + .attr = ar40xx_sw_attr_vlan, + .n_attr = ARRAY_SIZE(ar40xx_sw_attr_vlan), + }, + .get_port_pvid = ar40xx_sw_get_pvid, + .set_port_pvid = ar40xx_sw_set_pvid, + .get_vlan_ports = ar40xx_sw_get_ports, + .set_vlan_ports = ar40xx_sw_set_ports, + .apply_config = ar40xx_sw_hw_apply, + .reset_switch = ar40xx_sw_reset_switch, + .get_port_link = ar40xx_sw_get_port_link, +}; + +/* Platform driver probe function */ + +static int ar40xx_probe(struct platform_device *pdev) +{ + struct device_node *switch_node; + struct device_node *psgmii_node; + struct device_node *mdio_node; + const __be32 *mac_mode; + struct clk *ess_clk; + struct switch_dev *swdev; + struct ar40xx_priv *priv; + u32 len; + u32 num_mibs; + struct resource psgmii_base = {0}; + struct resource switch_base = {0}; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + ar40xx_priv = priv; + + switch_node = of_node_get(pdev->dev.of_node); + if (of_address_to_resource(switch_node, 0, &switch_base) != 0) + return -EIO; + + priv->hw_addr = devm_ioremap_resource(&pdev->dev, &switch_base); + if (IS_ERR(priv->hw_addr)) { + dev_err(&pdev->dev, "Failed to ioremap switch_base!\n"); + return PTR_ERR(priv->hw_addr); + } + + /*psgmii dts get*/ + psgmii_node = of_find_node_by_name(NULL, "ess-psgmii"); + if (!psgmii_node) { + dev_err(&pdev->dev, "Failed to find ess-psgmii node!\n"); + return -EINVAL; + } + + if (of_address_to_resource(psgmii_node, 0, &psgmii_base) != 0) + return -EIO; + + priv->psgmii_hw_addr = devm_ioremap_resource(&pdev->dev, &psgmii_base); + if (IS_ERR(priv->psgmii_hw_addr)) { + dev_err(&pdev->dev, "psgmii ioremap fail!\n"); + return PTR_ERR(priv->psgmii_hw_addr); + } + + mac_mode = of_get_property(switch_node, "switch_mac_mode", &len); + if (!mac_mode) { + dev_err(&pdev->dev, "Failed to read switch_mac_mode\n"); + return -EINVAL; + } + priv->mac_mode = be32_to_cpup(mac_mode); + + ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); + if (ess_clk) + clk_prepare_enable(ess_clk); + + priv->ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); + if (IS_ERR(priv->ess_rst)) { + dev_err(&pdev->dev, "Failed to get ess_rst control!\n"); + return PTR_ERR(priv->ess_rst); + } + + if (of_property_read_u32(switch_node, "switch_cpu_bmp", + &priv->cpu_bmp) || + of_property_read_u32(switch_node, "switch_lan_bmp", + &priv->lan_bmp) || + of_property_read_u32(switch_node, "switch_wan_bmp", + &priv->wan_bmp)) { + dev_err(&pdev->dev, "Failed to read port properties\n"); + return -EIO; + } + + mutex_init(&priv->reg_mutex); + mutex_init(&priv->mib_lock); + INIT_DELAYED_WORK(&priv->mib_work, ar40xx_mib_work_func); + + /* register switch */ + swdev = &priv->dev; + + mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq4019-mdio"); + if (!mdio_node) { + dev_err(&pdev->dev, "Probe failed - Cannot find mdio node by phandle!\n"); + ret = -ENODEV; + goto err_missing_phy; + } + + priv->mii_bus = of_mdio_find_bus(mdio_node); + + if (priv->mii_bus == NULL) { + dev_err(&pdev->dev, "Probe failed - Missing PHYs!\n"); + ret = -ENODEV; + goto err_missing_phy; + } + + swdev->alias = dev_name(&priv->mii_bus->dev); + + swdev->cpu_port = AR40XX_PORT_CPU; + swdev->name = "QCA AR40xx"; + swdev->vlans = AR40XX_MAX_VLANS; + swdev->ports = AR40XX_NUM_PORTS; + swdev->ops = &ar40xx_sw_ops; + ret = register_switch(swdev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "Switch registration failed!\n"); + return ret; + } + + num_mibs = ARRAY_SIZE(ar40xx_mibs); + len = priv->dev.ports * num_mibs * + sizeof(*priv->mib_stats); + priv->mib_stats = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); + if (!priv->mib_stats) { + ret = -ENOMEM; + goto err_unregister_switch; + } + + ar40xx_start(priv); + + return 0; + +err_unregister_switch: + unregister_switch(&priv->dev); +err_missing_phy: + platform_set_drvdata(pdev, NULL); + return ret; +} + +static int ar40xx_remove(struct platform_device *pdev) +{ + struct ar40xx_priv *priv = platform_get_drvdata(pdev); + + cancel_delayed_work_sync(&priv->qm_dwork); + cancel_delayed_work_sync(&priv->mib_work); + + unregister_switch(&priv->dev); + + return 0; +} + +static const struct of_device_id ar40xx_of_mtable[] = { + {.compatible = "qcom,ess-switch" }, + {} +}; + +struct platform_driver ar40xx_drv = { + .probe = ar40xx_probe, + .remove = ar40xx_remove, + .driver = { + .name = "ar40xx", + .of_match_table = ar40xx_of_mtable, + }, +}; + +module_platform_driver(ar40xx_drv); + +MODULE_DESCRIPTION("IPQ40XX ESS driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.h b/target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.h new file mode 100644 index 0000000000..7ba40ccf75 --- /dev/null +++ b/target/linux/ipq40xx/files-5.4/drivers/net/phy/ar40xx.h @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + #ifndef __AR40XX_H +#define __AR40XX_H + +#define AR40XX_MAX_VLANS 128 +#define AR40XX_NUM_PORTS 6 +#define AR40XX_NUM_PHYS 5 + +#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) + +struct ar40xx_priv { + struct switch_dev dev; + + u8 __iomem *hw_addr; + u8 __iomem *psgmii_hw_addr; + u32 mac_mode; + struct reset_control *ess_rst; + u32 cpu_bmp; + u32 lan_bmp; + u32 wan_bmp; + + struct mii_bus *mii_bus; + struct phy_device *phy; + + /* mutex for qm task */ + struct mutex qm_lock; + struct delayed_work qm_dwork; + u32 port_link_up[AR40XX_NUM_PORTS]; + u32 ar40xx_port_old_link[AR40XX_NUM_PORTS]; + u32 ar40xx_port_qm_buf[AR40XX_NUM_PORTS]; + + u32 phy_t_status; + + /* mutex for switch reg access */ + struct mutex reg_mutex; + + /* mutex for mib task */ + struct mutex mib_lock; + struct delayed_work mib_work; + int mib_next_port; + u64 *mib_stats; + + char buf[2048]; + + /* all fields below will be cleared on reset */ + bool vlan; + u16 vlan_id[AR40XX_MAX_VLANS]; + u8 vlan_table[AR40XX_MAX_VLANS]; + u8 vlan_tagged; + u16 pvid[AR40XX_NUM_PORTS]; + + /* mirror */ + bool mirror_rx; + bool mirror_tx; + int source_port; + int monitor_port; +}; + +#define AR40XX_PORT_LINK_UP 1 +#define AR40XX_PORT_LINK_DOWN 0 +#define AR40XX_QM_NOT_EMPTY 1 +#define AR40XX_QM_EMPTY 0 + +#define AR40XX_LAN_VLAN 1 +#define AR40XX_WAN_VLAN 2 + +enum ar40xx_port_wrapper_cfg { + PORT_WRAPPER_PSGMII = 0, +}; + +struct ar40xx_mib_desc { + u32 size; + u32 offset; + const char *name; +}; + +#define AR40XX_PORT_CPU 0 + +#define AR40XX_PSGMII_MODE_CONTROL 0x1b4 +#define AR40XX_PSGMII_ATHR_CSCO_MODE_25M BIT(0) + +#define AR40XX_PSGMIIPHY_TX_CONTROL 0x288 + +#define AR40XX_MII_ATH_MMD_ADDR 0x0d +#define AR40XX_MII_ATH_MMD_DATA 0x0e +#define AR40XX_MII_ATH_DBG_ADDR 0x1d +#define AR40XX_MII_ATH_DBG_DATA 0x1e + +#define AR40XX_STATS_RXBROAD 0x00 +#define AR40XX_STATS_RXPAUSE 0x04 +#define AR40XX_STATS_RXMULTI 0x08 +#define AR40XX_STATS_RXFCSERR 0x0c +#define AR40XX_STATS_RXALIGNERR 0x10 +#define AR40XX_STATS_RXRUNT 0x14 +#define AR40XX_STATS_RXFRAGMENT 0x18 +#define AR40XX_STATS_RX64BYTE 0x1c +#define AR40XX_STATS_RX128BYTE 0x20 +#define AR40XX_STATS_RX256BYTE 0x24 +#define AR40XX_STATS_RX512BYTE 0x28 +#define AR40XX_STATS_RX1024BYTE 0x2c +#define AR40XX_STATS_RX1518BYTE 0x30 +#define AR40XX_STATS_RXMAXBYTE 0x34 +#define AR40XX_STATS_RXTOOLONG 0x38 +#define AR40XX_STATS_RXGOODBYTE 0x3c +#define AR40XX_STATS_RXBADBYTE 0x44 +#define AR40XX_STATS_RXOVERFLOW 0x4c +#define AR40XX_STATS_FILTERED 0x50 +#define AR40XX_STATS_TXBROAD 0x54 +#define AR40XX_STATS_TXPAUSE 0x58 +#define AR40XX_STATS_TXMULTI 0x5c +#define AR40XX_STATS_TXUNDERRUN 0x60 +#define AR40XX_STATS_TX64BYTE 0x64 +#define AR40XX_STATS_TX128BYTE 0x68 +#define AR40XX_STATS_TX256BYTE 0x6c +#define AR40XX_STATS_TX512BYTE 0x70 +#define AR40XX_STATS_TX1024BYTE 0x74 +#define AR40XX_STATS_TX1518BYTE 0x78 +#define AR40XX_STATS_TXMAXBYTE 0x7c +#define AR40XX_STATS_TXOVERSIZE 0x80 +#define AR40XX_STATS_TXBYTE 0x84 +#define AR40XX_STATS_TXCOLLISION 0x8c +#define AR40XX_STATS_TXABORTCOL 0x90 +#define AR40XX_STATS_TXMULTICOL 0x94 +#define AR40XX_STATS_TXSINGLECOL 0x98 +#define AR40XX_STATS_TXEXCDEFER 0x9c +#define AR40XX_STATS_TXDEFER 0xa0 +#define AR40XX_STATS_TXLATECOL 0xa4 + +#define AR40XX_REG_MODULE_EN 0x030 +#define AR40XX_MODULE_EN_MIB BIT(0) + +#define AR40XX_REG_MIB_FUNC 0x034 +#define AR40XX_MIB_BUSY BIT(17) +#define AR40XX_MIB_CPU_KEEP BIT(20) +#define AR40XX_MIB_FUNC BITS(24, 3) +#define AR40XX_MIB_FUNC_S 24 +#define AR40XX_MIB_FUNC_NO_OP 0x0 +#define AR40XX_MIB_FUNC_FLUSH 0x1 + +#define AR40XX_ESS_SERVICE_TAG 0x48 +#define AR40XX_ESS_SERVICE_TAG_STAG BIT(17) + +#define AR40XX_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) +#define AR40XX_PORT_SPEED BITS(0, 2) +#define AR40XX_PORT_STATUS_SPEED_S 0 +#define AR40XX_PORT_TX_EN BIT(2) +#define AR40XX_PORT_RX_EN BIT(3) +#define AR40XX_PORT_STATUS_TXFLOW BIT(4) +#define AR40XX_PORT_STATUS_RXFLOW BIT(5) +#define AR40XX_PORT_DUPLEX BIT(6) +#define AR40XX_PORT_TXHALF_FLOW BIT(7) +#define AR40XX_PORT_STATUS_LINK_UP BIT(8) +#define AR40XX_PORT_AUTO_LINK_EN BIT(9) +#define AR40XX_PORT_STATUS_FLOW_CONTROL BIT(12) + +#define AR40XX_REG_MAX_FRAME_SIZE 0x078 +#define AR40XX_MAX_FRAME_SIZE_MTU BITS(0, 14) + +#define AR40XX_REG_PORT_HEADER(_i) (0x09c + (_i) * 4) + +#define AR40XX_REG_EEE_CTRL 0x100 +#define AR40XX_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) + +#define AR40XX_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) +#define AR40XX_PORT_VLAN0_DEF_SVID BITS(0, 12) +#define AR40XX_PORT_VLAN0_DEF_SVID_S 0 +#define AR40XX_PORT_VLAN0_DEF_CVID BITS(16, 12) +#define AR40XX_PORT_VLAN0_DEF_CVID_S 16 + +#define AR40XX_REG_PORT_VLAN1(_i) (0x424 + (_i) * 0x8) +#define AR40XX_PORT_VLAN1_CORE_PORT BIT(9) +#define AR40XX_PORT_VLAN1_PORT_TLS_MODE BIT(7) +#define AR40XX_PORT_VLAN1_PORT_VLAN_PROP BIT(6) +#define AR40XX_PORT_VLAN1_OUT_MODE BITS(12, 2) +#define AR40XX_PORT_VLAN1_OUT_MODE_S 12 +#define AR40XX_PORT_VLAN1_OUT_MODE_UNMOD 0 +#define AR40XX_PORT_VLAN1_OUT_MODE_UNTAG 1 +#define AR40XX_PORT_VLAN1_OUT_MODE_TAG 2 +#define AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH 3 + +#define AR40XX_REG_VTU_FUNC0 0x0610 +#define AR40XX_VTU_FUNC0_EG_MODE BITS(4, 14) +#define AR40XX_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) +#define AR40XX_VTU_FUNC0_EG_MODE_KEEP 0 +#define AR40XX_VTU_FUNC0_EG_MODE_UNTAG 1 +#define AR40XX_VTU_FUNC0_EG_MODE_TAG 2 +#define AR40XX_VTU_FUNC0_EG_MODE_NOT 3 +#define AR40XX_VTU_FUNC0_IVL BIT(19) +#define AR40XX_VTU_FUNC0_VALID BIT(20) + +#define AR40XX_REG_VTU_FUNC1 0x0614 +#define AR40XX_VTU_FUNC1_OP BITS(0, 3) +#define AR40XX_VTU_FUNC1_OP_NOOP 0 +#define AR40XX_VTU_FUNC1_OP_FLUSH 1 +#define AR40XX_VTU_FUNC1_OP_LOAD 2 +#define AR40XX_VTU_FUNC1_OP_PURGE 3 +#define AR40XX_VTU_FUNC1_OP_REMOVE_PORT 4 +#define AR40XX_VTU_FUNC1_OP_GET_NEXT 5 +#define AR40XX7_VTU_FUNC1_OP_GET_ONE 6 +#define AR40XX_VTU_FUNC1_FULL BIT(4) +#define AR40XX_VTU_FUNC1_PORT BIT(8, 4) +#define AR40XX_VTU_FUNC1_PORT_S 8 +#define AR40XX_VTU_FUNC1_VID BIT(16, 12) +#define AR40XX_VTU_FUNC1_VID_S 16 +#define AR40XX_VTU_FUNC1_BUSY BIT(31) + +#define AR40XX_REG_FWD_CTRL0 0x620 +#define AR40XX_FWD_CTRL0_CPU_PORT_EN BIT(10) +#define AR40XX_FWD_CTRL0_MIRROR_PORT BITS(4, 4) +#define AR40XX_FWD_CTRL0_MIRROR_PORT_S 4 + +#define AR40XX_REG_FWD_CTRL1 0x624 +#define AR40XX_FWD_CTRL1_UC_FLOOD BITS(0, 7) +#define AR40XX_FWD_CTRL1_UC_FLOOD_S 0 +#define AR40XX_FWD_CTRL1_MC_FLOOD BITS(8, 7) +#define AR40XX_FWD_CTRL1_MC_FLOOD_S 8 +#define AR40XX_FWD_CTRL1_BC_FLOOD BITS(16, 7) +#define AR40XX_FWD_CTRL1_BC_FLOOD_S 16 +#define AR40XX_FWD_CTRL1_IGMP BITS(24, 7) +#define AR40XX_FWD_CTRL1_IGMP_S 24 + +#define AR40XX_REG_PORT_LOOKUP(_i) (0x660 + (_i) * 0xc) +#define AR40XX_PORT_LOOKUP_MEMBER BITS(0, 7) +#define AR40XX_PORT_LOOKUP_IN_MODE BITS(8, 2) +#define AR40XX_PORT_LOOKUP_IN_MODE_S 8 +#define AR40XX_PORT_LOOKUP_STATE BITS(16, 3) +#define AR40XX_PORT_LOOKUP_STATE_S 16 +#define AR40XX_PORT_LOOKUP_LEARN BIT(20) +#define AR40XX_PORT_LOOKUP_LOOPBACK BIT(21) +#define AR40XX_PORT_LOOKUP_ING_MIRROR_EN BIT(25) + +#define AR40XX_REG_ATU_FUNC 0x60c +#define AR40XX_ATU_FUNC_OP BITS(0, 4) +#define AR40XX_ATU_FUNC_OP_NOOP 0x0 +#define AR40XX_ATU_FUNC_OP_FLUSH 0x1 +#define AR40XX_ATU_FUNC_OP_LOAD 0x2 +#define AR40XX_ATU_FUNC_OP_PURGE 0x3 +#define AR40XX_ATU_FUNC_OP_FLUSH_LOCKED 0x4 +#define AR40XX_ATU_FUNC_OP_FLUSH_UNICAST 0x5 +#define AR40XX_ATU_FUNC_OP_GET_NEXT 0x6 +#define AR40XX_ATU_FUNC_OP_SEARCH_MAC 0x7 +#define AR40XX_ATU_FUNC_OP_CHANGE_TRUNK 0x8 +#define AR40XX_ATU_FUNC_BUSY BIT(31) + +#define AR40XX_REG_QM_DEBUG_ADDR 0x820 +#define AR40XX_REG_QM_DEBUG_VALUE 0x824 +#define AR40XX_REG_QM_PORT0_3_QNUM 0x1d +#define AR40XX_REG_QM_PORT4_6_QNUM 0x1e + +#define AR40XX_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) +#define AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) + +#define AR40XX_REG_PORT_FLOWCTRL_THRESH(_i) (0x9b0 + (_i) * 0x4) +#define AR40XX_PORT0_FC_THRESH_ON_DFLT 0x60 +#define AR40XX_PORT0_FC_THRESH_OFF_DFLT 0x90 + +#define AR40XX_PHY_DEBUG_0 0 +#define AR40XX_PHY_MANU_CTRL_EN BIT(12) + +#define AR40XX_PHY_DEBUG_2 2 + +#define AR40XX_PHY_SPEC_STATUS 0x11 +#define AR40XX_PHY_SPEC_STATUS_LINK BIT(10) +#define AR40XX_PHY_SPEC_STATUS_DUPLEX BIT(13) +#define AR40XX_PHY_SPEC_STATUS_SPEED BITS(14, 2) + +/* port forwarding state */ +enum { + AR40XX_PORT_STATE_DISABLED = 0, + AR40XX_PORT_STATE_BLOCK = 1, + AR40XX_PORT_STATE_LISTEN = 2, + AR40XX_PORT_STATE_LEARN = 3, + AR40XX_PORT_STATE_FORWARD = 4 +}; + +/* ingress 802.1q mode */ +enum { + AR40XX_IN_PORT_ONLY = 0, + AR40XX_IN_PORT_FALLBACK = 1, + AR40XX_IN_VLAN_ONLY = 2, + AR40XX_IN_SECURE = 3 +}; + +/* egress 802.1q mode */ +enum { + AR40XX_OUT_KEEP = 0, + AR40XX_OUT_STRIP_VLAN = 1, + AR40XX_OUT_ADD_VLAN = 2 +}; + +/* port speed */ +enum { + AR40XX_PORT_SPEED_10M = 0, + AR40XX_PORT_SPEED_100M = 1, + AR40XX_PORT_SPEED_1000M = 2, + AR40XX_PORT_SPEED_ERR = 3, +}; + +#define AR40XX_MIB_WORK_DELAY 2000 /* msecs */ + +#define AR40XX_QM_WORK_DELAY 100 + +#define AR40XX_MIB_FUNC_CAPTURE 0x3 + +#define AR40XX_REG_PORT_STATS_START 0x1000 +#define AR40XX_REG_PORT_STATS_LEN 0x100 + +#define AR40XX_PORTS_ALL 0x3f + +#define AR40XX_PSGMII_ID 5 +#define AR40XX_PSGMII_CALB_NUM 100 +#define AR40XX_MALIBU_PSGMII_MODE_CTRL 0x6d +#define AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL 0x220c +#define AR40XX_MALIBU_PHY_MMD7_DAC_CTRL 0x801a +#define AR40XX_MALIBU_DAC_CTRL_MASK 0x380 +#define AR40XX_MALIBU_DAC_CTRL_VALUE 0x280 +#define AR40XX_MALIBU_PHY_RLP_CTRL 0x805a +#define AR40XX_PSGMII_TX_DRIVER_1_CTRL 0xb +#define AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP 0x8a +#define AR40XX_MALIBU_PHY_LAST_ADDR 4 + +static inline struct ar40xx_priv * +swdev_to_ar40xx(struct switch_dev *swdev) +{ + return container_of(swdev, struct ar40xx_priv, dev); +} + +#endif diff --git a/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch b/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch index 6b0272bd72..cd0b10c6c8 100644 --- a/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch +++ b/target/linux/ipq40xx/patches-5.10/705-net-add-qualcomm-ar40xx-phy.patch @@ -1,26 +1,27 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -388,6 +388,13 @@ config XILINX_GMII2RGMII - the Reduced Gigabit Media Independent Interface(RGMII) between - Ethernet physical media devices and the Gigabit Ethernet controller. +--- a/drivers/net/mdio/Kconfig ++++ b/drivers/net/mdio/Kconfig +@@ -27,6 +27,13 @@ config OF_MDIO + help + OpenFirmware MDIO bus (Ethernet PHY) accessors +config AR40XX_PHY -+ tristate "Driver for Qualcomm Atheros IPQ40XX switches" -+ depends on HAS_IOMEM && OF && OF_MDIO -+ select SWCONFIG -+ help -+ This is the driver for Qualcomm Atheros IPQ40XX ESS switches. ++ tristate "Driver for Qualcomm Atheros IPQ40XX switches" ++ depends on HAS_IOMEM && OF && OF_MDIO ++ select SWCONFIG ++ help ++ This is the driver for Qualcomm Atheros IPQ40XX ESS switches. + - endif # PHYLIB + if MDIO_BUS - config MICREL_KS8995MA ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -50,6 +50,7 @@ ifdef CONFIG_HWMON - aquantia-objs += aquantia_hwmon.o - endif - obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o -+obj-$(CONFIG_AR40XX_PHY) += ar40xx.o - obj-$(CONFIG_AT803X_PHY) += at803x.o - obj-$(CONFIG_AX88796B_PHY) += ax88796b.o - obj-$(CONFIG_BCM54140_PHY) += bcm54140.o + config MDIO_DEVRES +--- a/drivers/net/mdio/Makefile ++++ b/drivers/net/mdio/Makefile +@@ -21,6 +21,8 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i. + obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o + obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o + ++obj-$(CONFIG_AR40XX_PHY) += ar40xx.o ++ + obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o + obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o + obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o diff --git a/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch b/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch index 55b74d1e56..b58797c321 100644 --- a/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch +++ b/target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -40,7 +40,7 @@ Signed-off-by: Robert Marko help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -86,6 +86,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc/ +@@ -85,6 +85,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc/ obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o From 7b1fa276f5a220782f702b099fc68a079c2a0fd5 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 12 Sep 2021 22:41:43 +0200 Subject: [PATCH 53/82] ipq40xx: add testing support for kernel 5.10 Add kernel 5.10 as the testing kernel to ipq40xx to get wider testing. The following devices failed to build with buildbot settings and all feeds installed (apparently due to kernel size): * cell-c rtl30vw * compex wpj428 * devolo magic 2 next * engenius emr3500 * glinet gl-b1300 * glinet gl-s1300 * qcom ap-dk01.1-c1 * qcom ap-dk04.1-c1 Signed-off-by: Robert Marko Tested-by: Nick Hainke [ipq4019/fritzbox-7530 ipq4019/fritzbox-4040 ipq4019/sxtsq-5ac] Tested-by: Szabolcs Hubai [ipq4029/gl-b1300] Tested-by: Stefan Lippers-Hollmann [ipq4019/map-ac2200] [add tested-by and note about failed devices] Signed-off-by: Adrian Schmutzler --- target/linux/ipq40xx/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ipq40xx/Makefile b/target/linux/ipq40xx/Makefile index 400612376c..7b1a0b5b0e 100644 --- a/target/linux/ipq40xx/Makefile +++ b/target/linux/ipq40xx/Makefile @@ -9,7 +9,7 @@ CPU_SUBTYPE:=neon-vfpv4 SUBTARGETS:=generic mikrotik KERNEL_PATCHVER:=5.4 -KERNEL_TESTING_PATCHVER:=5.4 +KERNEL_TESTING_PATCHVER:=5.10 KERNELNAME:=zImage Image dtbs From 3c3b84fd87a604afecb159b7ecd614bfe88eb675 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 17 Sep 2021 12:27:44 +0200 Subject: [PATCH 54/82] kernel: 5.10: backport fix for lp55xx LED driver This backports the upstream commit: leds: lp55xx: Initialize enable GPIO direction to output Without it under kernel 5.10 on Asus MAP-AC2200 the LED driver will fail probing: [ 1.947521] lp5523x: probe of 0-0032 failed with error -22 After the backported fix: [ 1.873236] lp5523x 0-0032: lp5523 Programmable led chip found Signed-off-by: Robert Marko Tested-by: Szabolcs Hubai [ipq4029/gl-b1300] Tested-by: Nick Hainke [ipq4019/fritzbox-7530 ipq4019/fritzbox-4040 ipq4019/sxtsq-5ac] Tested-by: Stefan Lippers-Hollmann [ipq4019/map-ac2200] --- ...ialize-enable-GPIO-direction-to-outp.patch | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 target/linux/generic/backport-5.10/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch diff --git a/target/linux/generic/backport-5.10/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch b/target/linux/generic/backport-5.10/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch new file mode 100644 index 0000000000..75b9947392 --- /dev/null +++ b/target/linux/generic/backport-5.10/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch @@ -0,0 +1,28 @@ +From a5d3d1adc95f4ac5968b7a77ee95a3abbbb96f49 Mon Sep 17 00:00:00 2001 +From: Doug Zobel +Date: Mon, 10 May 2021 15:40:00 -0500 +Subject: [PATCH] leds: lp55xx: Initialize enable GPIO direction to output + +The "Convert to use GPIO descriptors" commit changed the +initialization of the enable GPIO from GPIOF_DIR_OUT to +GPIOD_ASIS. This breaks systems where the GPIO does not +default to output. Changing the enable initialization +to GPIOD_OUT_LOW. + +Signed-off-by: Doug Zobel +Signed-off-by: Pavel Machek +--- + drivers/leds/leds-lp55xx-common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/leds/leds-lp55xx-common.c ++++ b/drivers/leds/leds-lp55xx-common.c +@@ -694,7 +694,7 @@ struct lp55xx_platform_data *lp55xx_of_p + of_property_read_u8(np, "clock-mode", &pdata->clock_mode); + + pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable", +- GPIOD_ASIS); ++ GPIOD_OUT_LOW); + if (IS_ERR(pdata->enable_gpiod)) + return ERR_CAST(pdata->enable_gpiod); + From ac03e246351fbfa98e98f0319cce3a8663f836d3 Mon Sep 17 00:00:00 2001 From: Andrew Cameron Date: Mon, 12 Apr 2021 13:24:33 -0500 Subject: [PATCH 55/82] ath79: add support for TP-Link CPE710-v1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TP-Link CPE710-v1 is an outdoor wireless CPE for 5 GHz with one Ethernet port based on the AP152 reference board Specifications: - SoC: QCA9563-AL3A MIPS 74kc @ 775MHz, AHB @ 258MHz - RAM: 128MiB DDR2 @ 650MHz - Flash: 16MiB SPI NOR Based on the GD25Q128 - Wi-Fi 5Ghz: ath10k chip (802.11ac for up to 867Mbps on 5GHz wireless data rate) Based on the QCA9896 - Ethernet: one 1GbE port - 23dBi high-gain directional 2×2 MIMO antenna and a dedicated metal reflector - Power, LAN, WLAN5G Blue LEDs - 3x Blue LEDs Flashing instructions: Flash factory image through stock firmware WEB UI or through TFTP To get to TFTP recovery just hold reset button while powering on for around 30-40 seconds and release. Rename factory image to recovery.bin Stock TFTP server IP:192.168.0.100 Stock device TFTP address:192.168.0.254 Signed-off-by: Andrew Cameron [convert to nvmem, fix MAC assignment in 11-ath10k-caldata] Signed-off-by: Adrian Schmutzler --- .../ath79/dts/qca9563_tplink_cpe710-v1.dts | 152 ++++++++++++++++++ .../generic/base-files/etc/board.d/01_leds | 3 +- .../generic/base-files/etc/board.d/02_network | 1 + .../etc/hotplug.d/firmware/11-ath10k-caldata | 6 + target/linux/ath79/image/generic-tp-link.mk | 11 ++ tools/firmware-utils/src/tplink-safeloader.c | 37 +++++ 6 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 target/linux/ath79/dts/qca9563_tplink_cpe710-v1.dts diff --git a/target/linux/ath79/dts/qca9563_tplink_cpe710-v1.dts b/target/linux/ath79/dts/qca9563_tplink_cpe710-v1.dts new file mode 100644 index 0000000000..c97d1652cb --- /dev/null +++ b/target/linux/ath79/dts/qca9563_tplink_cpe710-v1.dts @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca956x.dtsi" + +#include +#include + +/ { + model = "TP-Link CPE710 v1"; + compatible = "tplink,cpe710-v1", "qca,qca9563"; + + aliases { + label-mac-device = ð0; + led-boot = &led_lan; + led-failsafe = &led_lan; + led-upgrade = &led_lan; + }; + + leds { + compatible = "gpio-leds"; + + led_lan: lan { + label = "blue:lan"; + gpios = <&gpio 5 GPIO_ACTIVE_LOW>; + }; + + wlan5g { + label = "blue:wlan5g"; + gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "Reset button"; + linux,code = ; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&spi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x000000 0x040000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x040000 0x010000>; + }; + + partition@50000 { + label = "partition-table"; + reg = <0x050000 0x010000>; + read-only; + }; + + info: partition@60000 { + label = "info"; + reg = <0x060000 0x010000>; + read-only; + }; + + partition@70000 { + compatible = "denx,uimage"; + label = "firmware"; + reg = <0x070000 0xf50000>; + }; + + partition@fc0000 { + label = "config"; + reg = <0xfc0000 0x030000>; + read-only; + }; + + art: partition@ff0000 { + label = "art"; + reg = <0xff0000 0x010000>; + read-only; + }; + }; + }; +}; + +&pinmux { + mdio_pins: mdio_pins { + /* GPIO 10 as MDIO(0x20), GPIO 8 as MDC(0x21) */ + pinctrl-single,bits = <0x8 0x00200021 0x00ff00ff>; + }; +}; + +&mdio0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy-mask = <0x10>; + + phy4: ethernet-phy@4 { + reg = <4>; + reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + }; +}; + +ð0 { + status = "okay"; + + phy-handle = <&phy4>; + phy-mode = "sgmii"; + + nvmem-cells = <&macaddr_info_8>; + nvmem-cell-names = "mac-address"; + + qca956x-serdes-fixup; + + gmac-config { + device = <&gmac>; + }; +}; + +&info { + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_info_8: macaddr@8 { + reg = <0x8 0x6>; + }; +}; diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds index ffc6f3086e..1c112b4952 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds @@ -169,7 +169,8 @@ enterasys,ws-ap3705i|\ openmesh,mr900-v1|\ openmesh,mr900-v2|\ openmesh,mr1750-v1|\ -openmesh,mr1750-v2) +openmesh,mr1750-v2|\ +tplink,cpe710-v1) ucidef_set_led_netdev "lan" "LAN" "blue:lan" "eth0" ;; compex,wpj344-16m|\ diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index e2c6f9feac..af4cf08ce0 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -63,6 +63,7 @@ ath79_setup_interfaces() tplink,cpe510-v3|\ tplink,cpe610-v1|\ tplink,cpe610-v2|\ + tplink,cpe710-v1|\ tplink,eap225-outdoor-v1|\ tplink,eap225-v3|\ tplink,eap245-v1|\ diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 5ba1a7a8ff..7f8c1b1143 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -236,6 +236,12 @@ case "$FIRMWARE" in ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ /lib/firmware/ath10k/QCA9888/hw2.0/board.bin ;; + tplink,cpe710-v1) + caldata_extract "art" 0x5000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary info 0x8) + ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ + /lib/firmware/ath10k/QCA9888/hw2.0/board.bin + ;; tplink,eap225-outdoor-v1|\ tplink,eap225-v3|\ tplink,eap225-wall-v2|\ diff --git a/target/linux/ath79/image/generic-tp-link.mk b/target/linux/ath79/image/generic-tp-link.mk index b6755fe547..363be289c6 100644 --- a/target/linux/ath79/image/generic-tp-link.mk +++ b/target/linux/ath79/image/generic-tp-link.mk @@ -362,6 +362,17 @@ define Device/tplink_cpe610-v2 endef TARGET_DEVICES += tplink_cpe610-v2 +define Device/tplink_cpe710-v1 + $(Device/tplink-safeloader-uimage) + SOC := qca9563 + IMAGE_SIZE := 15680k + DEVICE_MODEL := CPE710 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct + TPLINK_BOARD_ID := CPE710V1 +endef +TARGET_DEVICES += tplink_cpe710-v1 + define Device/tplink-eap2x5 $(Device/tplink-safeloader) LOADER_TYPE := elf diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index b20d1fdd30..03329a3926 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -534,6 +534,43 @@ static struct device_info boards[] = { .first_sysupgrade_partition = "os-image", .last_sysupgrade_partition = "support-list", }, + /** Firmware layout for the CPE710 V1 */ + { + .id = "CPE710V1", + .vendor = "CPE710(TP-LINK|UN|AC866-5|00000000):1.0\r\n", + .support_list = + "SupportList:\r\n" + "CPE710(TP-LINK|UN|AC866-5|00000000):1.0\r\n" + "CPE710(TP-LINK|EU|AC866-5|45550000):1.0\r\n" + "CPE710(TP-LINK|US|AC866-5|55530000):1.0\r\n" + "CPE710(TP-LINK|UN|AC866-5):1.0\r\n" + "CPE710(TP-LINK|EU|AC866-5):1.0\r\n" + "CPE710(TP-LINK|US|AC866-5):1.0\r\n", + .part_trail = 0xff, + .soft_ver = SOFT_VER_DEFAULT, + + .partitions = { + {"fs-uboot", 0x00000, 0x50000}, + {"partition-table", 0x50000, 0x02000}, + {"default-mac", 0x60000, 0x00020}, + {"serial-number", 0x60100, 0x00020}, + {"product-info", 0x61100, 0x00100}, + {"device-info", 0x61400, 0x00400}, + {"signature", 0x62000, 0x00400}, + {"device-id", 0x63000, 0x00100}, + {"firmware", 0x70000, 0xf40000}, + {"soft-version", 0xfb0000, 0x00100}, + {"support-list", 0xfb1000, 0x01000}, + {"user-config", 0xfc0000, 0x10000}, + {"default-config", 0xfd0000, 0x10000}, + {"log", 0xfe0000, 0x10000}, + {"radio", 0xff0000, 0x10000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "support-list", + }, { .id = "WBS210", From a9839697896c4fdf8c44a06bbce466ce52493069 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Fri, 20 Aug 2021 13:23:42 +0200 Subject: [PATCH 56/82] ramips: add support for Ubiquiti USW-Flex Hardware -------- MediaTek MT7621AT 16M SPI-NOR Macronix MX25L12835FMI Microchip PD69104B1 4-Channel PoE-PSE controller TI TPS2373 PoE-PD controller PoE-Controller -------------- By default, the PoE outputs do not work with OpenWrt. To make them output power, install the "poemgr" package from the packages feed. This package can control the PD69104B1 PSE controller. Installation ------------ 1. Connect to the booted device at 192.168.1.20 using username/password "ubnt" via SSH. 2. Add the uboot-envtools configuration file /etc/fw_env.config with the following content $ echo "/dev/mtd1 0x0 0x1000 0x10000 1" > /etc/fw_env.config 3. Update the bootloader environment. $ fw_setenv boot_openwrt "fdt addr \$(fdtcontroladdr); fdt rm /signature; bootubnt" $ fw_setenv bootcmd "run boot_openwrt" 4. Transfer the OpenWrt sysupgrade image to the device using SCP. 5. Check the mtd partition number for bs / kernel0 / kernel1 $ cat /proc/mtd 6. Set the bootselect flag to boot from kernel0 $ dd if=/dev/zero bs=1 count=1 of=/dev/mtdblock4 7. Write the OpenWrt sysupgrade image to both kernel0 as well as kernel1 $ dd if=openwrt.bin of=/dev/mtdblock6 $ dd if=openwrt.bin of=/dev/mtdblock7 8. Reboot the device. It should boot into OpenWrt. Restore to UniFi ---------------- To restore the vendor firmware, follow the Ubiquiti UniFi TFTP recovery guide for access points. The process is the same for the Flex switch. Signed-off-by: David Bauer --- .../linux/ramips/dts/mt7621_ubnt_usw-flex.dts | 172 ++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 10 + .../mt7621/base-files/etc/board.d/02_network | 3 + 3 files changed, 185 insertions(+) create mode 100644 target/linux/ramips/dts/mt7621_ubnt_usw-flex.dts diff --git a/target/linux/ramips/dts/mt7621_ubnt_usw-flex.dts b/target/linux/ramips/dts/mt7621_ubnt_usw-flex.dts new file mode 100644 index 0000000000..de5491bf1b --- /dev/null +++ b/target/linux/ramips/dts/mt7621_ubnt_usw-flex.dts @@ -0,0 +1,172 @@ +#include "mt7621.dtsi" + +#include +#include + +/ { + model = "Ubiquiti UniFi Switch Flex"; + compatible = "ubnt,usw-flex", "mediatek,mt7621-soc"; + + aliases { + led-boot = &led_white; + led-failsafe = &led_white; + led-running = &led_blue; + led-upgrade = &led_blue; + label-mac-device = &gmac0; + }; + + chosen { + bootargs-override = "console=ttyS0,115200"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_blue: status_blue { + label = "blue:status"; + gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; + }; + + led_white: status_white { + label = "white:status"; + gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; + }; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + + sda-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>; + + i2c-gpio,delay-us = <50>; + + /* Microsemi PD69104B1 PSE controller */ + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_eeprom>; + nvmem-cell-names = "mac-address"; + label = "dsa"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "lan5"; + }; + }; +}; + +&state_default { + gpio { + groups = "i2c", "uart2", "uart3", "jtag"; + function = "gpio"; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <30000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x60000>; + read-only; + }; + + partition@60000 { + label = "u-boot-env"; + reg = <0x60000 0x10000>; + }; + + partition@70000 { + label = "factory"; + reg = <0x70000 0x10000>; + read-only; + }; + + part_eeprom: partition@80000 { + compatible = "nvmem-cells"; + + #address-cells = <1>; + #size-cells = <1>; + + label = "eeprom"; + reg = <0x80000 0x10000>; + read-only; + + macaddr_eeprom: macaddr@0 { + reg = <0x0 0x6>; + }; + }; + + partition@90000 { + label = "bs"; + reg = <0x90000 0x10000>; + }; + + partition@a0000 { + label = "cfg"; + reg = <0xa0000 0x100000>; + read-only; + }; + + partition@1a0000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x1a0000 0x730000>; + }; + + partition@8d0000 { + label = "kernel1"; + reg = <0x8d0000 0x730000>; + }; + }; + }; +}; + +&xhci { + status = "disabled"; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index d28aa96224..68993a02fb 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1408,6 +1408,16 @@ define Device/ubnt_unifi-nanohd endef TARGET_DEVICES += ubnt_unifi-nanohd +define Device/ubnt_usw-flex + $(Device/dsa-migration) + DEVICE_VENDOR := Ubiquiti + DEVICE_MODEL := UniFi Switch Flex + DEVICE_DTS_CONFIG := config@1 + KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + IMAGE_SIZE := 7360k +endef +TARGET_DEVICES += ubnt_usw-flex + define Device/unielec_u7621-01-16m $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index 16148547f7..47f978baf8 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -67,6 +67,9 @@ ramips_setup_interfaces() ubnt,edgerouter-x-sfp) ucidef_set_interfaces_lan_wan "eth1 eth2 eth3 eth4 eth5" "eth0" ;; + ubnt,usw-flex) + ucidef_set_interface_lan "lan1 lan2 lan3 lan4 lan5" + ;; zyxel,nr7101) ucidef_set_interfaces_lan_wan "lan" "wan" ;; From 1edc7078d6549a7ff39d62318d2879ee72bd0b9d Mon Sep 17 00:00:00 2001 From: David Bauer Date: Fri, 20 Aug 2021 15:52:51 +0200 Subject: [PATCH 57/82] ramips: enable I2C_CHARDEV Expose I2C busses with a chardev device. This is required to control the PSE controller on the Ubiquiti UniFi Flex Switch. Signed-off-by: David Bauer --- target/linux/ramips/mt7621/config-5.4 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ramips/mt7621/config-5.4 b/target/linux/ramips/mt7621/config-5.4 index 46f519fa66..1be4db73fa 100644 --- a/target/linux/ramips/mt7621/config-5.4 +++ b/target/linux/ramips/mt7621/config-5.4 @@ -100,6 +100,7 @@ CONFIG_HIGHMEM=y CONFIG_HZ_PERIODIC=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y CONFIG_I2C_GPIO=y CONFIG_I2C_MT7621=y CONFIG_INITRAMFS_SOURCE="" From 95170b4350ec6dcadd4dc740c130709c46aa6ecb Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 09:32:27 +0900 Subject: [PATCH 58/82] realtek: copy config/files/patches to 5.10 this patch copies the following files from 5.4 to 5.10: - config-5.4 -> config-5.10 - files-5.4/ -> files-5.10/ - patches-5.4/ -> patches-5.10/ Signed-off-by: INAGAKI Hiroshi [rebase on change in files-5.4] Signed-off-by: Adrian Schmutzler --- target/linux/realtek/config-5.10 | 192 ++ .../mips/include/asm/mach-rtl838x/ioremap.h | 34 + .../arch/mips/include/asm/mach-rtl838x/irq.h | 93 + .../include/asm/mach-rtl838x/mach-rtl83xx.h | 418 ++++ .../files-5.10/arch/mips/rtl838x/Makefile | 5 + .../files-5.10/arch/mips/rtl838x/Platform | 6 + .../files-5.10/arch/mips/rtl838x/irq.c | 226 ++ .../files-5.10/arch/mips/rtl838x/prom.c | 183 ++ .../files-5.10/arch/mips/rtl838x/setup.c | 195 ++ .../drivers/clocksource/timer-rtl9300.c | 196 ++ .../files-5.10/drivers/gpio/gpio-rtl8231.c | 340 +++ .../files-5.10/drivers/gpio/gpio-rtl838x.c | 425 ++++ .../drivers/mtd/spi-nor/rtl838x-nor.c | 603 +++++ .../drivers/mtd/spi-nor/rtl838x-spi.h | 111 + .../drivers/net/dsa/rtl83xx/Kconfig | 8 + .../drivers/net/dsa/rtl83xx/Makefile | 3 + .../drivers/net/dsa/rtl83xx/common.c | 722 ++++++ .../drivers/net/dsa/rtl83xx/debugfs.c | 476 ++++ .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 1587 ++++++++++++ .../files-5.10/drivers/net/dsa/rtl83xx/qos.c | 576 +++++ .../drivers/net/dsa/rtl83xx/rtl838x.c | 859 +++++++ .../drivers/net/dsa/rtl83xx/rtl838x.h | 526 ++++ .../drivers/net/dsa/rtl83xx/rtl839x.c | 807 ++++++ .../drivers/net/dsa/rtl83xx/rtl83xx.h | 125 + .../drivers/net/dsa/rtl83xx/rtl930x.c | 1039 ++++++++ .../drivers/net/dsa/rtl83xx/rtl931x.c | 393 +++ .../drivers/net/ethernet/rtl838x_eth.c | 2201 +++++++++++++++++ .../drivers/net/ethernet/rtl838x_eth.h | 429 ++++ .../files-5.10/drivers/net/phy/rtl83xx-phy.c | 1983 +++++++++++++++ .../files-5.10/drivers/net/phy/rtl83xx-phy.h | 60 + .../300-mips-add-rtl838x-platform.patch | 39 + .../301-gpio-add-rtl838x-driver.patch | 32 + .../302-clocksource-add-rtl9300-driver.patch | 34 + ...400-mtd-add-rtl838x-spi-flash-driver.patch | 23 + ...t-dsa-add-support-for-rtl838x-switch.patch | 18 + ...-add-rtl838x-support-for-tag-trailer.patch | 40 + ...a-increase-dsa-max-ports-for-rtl838x.patch | 11 + ...net-add-support-for-rtl838x-ethernet.patch | 26 + ...nclude-linux-add-phy-ops-for-rtl838x.patch | 13 + ...vers-net-phy-eee-support-for-rtl838x.patch | 41 + .../patches-5.10/705-add-rtl-phy.patch | 25 + ...rease-phy-address-number-for-rtl839x.patch | 11 + 42 files changed, 15134 insertions(+) create mode 100644 target/linux/realtek/config-5.10 create mode 100644 target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h create mode 100644 target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h create mode 100644 target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h create mode 100644 target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile create mode 100644 target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform create mode 100644 target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c create mode 100644 target/linux/realtek/files-5.10/arch/mips/rtl838x/prom.c create mode 100644 target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c create mode 100644 target/linux/realtek/files-5.10/drivers/clocksource/timer-rtl9300.c create mode 100644 target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl8231.c create mode 100644 target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c create mode 100644 target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c create mode 100644 target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/qos.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h create mode 100644 target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c create mode 100644 target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h create mode 100644 target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch create mode 100644 target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch create mode 100644 target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch create mode 100644 target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch create mode 100644 target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch create mode 100644 target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch create mode 100644 target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch create mode 100644 target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch create mode 100644 target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch create mode 100644 target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch create mode 100644 target/linux/realtek/patches-5.10/705-add-rtl-phy.patch create mode 100644 target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 new file mode 100644 index 0000000000..5e29879798 --- /dev/null +++ b/target/linux/realtek/config-5.10 @@ -0,0 +1,192 @@ +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_CEVT_R4K=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_HAVE_CLK=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_BOSTON=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_LOAD_STORE_LR=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_RIXI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_8250=y +CONFIG_EFI_EARLYCON=y +CONFIG_ETHERNET_PACKET_MANGLE=y +CONFIG_EXTRA_FIRMWARE="rtl838x_phy/rtl838x_8214fc.fw rtl838x_phy/rtl838x_8218b.fw rtl838x_phy/rtl838x_8380.fw" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_FIXED_PHY=y +CONFIG_FONT_8x16=y +CONFIG_FONT_AUTOSELECT=y +CONFIG_FONT_SUPPORT=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_RTL8231=y +CONFIG_GPIO_RTL838X=y +CONFIG_REALTEK_SOC_PHY=y +CONFIG_GRO_CELLS=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_HWMON=y +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_GPIO=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_JFFS2_ZLIB=y +CONFIG_LEDS_GPIO=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_I2C=y +CONFIG_MEMFD_CREATE=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CBPF_JIT=y +CONFIG_MIPS_CLOCK_VSYSCALL=y +# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set +# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_MIPS_CMDLINE_FROM_DTB=y +# CONFIG_MIPS_ELF_APPENDED_DTB is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_RAW_APPENDED_DTB=y +CONFIG_MIPS_SPRAM=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_BRNIMAGE_FW=y +CONFIG_MTD_SPLIT_EVA_FW=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_TPLINK_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_RTL83XX=y +CONFIG_NET_DSA_TAG_TRAILER=y +CONFIG_NET_RTL838X=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +CONFIG_NVMEM=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_PCI_DRIVERS_LEGACY=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PINCTRL=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_PSB6970_PHY=y +CONFIG_REALTEK_PHY=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RTL838X=y +CONFIG_RTL9300_TIMER=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SFP=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_RTL838X=y +CONFIG_SRCU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TARGET_ISA_REV=2 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y +CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y +CONFIG_USE_OF=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h new file mode 100644 index 0000000000..e7a5bfaffc --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef RTL838X_IOREMAP_H_ +#define RTL838X_IOREMAP_H_ + +static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) +{ + return phys_addr; +} + +static inline int is_rtl838x_internal_registers(phys_addr_t offset) +{ + /* IO-Block */ + if (offset >= 0xb8000000 && offset < 0xb9000000) + return 1; + /* Switch block */ + if (offset >= 0xbb000000 && offset < 0xbc000000) + return 1; + return 0; +} + +static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, + unsigned long flags) +{ + if (is_rtl838x_internal_registers(offset)) + return (void __iomem *)offset; + return NULL; +} + +static inline int plat_iounmap(const volatile void __iomem *addr) +{ + return is_rtl838x_internal_registers((unsigned long)addr); +} + +#endif diff --git a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h new file mode 100644 index 0000000000..a4e95ab511 --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#ifndef _RTL83XX_IRQ_H_ +#define _RTL83XX_IRQ_H_ + +#define NR_IRQS 32 +#include_next + +/* Global Interrupt Mask Register */ +#define RTL83XX_ICTL_GIMR 0x00 +/* Global Interrupt Status Register */ +#define RTL83XX_ICTL_GISR 0x04 + +#define RTL83XX_IRQ_CPU_BASE 0 +#define RTL83XX_IRQ_CPU_NUM 8 +#define RTL83XX_IRQ_ICTL_BASE (RTL83XX_IRQ_CPU_BASE + RTL83XX_IRQ_CPU_NUM) +#define RTL83XX_IRQ_ICTL_NUM 32 + +/* Cascaded interrupts */ +#define RTL83XX_ICTL1_IRQ (RTL83XX_IRQ_CPU_BASE + 2) +#define RTL83XX_ICTL2_IRQ (RTL83XX_IRQ_CPU_BASE + 3) +#define RTL83XX_ICTL3_IRQ (RTL83XX_IRQ_CPU_BASE + 4) +#define RTL83XX_ICTL4_IRQ (RTL83XX_IRQ_CPU_BASE + 5) +#define RTL83XX_ICTL5_IRQ (RTL83XX_IRQ_CPU_BASE + 6) + +/* Interrupt routing register */ +#define RTL83XX_IRR0 0x08 +#define RTL83XX_IRR1 0x0c +#define RTL83XX_IRR2 0x10 +#define RTL83XX_IRR3 0x14 + +/* Cascade map */ +#define UART0_CASCADE 2 +#define UART1_CASCADE 1 +#define TC0_CASCADE 5 +#define TC1_CASCADE 1 +#define TC2_CASCADE 1 +#define TC3_CASCADE 1 +#define TC4_CASCADE 1 +#define OCPTO_CASCADE 1 +#define HLXTO_CASCADE 1 +#define SLXTO_CASCADE 1 +#define NIC_CASCADE 4 +#define GPIO_ABCD_CASCADE 4 +#define GPIO_EFGH_CASCADE 4 +#define RTC_CASCADE 4 +#define SWCORE_CASCADE 3 +#define WDT_IP1_CASCADE 4 +#define WDT_IP2_CASCADE 5 +#define USB_H2_CASCADE 1 + +/* Pack cascade map into interrupt routing registers */ +#define RTL83XX_IRR0_SETTING (\ + (UART0_CASCADE << 28) | \ + (UART1_CASCADE << 24) | \ + (TC0_CASCADE << 20) | \ + (TC1_CASCADE << 16) | \ + (OCPTO_CASCADE << 12) | \ + (HLXTO_CASCADE << 8) | \ + (SLXTO_CASCADE << 4) | \ + (NIC_CASCADE << 0)) +#define RTL83XX_IRR1_SETTING (\ + (GPIO_ABCD_CASCADE << 28) | \ + (GPIO_EFGH_CASCADE << 24) | \ + (RTC_CASCADE << 20) | \ + (SWCORE_CASCADE << 16)) +#define RTL83XX_IRR2_SETTING 0 +#define RTL83XX_IRR3_SETTING 0 + +/* On the RTL8390 there is no GPIO_EFGH and RTC IRQ */ +#define RTL8390_IRR1_SETTING (\ + (GPIO_ABCD_CASCADE << 28) | \ + (SWCORE_CASCADE << 16)) + +/* The RTL9300 has a different external IRQ numbering scheme */ +#define RTL9300_IRR0_SETTING (\ + (UART1_CASCADE << 28) | \ + (UART0_CASCADE << 24) | \ + (USB_H2_CASCADE << 16) | \ + (NIC_CASCADE << 0)) +#define RTL9300_IRR1_SETTING (\ + (SWCORE_CASCADE << 28)) +#define RTL9300_IRR2_SETTING (\ + (GPIO_ABCD_CASCADE << 20) | \ + (TC4_CASCADE << 12) | \ + (TC3_CASCADE << 8) | \ + (TC2_CASCADE << 4) | \ + (TC1_CASCADE << 0)) +#define RTL9300_IRR3_SETTING (\ + (TC0_CASCADE << 28) | \ + (WDT_IP1_CASCADE << 20)) + +#endif /* _RTL83XX_IRQ_H_ */ 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 new file mode 100644 index 0000000000..0abfc6f4d2 --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h @@ -0,0 +1,418 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com) + * Copyright (C) 2020 B. Koblitz + */ +#ifndef _MACH_RTL838X_H_ +#define _MACH_RTL838X_H_ + +#include +/* + * Register access macros + */ + +#define RTL838X_SW_BASE ((volatile void *) 0xBB000000) + +#define rtl83xx_r32(reg) readl(reg) +#define rtl83xx_w32(val, reg) writel(val, reg) +#define rtl83xx_w32_mask(clear, set, reg) rtl83xx_w32((rtl83xx_r32(reg) & ~(clear)) | (set), reg) + +#define rtl83xx_r8(reg) readb(reg) +#define rtl83xx_w8(val, reg) writeb(val, reg) + +#define sw_r32(reg) readl(RTL838X_SW_BASE + reg) +#define sw_w32(val, reg) writel(val, RTL838X_SW_BASE + reg) +#define sw_w32_mask(clear, set, reg) \ + sw_w32((sw_r32(reg) & ~(clear)) | (set), reg) +#define sw_r64(reg) ((((u64)readl(RTL838X_SW_BASE + reg)) << 32) | \ + readl(RTL838X_SW_BASE + reg + 4)) + +#define sw_w64(val, reg) do { \ + writel((u32)((val) >> 32), RTL838X_SW_BASE + reg); \ + writel((u32)((val) & 0xffffffff), \ + RTL838X_SW_BASE + reg + 4); \ + } while (0) + +/* + * SPRAM + */ +#define RTL838X_ISPRAM_BASE 0x0 +#define RTL838X_DSPRAM_BASE 0x0 + +/* + * IRQ Controller + */ +#define RTL838X_IRQ_CPU_BASE 0 +#define RTL838X_IRQ_CPU_NUM 8 +#define RTL838X_IRQ_ICTL_BASE (RTL838X_IRQ_CPU_BASE + RTL838X_IRQ_CPU_NUM) +#define RTL838X_IRQ_ICTL_NUM 32 + +#define RTL83XX_IRQ_UART0 31 +#define RTL83XX_IRQ_UART1 30 +#define RTL83XX_IRQ_TC0 29 +#define RTL83XX_IRQ_TC1 28 +#define RTL83XX_IRQ_OCPTO 27 +#define RTL83XX_IRQ_HLXTO 26 +#define RTL83XX_IRQ_SLXTO 25 +#define RTL83XX_IRQ_NIC 24 +#define RTL83XX_IRQ_GPIO_ABCD 23 +#define RTL83XX_IRQ_GPIO_EFGH 22 +#define RTL83XX_IRQ_RTC 21 +#define RTL83XX_IRQ_SWCORE 20 +#define RTL83XX_IRQ_WDT_IP1 19 +#define RTL83XX_IRQ_WDT_IP2 18 + +#define RTL9300_UART1_IRQ 31 +#define RTL9300_UART0_IRQ 30 +#define RTL9300_USB_H2_IRQ 28 +#define RTL9300_NIC_IRQ 24 +#define RTL9300_SWCORE_IRQ 23 +#define RTL9300_GPIO_ABC_IRQ 13 +#define RTL9300_TC4_IRQ 11 +#define RTL9300_TC3_IRQ 10 +#define RTL9300_TC2_IRQ 9 +#define RTL9300_TC1_IRQ 8 +#define RTL9300_TC0_IRQ 7 + + +/* + * MIPS32R2 counter + */ +#define RTL838X_COMPARE_IRQ (RTL838X_IRQ_CPU_BASE + 7) + +/* + * ICTL + * Base address 0xb8003000UL + */ +#define RTL838X_ICTL1_IRQ (RTL838X_IRQ_CPU_BASE + 2) +#define RTL838X_ICTL2_IRQ (RTL838X_IRQ_CPU_BASE + 3) +#define RTL838X_ICTL3_IRQ (RTL838X_IRQ_CPU_BASE + 4) +#define RTL838X_ICTL4_IRQ (RTL838X_IRQ_CPU_BASE + 5) +#define RTL838X_ICTL5_IRQ (RTL838X_IRQ_CPU_BASE + 6) + +#define GIMR (0x00) +#define UART0_IE (1 << 31) +#define UART1_IE (1 << 30) +#define TC0_IE (1 << 29) +#define TC1_IE (1 << 28) +#define OCPTO_IE (1 << 27) +#define HLXTO_IE (1 << 26) +#define SLXTO_IE (1 << 25) +#define NIC_IE (1 << 24) +#define GPIO_ABCD_IE (1 << 23) +#define GPIO_EFGH_IE (1 << 22) +#define RTC_IE (1 << 21) +#define WDT_IP1_IE (1 << 19) +#define WDT_IP2_IE (1 << 18) + +#define GISR (0x04) +#define UART0_IP (1 << 31) +#define UART1_IP (1 << 30) +#define TC0_IP (1 << 29) +#define TC1_IP (1 << 28) +#define OCPTO_IP (1 << 27) +#define HLXTO_IP (1 << 26) +#define SLXTO_IP (1 << 25) +#define NIC_IP (1 << 24) +#define GPIO_ABCD_IP (1 << 23) +#define GPIO_EFGH_IP (1 << 22) +#define RTC_IP (1 << 21) +#define WDT_IP1_IP (1 << 19) +#define WDT_IP2_IP (1 << 18) + + +/* Interrupt Routing Selection */ +#define UART0_RS 2 +#define UART1_RS 1 +#define TC0_RS 5 +#define TC1_RS 1 +#define OCPTO_RS 1 +#define HLXTO_RS 1 +#define SLXTO_RS 1 +#define NIC_RS 4 +#define GPIO_ABCD_RS 4 +#define GPIO_EFGH_RS 4 +#define RTC_RS 4 +#define SWCORE_RS 3 +#define WDT_IP1_RS 4 +#define WDT_IP2_RS 5 + +/* Interrupt IRQ Assignments */ +#define UART0_IRQ 31 +#define UART1_IRQ 30 +#define TC0_IRQ 29 +#define TC1_IRQ 28 +#define OCPTO_IRQ 27 +#define HLXTO_IRQ 26 +#define SLXTO_IRQ 25 +#define NIC_IRQ 24 +#define GPIO_ABCD_IRQ 23 +#define GPIO_EFGH_IRQ 22 +#define RTC_IRQ 21 +#define SWCORE_IRQ 20 +#define WDT_IP1_IRQ 19 +#define WDT_IP2_IRQ 18 + +#define SYSTEM_FREQ 200000000 +#define RTL838X_UART0_BASE ((volatile void *)(0xb8002000UL)) +#define RTL838X_UART0_BAUD 38400 /* ex. 19200 or 38400 or 57600 or 115200 */ +#define RTL838X_UART0_FREQ (SYSTEM_FREQ - RTL838X_UART0_BAUD * 24) +#define RTL838X_UART0_MAPBASE 0x18002000UL +#define RTL838X_UART0_MAPSIZE 0x100 +#define RTL838X_UART0_IRQ UART0_IRQ + +#define RTL838X_UART1_BASE ((volatile void *)(0xb8002100UL)) +#define RTL838X_UART1_BAUD 38400 /* ex. 19200 or 38400 or 57600 or 115200 */ +#define RTL838X_UART1_FREQ (SYSTEM_FREQ - RTL838X_UART1_BAUD * 24) +#define RTL838X_UART1_MAPBASE 0x18002100UL +#define RTL838X_UART1_MAPSIZE 0x100 +#define RTL838X_UART1_IRQ UART1_IRQ + +#define UART0_RBR (RTL838X_UART0_BASE + 0x000) +#define UART0_THR (RTL838X_UART0_BASE + 0x000) +#define UART0_DLL (RTL838X_UART0_BASE + 0x000) +#define UART0_IER (RTL838X_UART0_BASE + 0x004) +#define UART0_DLM (RTL838X_UART0_BASE + 0x004) +#define UART0_IIR (RTL838X_UART0_BASE + 0x008) +#define UART0_FCR (RTL838X_UART0_BASE + 0x008) +#define UART0_LCR (RTL838X_UART0_BASE + 0x00C) +#define UART0_MCR (RTL838X_UART0_BASE + 0x010) +#define UART0_LSR (RTL838X_UART0_BASE + 0x014) + +#define UART1_RBR (RTL838X_UART1_BASE + 0x000) +#define UART1_THR (RTL838X_UART1_BASE + 0x000) +#define UART1_DLL (RTL838X_UART1_BASE + 0x000) +#define UART1_IER (RTL838X_UART1_BASE + 0x004) +#define UART1_DLM (RTL838X_UART1_BASE + 0x004) +#define UART1_IIR (RTL838X_UART1_BASE + 0x008) +#define UART1_FCR (RTL838X_UART1_BASE + 0x008) +#define UART1_LCR (RTL838X_UART1_BASE + 0x00C) +#define UART1_MCR (RTL838X_UART1_BASE + 0x010) +#define UART1_LSR (RTL838X_UART1_BASE + 0x014) + +/* + * Memory Controller + */ +#define MC_MCR 0xB8001000 +#define MC_MCR_VAL 0x00000000 + +#define MC_DCR 0xB8001004 +#define MC_DCR0_VAL 0x54480000 + +#define MC_DTCR 0xB8001008 +#define MC_DTCR_VAL 0xFFFF05C0 + +/* + * GPIO + */ +#define GPIO_CTRL_REG_BASE ((volatile void *) 0xb8003500) +#define RTL838X_GPIO_PABC_CNR (GPIO_CTRL_REG_BASE + 0x0) +#define RTL838X_GPIO_PABC_TYPE (GPIO_CTRL_REG_BASE + 0x04) +#define RTL838X_GPIO_PABC_DIR (GPIO_CTRL_REG_BASE + 0x8) +#define RTL838X_GPIO_PABC_DATA (GPIO_CTRL_REG_BASE + 0xc) +#define RTL838X_GPIO_PABC_ISR (GPIO_CTRL_REG_BASE + 0x10) +#define RTL838X_GPIO_PAB_IMR (GPIO_CTRL_REG_BASE + 0x14) +#define RTL838X_GPIO_PC_IMR (GPIO_CTRL_REG_BASE + 0x18) + +#define RTL838X_MODEL_NAME_INFO (0x00D4) +#define RTL839X_MODEL_NAME_INFO (0x0FF0) +#define RTL93XX_MODEL_NAME_INFO (0x0004) + +#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 RTL931X_LED_GLB_CTRL (0x0600) + +#define RTL838X_EXT_GPIO_DIR (0xA08C) +#define RTL839X_EXT_GPIO_DIR (0x0214) +#define RTL838X_EXT_GPIO_DATA (0xA094) +#define RTL839X_EXT_GPIO_DATA (0x021c) +#define RTL838X_EXT_GPIO_INDRT_ACCESS (0xA09C) +#define RTL839X_EXT_GPIO_INDRT_ACCESS (0x0224) +#define RTL838X_EXTRA_GPIO_CTRL (0xA0E0) +#define RTL838X_DMY_REG5 (0x0144) +#define RTL838X_EXTRA_GPIO_CTRL (0xA0E0) + +#define RTL838X_GMII_INTF_SEL (0x1000) +#define RTL838X_IO_DRIVING_ABILITY_CTRL (0x1010) + +#define RTL838X_GPIO_A7 31 +#define RTL838X_GPIO_A6 30 +#define RTL838X_GPIO_A5 29 +#define RTL838X_GPIO_A4 28 +#define RTL838X_GPIO_A3 27 +#define RTL838X_GPIO_A2 26 +#define RTL838X_GPIO_A1 25 +#define RTL838X_GPIO_A0 24 +#define RTL838X_GPIO_B7 23 +#define RTL838X_GPIO_B6 22 +#define RTL838X_GPIO_B5 21 +#define RTL838X_GPIO_B4 20 +#define RTL838X_GPIO_B3 19 +#define RTL838X_GPIO_B2 18 +#define RTL838X_GPIO_B1 17 +#define RTL838X_GPIO_B0 16 +#define RTL838X_GPIO_C7 15 +#define RTL838X_GPIO_C6 14 +#define RTL838X_GPIO_C5 13 +#define RTL838X_GPIO_C4 12 +#define RTL838X_GPIO_C3 11 +#define RTL838X_GPIO_C2 10 +#define RTL838X_GPIO_C1 9 +#define RTL838X_GPIO_C0 8 + +#define RTL838X_INT_RW_CTRL (0x0058) +#define RTL838X_EXT_VERSION (0x00D0) +#define RTL838X_PLL_CML_CTRL (0x0FF8) +#define RTL838X_STRAP_DBG (0x100C) + +/* + * Reset + */ +#define RGCR (0x1E70) +#define RTL838X_RST_GLB_CTRL_0 (0x003c) +#define RTL838X_RST_GLB_CTRL_1 (0x0040) +#define RTL839X_RST_GLB_CTRL (0x0014) +#define RTL930X_RST_GLB_CTRL_0 (0x000c) +#define RTL931X_RST_GLB_CTRL (0x0400) + +/* LED control by switch */ +#define RTL838X_LED_MODE_SEL (0x1004) +#define RTL838X_LED_MODE_CTRL (0xA004) +#define RTL838X_LED_P_EN_CTRL (0xA008) + +/* LED control by software */ +#define RTL838X_LED_SW_CTRL (0x0128) +#define RTL839X_LED_SW_CTRL (0xA00C) +#define RTL838X_LED_SW_P_EN_CTRL (0xA010) +#define RTL839X_LED_SW_P_EN_CTRL (0x012C) +#define RTL838X_LED0_SW_P_EN_CTRL (0xA010) +#define RTL839X_LED0_SW_P_EN_CTRL (0x012C) +#define RTL838X_LED1_SW_P_EN_CTRL (0xA014) +#define RTL839X_LED1_SW_P_EN_CTRL (0x0130) +#define RTL838X_LED2_SW_P_EN_CTRL (0xA018) +#define RTL839X_LED2_SW_P_EN_CTRL (0x0134) +#define RTL838X_LED_SW_P_CTRL (0xA01C) +#define RTL839X_LED_SW_P_CTRL (0x0144) + +#define RTL839X_MAC_EFUSE_CTRL (0x02ac) + +/* + * MDIO via Realtek's SMI interface + */ +#define RTL838X_SMI_GLB_CTRL (0xa100) +#define RTL838X_SMI_ACCESS_PHY_CTRL_0 (0xa1b8) +#define RTL838X_SMI_ACCESS_PHY_CTRL_1 (0xa1bc) +#define RTL838X_SMI_ACCESS_PHY_CTRL_2 (0xa1c0) +#define RTL838X_SMI_ACCESS_PHY_CTRL_3 (0xa1c4) +#define RTL838X_SMI_PORT0_5_ADDR_CTRL (0xa1c8) +#define RTL838X_SMI_POLL_CTRL (0xa17c) + +#define RTL839X_SMI_GLB_CTRL (0x03f8) +#define RTL839X_SMI_PORT_POLLING_CTRL (0x03fc) +#define RTL839X_PHYREG_ACCESS_CTRL (0x03DC) +#define RTL839X_PHYREG_CTRL (0x03E0) +#define RTL839X_PHYREG_PORT_CTRL (0x03E4) +#define RTL839X_PHYREG_DATA_CTRL (0x03F0) +#define RTL839X_PHYREG_MMD_CTRL (0x3F4) + +#define RTL930X_SMI_GLB_CTRL (0xCA00) +#define RTL930X_SMI_POLL_CTRL (0xca90) +#define RTL930X_SMI_PORT0_15_POLLING_SEL (0xCA08) +#define RTL930X_SMI_PORT16_27_POLLING_SEL (0xCA0C) +#define RTL930X_SMI_PORT0_5_ADDR (0xCB80) +#define RTL930X_SMI_ACCESS_PHY_CTRL_0 (0xCB70) +#define RTL930X_SMI_ACCESS_PHY_CTRL_1 (0xCB74) +#define RTL930X_SMI_ACCESS_PHY_CTRL_2 (0xCB78) +#define RTL930X_SMI_ACCESS_PHY_CTRL_3 (0xCB7C) + +#define RTL931X_SMI_GLB_CTRL1 (0x0CBC) +#define RTL931X_SMI_GLB_CTRL0 (0x0CC0) +#define RTL931X_SMI_PORT_POLLING_CTRL (0x0CCC) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_0 (0x0C00) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_1 (0x0C04) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_2 (0x0C08) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_3 (0x0C10) +#define RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL (0x0C14) +#define RTL931X_SMI_INDRT_ACCESS_MMD_CTRL (0xC18) + +#define RTL930X_SMI_GLB_CTRL (0xCA00) +#define RTL930X_SMI_POLL_CTRL (0xca90) +#define RTL930X_SMI_PORT0_15_POLLING_SEL (0xCA08) +#define RTL930X_SMI_PORT16_27_POLLING_SEL (0xCA0C) +#define RTL930X_SMI_PORT0_5_ADDR (0xCB80) +#define RTL930X_SMI_ACCESS_PHY_CTRL_0 (0xCB70) +#define RTL930X_SMI_ACCESS_PHY_CTRL_1 (0xCB74) +#define RTL930X_SMI_ACCESS_PHY_CTRL_2 (0xCB78) +#define RTL930X_SMI_ACCESS_PHY_CTRL_3 (0xCB7C) + +#define RTL931X_SMI_GLB_CTRL1 (0x0CBC) +#define RTL931X_SMI_GLB_CTRL0 (0x0CC0) +#define RTL931X_SMI_PORT_POLLING_CTRL (0x0CCC) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_0 (0x0C00) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_1 (0x0C04) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_2 (0x0C08) +#define RTL931X_SMI_INDRT_ACCESS_CTRL_3 (0x0C10) + +/* + * Switch interrupts + */ +#define RTL838X_IMR_GLB (0x1100) +#define RTL838X_IMR_PORT_LINK_STS_CHG (0x1104) +#define RTL838X_ISR_GLB_SRC (0x1148) +#define RTL838X_ISR_PORT_LINK_STS_CHG (0x114C) + +#define RTL839X_IMR_GLB (0x0064) +#define RTL839X_IMR_PORT_LINK_STS_CHG (0x0068) +#define RTL839X_ISR_GLB_SRC (0x009c) +#define RTL839X_ISR_PORT_LINK_STS_CHG (0x00a0) + +#define RTL930X_IMR_GLB (0xC628) +#define RTL930X_IMR_PORT_LINK_STS_CHG (0xC62C) +#define RTL930X_ISR_GLB (0xC658) +#define RTL930X_ISR_PORT_LINK_STS_CHG (0xC660) + +// IMR_GLB does not exit on RTL931X +#define RTL931X_IMR_PORT_LINK_STS_CHG (0x126C) +#define RTL931X_ISR_GLB_SRC (0x12B4) +#define RTL931X_ISR_PORT_LINK_STS_CHG (0x12B8) + +/* Definition of family IDs */ +#define RTL8389_FAMILY_ID (0x8389) +#define RTL8328_FAMILY_ID (0x8328) +#define RTL8390_FAMILY_ID (0x8390) +#define RTL8350_FAMILY_ID (0x8350) +#define RTL8380_FAMILY_ID (0x8380) +#define RTL8330_FAMILY_ID (0x8330) +#define RTL9300_FAMILY_ID (0x9300) +#define RTL9310_FAMILY_ID (0x9310) + +/* Basic SoC Features */ +#define RTL838X_CPU_PORT 28 +#define RTL839X_CPU_PORT 52 +#define RTL930X_CPU_PORT 28 +#define RTL931X_CPU_PORT 56 + +struct rtl83xx_soc_info { + unsigned char *name; + unsigned int id; + unsigned int family; + unsigned char *compatible; + volatile void *sw_base; + volatile void *icu_base; + int cpu_port; +}; + +/* rtl83xx-related functions used across subsystems */ +int rtl838x_smi_wait_op(int timeout); +int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val); + +#endif /* _MACH_RTL838X_H_ */ diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile new file mode 100644 index 0000000000..8212dc3f48 --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the rtl838x specific parts of the kernel +# + +obj-y := setup.o prom.o irq.o diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform new file mode 100644 index 0000000000..4d48932d80 --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform @@ -0,0 +1,6 @@ +# +# Realtek RTL838x SoCs +# +platform-$(CONFIG_RTL838X) += rtl838x/ +cflags-$(CONFIG_RTL838X) += -I$(srctree)/arch/mips/include/asm/mach-rtl838x/ +load-$(CONFIG_RTL838X) += 0xffffffff80000000 diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c b/target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c new file mode 100644 index 0000000000..c0dd2f608c --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Realtek RTL83XX architecture specific IRQ handling + * + * based on the original BSP + * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com) + * Copyright (C) 2020 B. Koblitz + * Copyright (C) 2020 Bert Vermeulen + * Copyright (C) 2020 John Crispin + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "irq.h" + +#define REALTEK_CPU_IRQ_SHARED0 (MIPS_CPU_IRQ_BASE + 2) +#define REALTEK_CPU_IRQ_UART (MIPS_CPU_IRQ_BASE + 3) +#define REALTEK_CPU_IRQ_SWITCH (MIPS_CPU_IRQ_BASE + 4) +#define REALTEK_CPU_IRQ_SHARED1 (MIPS_CPU_IRQ_BASE + 5) +#define REALTEK_CPU_IRQ_EXTERNAL (MIPS_CPU_IRQ_BASE + 6) +#define REALTEK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7) + +#define REG(x) (rtl83xx_ictl_base + x) + +extern struct rtl83xx_soc_info soc_info; + +static DEFINE_RAW_SPINLOCK(irq_lock); +static void __iomem *rtl83xx_ictl_base; + +static void rtl83xx_ictl_enable_irq(struct irq_data *i) +{ + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&irq_lock, flags); + + value = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)); + value |= BIT(i->hwirq); + rtl83xx_w32(value, REG(RTL83XX_ICTL_GIMR)); + + raw_spin_unlock_irqrestore(&irq_lock, flags); +} + +static void rtl83xx_ictl_disable_irq(struct irq_data *i) +{ + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&irq_lock, flags); + + value = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)); + value &= ~BIT(i->hwirq); + rtl83xx_w32(value, REG(RTL83XX_ICTL_GIMR)); + + raw_spin_unlock_irqrestore(&irq_lock, flags); +} + +static struct irq_chip rtl83xx_ictl_irq = { + .name = "RTL83xx", + .irq_enable = rtl83xx_ictl_enable_irq, + .irq_disable = rtl83xx_ictl_disable_irq, + .irq_ack = rtl83xx_ictl_disable_irq, + .irq_mask = rtl83xx_ictl_disable_irq, + .irq_unmask = rtl83xx_ictl_enable_irq, + .irq_eoi = rtl83xx_ictl_enable_irq, +}; + +static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ + irq_set_chip_and_handler(hw, &rtl83xx_ictl_irq, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops irq_domain_ops = { + .map = intc_map, + .xlate = irq_domain_xlate_onecell, +}; + +static void rtl838x_irq_dispatch(struct irq_desc *desc) +{ + unsigned int pending = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)) & + rtl83xx_r32(REG(RTL83XX_ICTL_GISR)); + + if (pending) { + struct irq_domain *domain = irq_desc_get_handler_data(desc); + generic_handle_irq(irq_find_mapping(domain, __ffs(pending))); + } else { + spurious_interrupt(); + } +} + +asmlinkage void plat_rtl83xx_irq_dispatch(void) +{ + unsigned int pending; + + pending = read_c0_cause() & read_c0_status() & ST0_IM; + + if (pending & CAUSEF_IP7) + do_IRQ(REALTEK_CPU_IRQ_COUNTER); + + else if (pending & CAUSEF_IP6) + do_IRQ(REALTEK_CPU_IRQ_EXTERNAL); + + else if (pending & CAUSEF_IP5) + do_IRQ(REALTEK_CPU_IRQ_SHARED1); + + else if (pending & CAUSEF_IP4) + do_IRQ(REALTEK_CPU_IRQ_SWITCH); + + else if (pending & CAUSEF_IP3) + do_IRQ(REALTEK_CPU_IRQ_UART); + + else if (pending & CAUSEF_IP2) + do_IRQ(REALTEK_CPU_IRQ_SHARED0); + + else + spurious_interrupt(); +} + +static int icu_setup_domain(struct device_node *node) +{ + struct irq_domain *domain; + + domain = irq_domain_add_simple(node, 32, 0, + &irq_domain_ops, NULL); + irq_set_chained_handler_and_data(2, rtl838x_irq_dispatch, domain); + irq_set_chained_handler_and_data(3, rtl838x_irq_dispatch, domain); + irq_set_chained_handler_and_data(4, rtl838x_irq_dispatch, domain); + irq_set_chained_handler_and_data(5, rtl838x_irq_dispatch, domain); + + rtl83xx_ictl_base = of_iomap(node, 0); + if (!rtl83xx_ictl_base) + return -EINVAL; + + return 0; +} + +static void __init rtl8380_icu_of_init(struct device_node *node, struct device_node *parent) +{ + if (icu_setup_domain(node)) + return; + + /* Disable all cascaded interrupts */ + rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR)); + + /* Set up interrupt routing */ + rtl83xx_w32(RTL83XX_IRR0_SETTING, REG(RTL83XX_IRR0)); + rtl83xx_w32(RTL83XX_IRR1_SETTING, REG(RTL83XX_IRR1)); + rtl83xx_w32(RTL83XX_IRR2_SETTING, REG(RTL83XX_IRR2)); + rtl83xx_w32(RTL83XX_IRR3_SETTING, REG(RTL83XX_IRR3)); + + /* Clear timer interrupt */ + write_c0_compare(0); + + /* Enable all CPU interrupts */ + write_c0_status(read_c0_status() | ST0_IM); + + /* Enable timer0 and uart0 interrupts */ + rtl83xx_w32(BIT(RTL83XX_IRQ_TC0) | BIT(RTL83XX_IRQ_UART0), REG(RTL83XX_ICTL_GIMR)); +} + +static void __init rtl8390_icu_of_init(struct device_node *node, struct device_node *parent) +{ + if (icu_setup_domain(node)) + return; + + /* Disable all cascaded interrupts */ + rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR)); + + /* Set up interrupt routing */ + rtl83xx_w32(RTL83XX_IRR0_SETTING, REG(RTL83XX_IRR0)); + rtl83xx_w32(RTL8390_IRR1_SETTING, REG(RTL83XX_IRR1)); + rtl83xx_w32(RTL83XX_IRR2_SETTING, REG(RTL83XX_IRR2)); + rtl83xx_w32(RTL83XX_IRR3_SETTING, REG(RTL83XX_IRR3)); + + /* Clear timer interrupt */ + write_c0_compare(0); + + /* Enable all CPU interrupts */ + write_c0_status(read_c0_status() | ST0_IM); + + /* Enable timer0 and uart0 interrupts */ + rtl83xx_w32(BIT(RTL83XX_IRQ_TC0) | BIT(RTL83XX_IRQ_UART0), REG(RTL83XX_ICTL_GIMR)); +} + +static void __init rtl9300_icu_of_init(struct device_node *node, struct device_node *parent) +{ + pr_info("RTL9300: Setting up IRQs\n"); + if (icu_setup_domain(node)) + return; + + /* Disable all cascaded interrupts */ + rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR)); + + /* Set up interrupt routing */ + rtl83xx_w32(RTL9300_IRR0_SETTING, REG(RTL83XX_IRR0)); + rtl83xx_w32(RTL9300_IRR1_SETTING, REG(RTL83XX_IRR1)); + rtl83xx_w32(RTL9300_IRR2_SETTING, REG(RTL83XX_IRR2)); + rtl83xx_w32(RTL9300_IRR3_SETTING, REG(RTL83XX_IRR3)); + + /* Clear timer interrupt */ + write_c0_compare(0); + + /* Enable all CPU interrupts */ + write_c0_status(read_c0_status() | ST0_IM); +} + +static struct of_device_id __initdata of_irq_ids[] = { + { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init }, + { .compatible = "realtek,rt8380-intc", .data = rtl8380_icu_of_init }, + { .compatible = "realtek,rt8390-intc", .data = rtl8390_icu_of_init }, + { .compatible = "realtek,rt9300-intc", .data = rtl9300_icu_of_init }, + {}, +}; + +void __init arch_init_irq(void) +{ + of_irq_init(of_irq_ids); +} diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/prom.c b/target/linux/realtek/files-5.10/arch/mips/rtl838x/prom.c new file mode 100644 index 0000000000..3390c04334 --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/prom.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * prom.c + * Early intialization code for the Realtek RTL838X SoC + * + * based on the original BSP by + * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com) + * Copyright (C) 2020 B. Koblitz + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern char arcs_cmdline[]; +extern const char __appended_dtb; + +struct rtl83xx_soc_info soc_info; +const void *fdt; + +const char *get_system_type(void) +{ + return soc_info.name; +} + +void __init prom_free_prom_memory(void) +{ + +} + +void __init device_tree_init(void) +{ + if (!fdt_check_header(&__appended_dtb)) { + fdt = &__appended_dtb; + pr_info("Using appended Device Tree.\n"); + } + initial_boot_params = (void *)fdt; + unflatten_and_copy_device_tree(); +} + +static void __init prom_init_cmdline(void) +{ + int argc = fw_arg0; + char **argv = (char **) KSEG1ADDR(fw_arg1); + int i; + + arcs_cmdline[0] = '\0'; + + for (i = 0; i < argc; i++) { + char *p = (char *) KSEG1ADDR(argv[i]); + + if (CPHYSADDR(p) && *p) { + strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); + strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); + } + } + pr_info("Kernel command line: %s\n", arcs_cmdline); +} + +void __init identify_rtl9302(void) +{ + switch (sw_r32(RTL93XX_MODEL_NAME_INFO) & 0xfffffff0) { + case 0x93020810: + soc_info.name = "RTL9302A 12x2.5G"; + break; + case 0x93021010: + soc_info.name = "RTL9302B 8x2.5G"; + break; + case 0x93021810: + soc_info.name = "RTL9302C 16x2.5G"; + break; + case 0x93022010: + soc_info.name = "RTL9302D 24x2.5G"; + break; + case 0x93020800: + soc_info.name = "RTL9302A"; + break; + case 0x93021000: + soc_info.name = "RTL9302B"; + break; + case 0x93021800: + soc_info.name = "RTL9302C"; + break; + case 0x93022000: + soc_info.name = "RTL9302D"; + break; + case 0x93023001: + soc_info.name = "RTL9302F"; + break; + default: + soc_info.name = "RTL9302"; + } +} + +void __init prom_init(void) +{ + uint32_t model; + + /* uart0 */ + setup_8250_early_printk_port(0xb8002000, 2, 0); + + model = sw_r32(RTL838X_MODEL_NAME_INFO); + pr_info("RTL838X model is %x\n", model); + model = model >> 16 & 0xFFFF; + + if ((model != 0x8328) && (model != 0x8330) && (model != 0x8332) + && (model != 0x8380) && (model != 0x8382)) { + model = sw_r32(RTL839X_MODEL_NAME_INFO); + pr_info("RTL839X model is %x\n", model); + model = model >> 16 & 0xFFFF; + } + + if ((model & 0x8390) != 0x8380 && (model & 0x8390) != 0x8390) { + model = sw_r32(RTL93XX_MODEL_NAME_INFO); + pr_info("RTL93XX model is %x\n", model); + model = model >> 16 & 0xFFFF; + } + + soc_info.id = model; + + switch (model) { + case 0x8328: + soc_info.name = "RTL8328"; + soc_info.family = RTL8328_FAMILY_ID; + break; + case 0x8332: + soc_info.name = "RTL8332"; + soc_info.family = RTL8380_FAMILY_ID; + break; + case 0x8380: + soc_info.name = "RTL8380"; + soc_info.family = RTL8380_FAMILY_ID; + break; + case 0x8382: + soc_info.name = "RTL8382"; + soc_info.family = RTL8380_FAMILY_ID; + break; + case 0x8390: + soc_info.name = "RTL8390"; + soc_info.family = RTL8390_FAMILY_ID; + break; + case 0x8391: + soc_info.name = "RTL8391"; + soc_info.family = RTL8390_FAMILY_ID; + break; + case 0x8392: + soc_info.name = "RTL8392"; + soc_info.family = RTL8390_FAMILY_ID; + break; + case 0x8393: + soc_info.name = "RTL8393"; + soc_info.family = RTL8390_FAMILY_ID; + break; + case 0x9301: + soc_info.name = "RTL9301"; + soc_info.family = RTL9300_FAMILY_ID; + break; + case 0x9302: + identify_rtl9302(); + soc_info.family = RTL9300_FAMILY_ID; + break; + case 0x9313: + soc_info.name = "RTL9313"; + soc_info.family = RTL9310_FAMILY_ID; + break; + default: + soc_info.name = "DEFAULT"; + soc_info.family = 0; + } + + pr_info("SoC Type: %s\n", get_system_type()); + + prom_init_cmdline(); +} diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c b/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c new file mode 100644 index 0000000000..ef97d485e1 --- /dev/null +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Setup for the Realtek RTL838X SoC: + * Memory, Timer and Serial + * + * Copyright (C) 2020 B. Koblitz + * based on the original BSP by + * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com) + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mach-rtl83xx.h" + +extern struct rtl83xx_soc_info soc_info; + +u32 pll_reset_value; + +static void rtl838x_restart(char *command) +{ + u32 pll = sw_r32(RTL838X_PLL_CML_CTRL); + + pr_info("System restart.\n"); + pr_info("PLL control register: %x, applying reset value %x\n", + pll, pll_reset_value); + + sw_w32(3, RTL838X_INT_RW_CTRL); + sw_w32(pll_reset_value, RTL838X_PLL_CML_CTRL); + sw_w32(0, RTL838X_INT_RW_CTRL); + + /* Reset Global Control1 Register */ + sw_w32(1, RTL838X_RST_GLB_CTRL_1); +} + +static void rtl839x_restart(char *command) +{ + /* SoC reset vector (in flash memory): on RTL839x platform preferred way to reset */ + void (*f)(void) = (void *) 0xbfc00000; + + pr_info("System restart.\n"); + /* Reset SoC */ + sw_w32(0xFFFFFFFF, RTL839X_RST_GLB_CTRL); + /* and call reset vector */ + f(); + /* If this fails, halt the CPU */ + while + (1); +} + +static void rtl930x_restart(char *command) +{ + pr_info("System restart.\n"); + sw_w32(0x1, RTL930X_RST_GLB_CTRL_0); + while + (1); +} + +static void rtl931x_restart(char *command) +{ + u32 v; + + pr_info("System restart.\n"); + sw_w32(1, RTL931X_RST_GLB_CTRL); + v = sw_r32(RTL931X_RST_GLB_CTRL); + sw_w32(0x101, RTL931X_RST_GLB_CTRL); + msleep(15); + sw_w32(v, RTL931X_RST_GLB_CTRL); + msleep(15); + sw_w32(0x101, RTL931X_RST_GLB_CTRL); +} + +static void rtl838x_halt(void) +{ + pr_info("System halted.\n"); + while + (1); +} + +static void __init rtl838x_setup(void) +{ + pr_info("Registering _machine_restart\n"); + _machine_restart = rtl838x_restart; + _machine_halt = rtl838x_halt; + + /* This PLL value needs to be restored before a reset and will then be + * preserved over a SoC reset. A wrong value prevents the SoC from + * connecting to the SPI flash controller at boot and reading the + * reset routine */ + pll_reset_value = sw_r32(RTL838X_PLL_CML_CTRL); + + /* Setup System LED. Bit 15 then allows to toggle it */ + sw_w32_mask(0, 3 << 16, RTL838X_LED_GLB_CTRL); +} + +static void __init rtl839x_setup(void) +{ + pr_info("Registering _machine_restart\n"); + _machine_restart = rtl839x_restart; + _machine_halt = rtl838x_halt; + + /* Setup System LED. Bit 14 of RTL839X_LED_GLB_CTRL then allows to toggle it */ + sw_w32_mask(0, 3 << 15, RTL839X_LED_GLB_CTRL); +} + +static void __init rtl930x_setup(void) +{ + pr_info("Registering _machine_restart\n"); + _machine_restart = rtl930x_restart; + _machine_halt = rtl838x_halt; + + if (soc_info.id == 0x9302) + sw_w32_mask(0, 3 << 13, RTL9302_LED_GLB_CTRL); + else + sw_w32_mask(0, 3 << 13, RTL930X_LED_GLB_CTRL); +} + +static void __init rtl931x_setup(void) +{ + pr_info("Registering _machine_restart\n"); + _machine_restart = rtl931x_restart; + _machine_halt = rtl838x_halt; + sw_w32_mask(0, 3 << 12, RTL931X_LED_GLB_CTRL); +} + +void __init plat_mem_setup(void) +{ + void *dtb; + + set_io_port_base(KSEG1); + _machine_restart = rtl838x_restart; + + if (fw_passed_dtb) /* UHI interface */ + dtb = (void *)fw_passed_dtb; + else if (__dtb_start != __dtb_end) + dtb = (void *)__dtb_start; + else + panic("no dtb found"); + + /* + * Load the devicetree. This causes the chosen node to be + * parsed resulting in our memory appearing + */ + __dt_setup_arch(dtb); + + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + rtl838x_setup(); + break; + case RTL8390_FAMILY_ID: + rtl839x_setup(); + break; + case RTL9300_FAMILY_ID: + rtl930x_setup(); + break; + case RTL9310_FAMILY_ID: + rtl931x_setup(); + break; + } +} + +void __init plat_time_init(void) +{ + struct device_node *np; + u32 freq = 500000000; + + of_clk_init(NULL); + timer_probe(); + + np = of_find_node_by_name(NULL, "cpus"); + if (!np) { + pr_err("Missing 'cpus' DT node, using default frequency."); + } else { + if (of_property_read_u32(np, "frequency", &freq) < 0) + pr_err("No 'frequency' property in DT, using default."); + else + pr_info("CPU frequency from device tree: %dMHz", freq / 1000000); + of_node_put(np); + } + + mips_hpt_frequency = freq / 2; +} diff --git a/target/linux/realtek/files-5.10/drivers/clocksource/timer-rtl9300.c b/target/linux/realtek/files-5.10/drivers/clocksource/timer-rtl9300.c new file mode 100644 index 0000000000..9ab1733fe3 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clocksource/timer-rtl9300.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include "timer-of.h" + +#include + +/* + * Timer registers + * the RTL9300/9310 SoCs have 6 timers, each register block 0x10 apart + */ +#define RTL9300_TC_DATA 0x0 +#define RTL9300_TC_CNT 0x4 +#define RTL9300_TC_CTRL 0x8 +#define RTL9300_TC_CTRL_MODE BIT(24) +#define RTL9300_TC_CTRL_EN BIT(28) +#define RTL9300_TC_INT 0xc +#define RTL9300_TC_INT_IP BIT(16) +#define RTL9300_TC_INT_IE BIT(20) + +// Clocksource is using timer 0, clock event uses timer 1 +#define TIMER_CLK_SRC 0 +#define TIMER_CLK_EVT 1 +#define TIMER_BLK_EVT (TIMER_CLK_EVT << 4) + +// Timer modes +#define TIMER_MODE_REPEAT 1 +#define TIMER_MODE_ONCE 0 + +// Minimum divider is 2 +#define DIVISOR_RTL9300 2 + +#define N_BITS 28 + +static void __iomem *rtl9300_sched_reg __read_mostly; + +static u64 notrace rtl9300_sched_clock_read(void) +{ +/* pr_info("In %s: %x\n", __func__, readl_relaxed(rtl9300_sched_reg)); + dump_stack();*/ + return readl_relaxed(rtl9300_sched_reg); +} + +static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *clk = dev_id; + struct timer_of *to = to_timer_of(clk); + u32 v = readl(timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_INT); + + // Acknowledge the IRQ + v |= RTL9300_TC_INT_IP; + writel(v, timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_INT); + + clk->event_handler(clk); + return IRQ_HANDLED; +} + +static void rtl9300_timer_stop(struct timer_of *to) +{ + u32 v; + + writel(0, timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_CTRL); + + // Acknowledge possibly pending IRQ + v = readl(timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_INT); + if (v & RTL9300_TC_INT_IP) + writel(v, timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_INT); +} + +static void rtl9300_timer_start(struct timer_of *to, int timer, bool periodic) +{ + u32 v = (periodic ? RTL9300_TC_CTRL_MODE : 0) | RTL9300_TC_CTRL_EN | DIVISOR_RTL9300; + writel(v, timer_of_base(to) + timer * 0x10 + RTL9300_TC_CTRL); +} + +static int rtl9300_set_next_event(unsigned long delta, struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + + rtl9300_timer_stop(to); + writel(delta, timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_DATA); + rtl9300_timer_start(to, TIMER_CLK_EVT, TIMER_MODE_ONCE); + return 0; +} + +static int rtl9300_set_state_periodic(struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + + rtl9300_timer_stop(to); + writel(to->of_clk.period, timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_DATA); + rtl9300_timer_start(to, TIMER_CLK_EVT, TIMER_MODE_REPEAT); + return 0; +} + +static int rtl9300_set_state_oneshot(struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + + rtl9300_timer_stop(to); + writel(to->of_clk.period, timer_of_base(to) + TIMER_BLK_EVT + RTL9300_TC_DATA); + rtl9300_timer_start(to, TIMER_CLK_EVT, TIMER_MODE_ONCE); + return 0; +} + +static int rtl9300_set_state_shutdown(struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + + rtl9300_timer_stop(to); + return 0; +} + +static struct timer_of t_of = { + .flags = TIMER_OF_BASE | TIMER_OF_IRQ | TIMER_OF_CLOCK, + + .clkevt = { + .name = "rtl9300_timer", + .rating = 350, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = rtl9300_set_next_event, + .set_state_oneshot = rtl9300_set_state_oneshot, + .set_state_periodic = rtl9300_set_state_periodic, + .set_state_shutdown = rtl9300_set_state_shutdown, + }, + + .of_irq = { + .name = "ostimer", + .handler = rtl9300_timer_interrupt, + .flags = IRQF_TIMER, + }, +}; + +static void __init rtl9300_timer_setup(u8 timer) +{ + u32 v; + + // Disable timer + writel(0, timer_of_base(&t_of) + 0x10 * timer + RTL9300_TC_CTRL); + + // Acknowledge possibly pending IRQ + v = readl(timer_of_base(&t_of) + 0x10 * timer + RTL9300_TC_INT); + if (v & RTL9300_TC_INT_IP) + writel(v, timer_of_base(&t_of) + 0x10 * timer + RTL9300_TC_INT); + + // Setup maximum period (for use as clock-source) + writel(0x0fffffff, timer_of_base(&t_of) + 0x10 * timer + RTL9300_TC_DATA); +} + + +static int __init rtl9300_timer_init(struct device_node *node) +{ + int err = 0; + unsigned long rate; + + pr_info("%s: setting up timer\n", __func__); + + err = timer_of_init(node, &t_of); + if (err) + return err; + + rate = timer_of_rate(&t_of) / DIVISOR_RTL9300; + pr_info("Frequency in dts: %ld, my rate is %ld, period %ld\n", + timer_of_rate(&t_of), rate, timer_of_period(&t_of)); + pr_info("With base %08x IRQ: %d\n", (u32)timer_of_base(&t_of), timer_of_irq(&t_of)); + + // Configure clock source and register it for scheduling + rtl9300_timer_setup(TIMER_CLK_SRC); + rtl9300_timer_start(&t_of, TIMER_CLK_SRC, TIMER_MODE_REPEAT); + + rtl9300_sched_reg = timer_of_base(&t_of) + TIMER_CLK_SRC * 0x10 + RTL9300_TC_CNT; + + err = clocksource_mmio_init(rtl9300_sched_reg, node->name, rate , 100, N_BITS, + clocksource_mmio_readl_up); + if (err) + return err; + + sched_clock_register(rtl9300_sched_clock_read, N_BITS, rate); + + // Configure clock event source + rtl9300_timer_setup(TIMER_CLK_EVT); + clockevents_config_and_register(&t_of.clkevt, rate, 100, 0x0fffffff); + + // Enable interrupt + writel(RTL9300_TC_INT_IE, timer_of_base(&t_of) + TIMER_BLK_EVT + RTL9300_TC_INT); + + return err; +} + +TIMER_OF_DECLARE(rtl9300_timer, "realtek,rtl9300-timer", rtl9300_timer_init); diff --git a/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl8231.c b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl8231.c new file mode 100644 index 0000000000..a8ffcdc313 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl8231.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +/* RTL8231 registers for LED control */ +#define RTL8231_LED_FUNC0 0x0000 +#define RTL8231_GPIO_PIN_SEL(gpio) ((0x0002) + ((gpio) >> 4)) +#define RTL8231_GPIO_DIR(gpio) ((0x0005) + ((gpio) >> 4)) +#define RTL8231_GPIO_DATA(gpio) ((0x001C) + ((gpio) >> 4)) + +#define USEC_TIMEOUT 5000 + +struct rtl8231_gpios { + struct gpio_chip gc; + struct device *dev; + u32 id; + int smi_bus_id; + u16 reg_shadow[0x20]; + u32 reg_cached; + int ext_gpio_indrt_access; +}; + +extern struct mutex smi_lock; +extern struct rtl83xx_soc_info soc_info; + +static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg) +{ + u32 t = 0, n = 0; + u8 bus_id = gpios->smi_bus_id; + + reg &= 0x1f; + bus_id &= 0x1f; + + /* Calculate read register address */ + t = (bus_id << 2) | (reg << 7); + + /* Set execution bit: cleared when operation completed */ + t |= 1; + + // Start execution + sw_w32(t, gpios->ext_gpio_indrt_access); + do { + udelay(1); + t = sw_r32(gpios->ext_gpio_indrt_access); + n++; + } while ((t & 1) && (n < USEC_TIMEOUT)); + + if (n >= USEC_TIMEOUT) + return 0x80000000; + + pr_debug("%s: %x, %x, %x\n", __func__, bus_id, reg, (t & 0xffff0000) >> 16); + + return (t & 0xffff0000) >> 16; +} + +static int rtl8231_write(struct rtl8231_gpios *gpios, u32 reg, u32 data) +{ + u32 t = 0, n = 0; + u8 bus_id = gpios->smi_bus_id; + + pr_debug("%s: %x, %x, %x\n", __func__, bus_id, reg, data); + reg &= 0x1f; + bus_id &= 0x1f; + + t = (bus_id << 2) | (reg << 7) | (data << 16); + /* Set write bit */ + t |= 2; + + /* Set execution bit: cleared when operation completed */ + t |= 1; + + // Start execution + sw_w32(t, gpios->ext_gpio_indrt_access); + do { + udelay(1); + t = sw_r32(gpios->ext_gpio_indrt_access); + } while ((t & 1) && (n < USEC_TIMEOUT)); + + if (n >= USEC_TIMEOUT) + return -1; + + return 0; +} + +static u32 rtl8231_read_cached(struct rtl8231_gpios *gpios, u32 reg) +{ + if (reg > 0x1f) + return 0; + + if (gpios->reg_cached & (1 << reg)) + return gpios->reg_shadow[reg]; + + return rtl8231_read(gpios, reg); +} + +/* Set Direction of the RTL8231 pin: + * dir 1: input + * dir 0: output + */ +static int rtl8231_pin_dir(struct rtl8231_gpios *gpios, u32 gpio, u32 dir) +{ + u32 v; + int pin_sel_addr = RTL8231_GPIO_PIN_SEL(gpio); + int pin_dir_addr = RTL8231_GPIO_DIR(gpio); + int dpin = gpio % 16; + + if (gpio > 31) { + pr_debug("WARNING: HIGH pin\n"); + dpin += 5; + pin_dir_addr = pin_sel_addr; + } + + v = rtl8231_read_cached(gpios, pin_dir_addr); + if (v & 0x80000000) { + pr_err("Error reading RTL8231\n"); + return -1; + } + + v = (v & ~(1 << dpin)) | (dir << dpin); + rtl8231_write(gpios, pin_dir_addr, v); + gpios->reg_shadow[pin_dir_addr] = v; + gpios->reg_cached |= 1 << pin_dir_addr; + return 0; +} + +static int rtl8231_pin_dir_get(struct rtl8231_gpios *gpios, u32 gpio, u32 *dir) +{ + /* dir 1: input + * dir 0: output + */ + + u32 v; + int pin_dir_addr = RTL8231_GPIO_DIR(gpio); + int pin = gpio % 16; + + if (gpio > 31) { + pin_dir_addr = RTL8231_GPIO_PIN_SEL(gpio); + pin += 5; + } + + v = rtl8231_read(gpios, pin_dir_addr); + if (v & (1 << pin)) + *dir = 1; + else + *dir = 0; + return 0; +} + +static int rtl8231_pin_set(struct rtl8231_gpios *gpios, u32 gpio, u32 data) +{ + u32 v = rtl8231_read(gpios, RTL8231_GPIO_DATA(gpio)); + + pr_debug("%s: %d to %d\n", __func__, gpio, data); + if (v & 0x80000000) { + pr_err("Error reading RTL8231\n"); + return -1; + } + v = (v & ~(1 << (gpio % 16))) | (data << (gpio % 16)); + rtl8231_write(gpios, RTL8231_GPIO_DATA(gpio), v); + gpios->reg_shadow[RTL8231_GPIO_DATA(gpio)] = v; + gpios->reg_cached |= 1 << RTL8231_GPIO_DATA(gpio); + return 0; +} + +static int rtl8231_pin_get(struct rtl8231_gpios *gpios, u32 gpio, u16 *state) +{ + u32 v = rtl8231_read(gpios, RTL8231_GPIO_DATA(gpio)); + + if (v & 0x80000000) { + pr_err("Error reading RTL8231\n"); + return -1; + } + + *state = v & 0xffff; + return 0; +} + +static int rtl8231_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + int err; + struct rtl8231_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("%s: %d\n", __func__, offset); + mutex_lock(&smi_lock); + err = rtl8231_pin_dir(gpios, offset, 1); + mutex_unlock(&smi_lock); + return err; +} + +static int rtl8231_direction_output(struct gpio_chip *gc, unsigned int offset, int value) +{ + int err; + struct rtl8231_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("%s: %d\n", __func__, offset); + mutex_lock(&smi_lock); + err = rtl8231_pin_dir(gpios, offset, 0); + mutex_unlock(&smi_lock); + if (!err) + err = rtl8231_pin_set(gpios, offset, value); + return err; +} + +static int rtl8231_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + u32 v = 0; + struct rtl8231_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("%s: %d\n", __func__, offset); + mutex_lock(&smi_lock); + rtl8231_pin_dir_get(gpios, offset, &v); + mutex_unlock(&smi_lock); + return v; +} + +static int rtl8231_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + u16 state = 0; + struct rtl8231_gpios *gpios = gpiochip_get_data(gc); + + mutex_lock(&smi_lock); + rtl8231_pin_get(gpios, offset, &state); + mutex_unlock(&smi_lock); + if (state & (1 << (offset % 16))) + return 1; + return 0; +} + +void rtl8231_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct rtl8231_gpios *gpios = gpiochip_get_data(gc); + + rtl8231_pin_set(gpios, offset, value); +} + +int rtl8231_init(struct rtl8231_gpios *gpios) +{ + u32 v; + + pr_info("%s called, MDIO bus ID: %d\n", __func__, gpios->smi_bus_id); + + gpios->reg_cached = 0; + + if (soc_info.family == RTL8390_FAMILY_ID) { + // RTL8390: Enable external gpio in global led control register + sw_w32_mask(0x7 << 18, 0x4 << 18, RTL839X_LED_GLB_CTRL); + } else if (soc_info.family == RTL8380_FAMILY_ID) { + // RTL8380: Enable RTL8231 indirect access mode + sw_w32_mask(0, 1, RTL838X_EXTRA_GPIO_CTRL); + sw_w32_mask(3, 1, RTL838X_DMY_REG5); + } + + /* Select GPIO functionality for pins 0-34 */ + rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(0), 0xffff); + rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(16), 0xffff); + v = rtl8231_read(gpios, RTL8231_GPIO_PIN_SEL(32)); + rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(32), v | 0x7); + + return 0; +} + +static const struct of_device_id rtl8231_gpio_of_match[] = { + { .compatible = "realtek,rtl8231-gpio" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, rtl8231_gpio_of_match); + +static int rtl8231_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct rtl8231_gpios *gpios; + int err; + u32 indirect_bus_id; + + pr_info("Probing RTL8231 GPIOs\n"); + + if (!np) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); + if (!gpios) + return -ENOMEM; + + gpios->id = soc_info.id; + if (soc_info.family == RTL8380_FAMILY_ID) { + gpios->ext_gpio_indrt_access = RTL838X_EXT_GPIO_INDRT_ACCESS; + } + + if (soc_info.family == RTL8390_FAMILY_ID) { + gpios->ext_gpio_indrt_access = RTL839X_EXT_GPIO_INDRT_ACCESS; + } + + /* + * We use a default MDIO bus ID for the 8231 of 0, which can be overriden + * by the indirect-access-bus-id property in the dts. + */ + gpios->smi_bus_id = 0; + of_property_read_u32(np, "indirect-access-bus-id", &indirect_bus_id); + gpios->smi_bus_id = indirect_bus_id; + + rtl8231_init(gpios); + + gpios->dev = dev; + gpios->gc.base = 160; + gpios->gc.ngpio = 36; + gpios->gc.label = "rtl8231"; + gpios->gc.parent = dev; + gpios->gc.owner = THIS_MODULE; + gpios->gc.can_sleep = true; + + gpios->gc.direction_input = rtl8231_direction_input; + gpios->gc.direction_output = rtl8231_direction_output; + gpios->gc.set = rtl8231_gpio_set; + gpios->gc.get = rtl8231_gpio_get; + gpios->gc.get_direction = rtl8231_get_direction; + + err = devm_gpiochip_add_data(dev, &gpios->gc, gpios); + return err; +} + +static struct platform_driver rtl8231_gpio_driver = { + .driver = { + .name = "rtl8231-gpio", + .of_match_table = rtl8231_gpio_of_match, + }, + .probe = rtl8231_gpio_probe, +}; + +module_platform_driver(rtl8231_gpio_driver); + +MODULE_DESCRIPTION("Realtek RTL8231 GPIO expansion chip support"); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c new file mode 100644 index 0000000000..8207e4bb73 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +/* RTL8231 registers for LED control */ +#define RTL8231_LED_FUNC0 0x0000 +#define RTL8231_GPIO_PIN_SEL(gpio) ((0x0002) + ((gpio) >> 4)) +#define RTL8231_GPIO_DIR(gpio) ((0x0005) + ((gpio) >> 4)) +#define RTL8231_GPIO_DATA(gpio) ((0x001C) + ((gpio) >> 4)) + +struct rtl838x_gpios { + struct gpio_chip gc; + u32 id; + struct device *dev; + int irq; + int num_leds; + int min_led; + int leds_per_port; + u32 led_mode; + int led_glb_ctrl; + int led_sw_ctrl; + int (*led_sw_p_ctrl)(int port); + int (*led_sw_p_en_ctrl)(int port); + int (*ext_gpio_dir)(int i); + int (*ext_gpio_data)(int i); +}; + +inline int rtl838x_ext_gpio_dir(int i) +{ + return RTL838X_EXT_GPIO_DIR + ((i >>5) << 2); +} + +inline int rtl839x_ext_gpio_dir(int i) +{ + return RTL839X_EXT_GPIO_DIR + ((i >>5) << 2); +} + +inline int rtl838x_ext_gpio_data(int i) +{ + return RTL838X_EXT_GPIO_DATA + ((i >>5) << 2); +} + +inline int rtl839x_ext_gpio_data(int i) +{ + return RTL839X_EXT_GPIO_DATA + ((i >>5) << 2); +} + +inline int rtl838x_led_sw_p_ctrl(int p) +{ + return RTL838X_LED_SW_P_CTRL + (p << 2); +} + +inline int rtl839x_led_sw_p_ctrl(int p) +{ + return RTL839X_LED_SW_P_CTRL + (p << 2); +} + +inline int rtl838x_led_sw_p_en_ctrl(int p) +{ + return RTL838X_LED_SW_P_EN_CTRL + ((p / 10) << 2); +} + +inline int rtl839x_led_sw_p_en_ctrl(int p) +{ + return RTL839X_LED_SW_P_EN_CTRL + ((p / 10) << 2); +} + +extern struct mutex smi_lock; +extern struct rtl83xx_soc_info soc_info; + + +void rtl838x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + int bit; + struct rtl838x_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("rtl838x_set: %d, value: %d\n", offset, value); + /* Internal GPIO of the RTL8380 */ + if (offset < 32) { + if (value) + rtl83xx_w32_mask(0, BIT(offset), RTL838X_GPIO_PABC_DATA); + else + rtl83xx_w32_mask(BIT(offset), 0, RTL838X_GPIO_PABC_DATA); + } + + /* LED driver for PWR and SYS */ + if (offset >= 32 && offset < 64) { + bit = offset - 32; + if (value) + sw_w32_mask(0, BIT(bit), gpios->led_glb_ctrl); + else + sw_w32_mask(BIT(bit), 0, gpios->led_glb_ctrl); + return; + } + + bit = (offset - 64) % 32; + /* First Port-LED */ + if (offset >= 64 && offset < 96 + && offset >= (64 + gpios->min_led) + && offset < (64 + gpios->min_led + gpios->num_leds)) { + if (value) + sw_w32_mask(7, 5, gpios->led_sw_p_ctrl(bit)); + else + sw_w32_mask(7, 0, gpios->led_sw_p_ctrl(bit)); + } + if (offset >= 96 && offset < 128 + && offset >= (96 + gpios->min_led) + && offset < (96 + gpios->min_led + gpios->num_leds)) { + if (value) + sw_w32_mask(7 << 3, 5 << 3, gpios->led_sw_p_ctrl(bit)); + else + sw_w32_mask(7 << 3, 0, gpios->led_sw_p_ctrl(bit)); + } + if (offset >= 128 && offset < 160 + && offset >= (128 + gpios->min_led) + && offset < (128 + gpios->min_led + gpios->num_leds)) { + if (value) + sw_w32_mask(7 << 6, 5 << 6, gpios->led_sw_p_ctrl(bit)); + else + sw_w32_mask(7 << 6, 0, gpios->led_sw_p_ctrl(bit)); + } + __asm__ volatile ("sync"); +} + +static int rtl838x_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + pr_debug("%s: %d\n", __func__, offset); + + if (offset < 32) { + rtl83xx_w32_mask(BIT(offset), 0, RTL838X_GPIO_PABC_DIR); + return 0; + } + + /* Internal LED driver does not support input */ + return -ENOTSUPP; +} + +static int rtl838x_direction_output(struct gpio_chip *gc, unsigned int offset, int value) +{ + pr_debug("%s: %d\n", __func__, offset); + if (offset < 32) + rtl83xx_w32_mask(0, BIT(offset), RTL838X_GPIO_PABC_DIR); + rtl838x_gpio_set(gc, offset, value); + + /* LED for PWR and SYS driver is direction output by default */ + return 0; +} + +static int rtl838x_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + u32 v = 0; + + pr_debug("%s: %d\n", __func__, offset); + if (offset < 32) { + v = rtl83xx_r32(RTL838X_GPIO_PABC_DIR); + if (v & BIT(offset)) + return 0; + return 1; + } + + /* LED driver for PWR and SYS is direction output by default */ + if (offset >= 32 && offset < 64) + return 0; + + return 0; +} + +static int rtl838x_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + u32 v; + struct rtl838x_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("%s: %d\n", __func__, offset); + + /* Internal GPIO of the RTL8380 */ + if (offset < 32) { + v = rtl83xx_r32(RTL838X_GPIO_PABC_DATA); + if (v & BIT(offset)) + return 1; + return 0; + } + + /* LED driver for PWR and SYS */ + if (offset >= 32 && offset < 64) { + v = sw_r32(gpios->led_glb_ctrl); + if (v & BIT(offset-32)) + return 1; + return 0; + } + +/* BUG: + bit = (offset - 64) % 32; + if (offset >= 64 && offset < 96) { + if (sw_r32(RTL838X_LED1_SW_P_EN_CTRL) & BIT(bit)) + return 1; + return 0; + } + if (offset >= 96 && offset < 128) { + if (sw_r32(RTL838X_LED1_SW_P_EN_CTRL) & BIT(bit)) + return 1; + return 0; + } + if (offset >= 128 && offset < 160) { + if (sw_r32(RTL838X_LED1_SW_P_EN_CTRL) & BIT(bit)) + return 1; + return 0; + } + */ + return 0; +} + +void rtl8380_led_test(struct rtl838x_gpios *gpios, u32 mask) +{ + int i; + u32 led_gbl = sw_r32(gpios->led_glb_ctrl); + u32 mode_sel, led_p_en; + + if (soc_info.family == RTL8380_FAMILY_ID) { + mode_sel = sw_r32(RTL838X_LED_MODE_SEL); + led_p_en = sw_r32(RTL838X_LED_P_EN_CTRL); + } + + /* 2 Leds for ports 0-23 and 24-27, 3 would be 0x7 */ + sw_w32_mask(0x3f, 0x3 | (0x3 << 3), gpios->led_glb_ctrl); + + if(soc_info.family == RTL8380_FAMILY_ID) { + /* Enable all leds */ + sw_w32(0xFFFFFFF, RTL838X_LED_P_EN_CTRL); + } + /* Enable software control of all leds */ + sw_w32(0xFFFFFFF, gpios->led_sw_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(0)); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(10)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); + + for (i = 0; i < 28; i++) { + if (mask & BIT(i)) + sw_w32(5 | (5 << 3) | (5 << 6), gpios->led_sw_p_ctrl(i)); + } + msleep(3000); + + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(led_p_en, RTL838X_LED_P_EN_CTRL); + /* Disable software control of all leds */ + sw_w32(0x0000000, gpios->led_sw_ctrl); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(0)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(10)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); + + sw_w32(led_gbl, gpios->led_glb_ctrl); + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(mode_sel, RTL838X_LED_MODE_SEL); +} + +void take_port_leds(struct rtl838x_gpios *gpios) +{ + int leds_per_port = gpios->leds_per_port; + int mode = gpios->led_mode; + + pr_info("%s, %d, %x\n", __func__, leds_per_port, mode); + pr_debug("Bootloader settings: %x %x %x\n", + sw_r32(gpios->led_sw_p_en_ctrl(0)), + sw_r32(gpios->led_sw_p_en_ctrl(10)), + sw_r32(gpios->led_sw_p_en_ctrl(20)) + ); + + if (soc_info.family == RTL8380_FAMILY_ID) { + pr_debug("led glb: %x, sel %x\n", + sw_r32(gpios->led_glb_ctrl), sw_r32(RTL838X_LED_MODE_SEL)); + pr_debug("RTL838X_LED_P_EN_CTRL: %x", sw_r32(RTL838X_LED_P_EN_CTRL)); + pr_debug("RTL838X_LED_MODE_CTRL: %x", sw_r32(RTL838X_LED_MODE_CTRL)); + sw_w32_mask(3, 0, RTL838X_LED_MODE_SEL); + sw_w32(mode, RTL838X_LED_MODE_CTRL); + } + + /* Enable software control of all leds */ + sw_w32(0xFFFFFFF, gpios->led_sw_ctrl); + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(0xFFFFFFF, RTL838X_LED_P_EN_CTRL); + + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(0)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(10)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); + + sw_w32_mask(0x3f, 0, gpios->led_glb_ctrl); + switch (leds_per_port) { + case 3: + sw_w32_mask(0, 0x7 | (0x7 << 3), gpios->led_glb_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(20)); + /* FALLTHRU */ + case 2: + sw_w32_mask(0, 0x3 | (0x3 << 3), gpios->led_glb_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(10)); + /* FALLTHRU */ + case 1: + sw_w32_mask(0, 0x1 | (0x1 << 3), gpios->led_glb_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(0)); + break; + default: + pr_err("No LEDS configured for software control\n"); + } +} + +static const struct of_device_id rtl838x_gpio_of_match[] = { + { .compatible = "realtek,rtl838x-gpio" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, rtl838x_gpio_of_match); + +static int rtl838x_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct rtl838x_gpios *gpios; + int err; + + pr_info("Probing RTL838X GPIOs\n"); + + if (!np) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); + if (!gpios) + return -ENOMEM; + + gpios->id = soc_info.id; + + switch (gpios->id) { + case 0x8332: + pr_debug("Found RTL8332M GPIO\n"); + break; + case 0x8380: + pr_debug("Found RTL8380M GPIO\n"); + break; + case 0x8381: + pr_debug("Found RTL8381M GPIO\n"); + break; + case 0x8382: + pr_debug("Found RTL8382M GPIO\n"); + break; + case 0x8391: + pr_debug("Found RTL8391 GPIO\n"); + break; + case 0x8393: + pr_debug("Found RTL8393 GPIO\n"); + break; + default: + pr_err("Unknown GPIO chip id (%04x)\n", gpios->id); + return -ENODEV; + } + + if (soc_info.family == RTL8380_FAMILY_ID) { + gpios->led_glb_ctrl = RTL838X_LED_GLB_CTRL; + gpios->led_sw_ctrl = RTL838X_LED_SW_CTRL; + gpios->led_sw_p_ctrl = rtl838x_led_sw_p_ctrl; + gpios->led_sw_p_en_ctrl = rtl838x_led_sw_p_en_ctrl; + gpios->ext_gpio_dir = rtl838x_ext_gpio_dir; + gpios->ext_gpio_data = rtl838x_ext_gpio_data; + } + + if (soc_info.family == RTL8390_FAMILY_ID) { + gpios->led_glb_ctrl = RTL839X_LED_GLB_CTRL; + gpios->led_sw_ctrl = RTL839X_LED_SW_CTRL; + gpios->led_sw_p_ctrl = rtl839x_led_sw_p_ctrl; + gpios->led_sw_p_en_ctrl = rtl839x_led_sw_p_en_ctrl; + gpios->ext_gpio_dir = rtl839x_ext_gpio_dir; + gpios->ext_gpio_data = rtl839x_ext_gpio_data; + } + + gpios->dev = dev; + gpios->gc.base = 0; + /* 0-31: internal + * 32-63, LED control register + * 64-95: PORT-LED 0 + * 96-127: PORT-LED 1 + * 128-159: PORT-LED 2 + */ + gpios->gc.ngpio = 160; + gpios->gc.label = "rtl838x"; + gpios->gc.parent = dev; + gpios->gc.owner = THIS_MODULE; + gpios->gc.can_sleep = true; + gpios->irq = 31; + + gpios->gc.direction_input = rtl838x_direction_input; + gpios->gc.direction_output = rtl838x_direction_output; + gpios->gc.set = rtl838x_gpio_set; + gpios->gc.get = rtl838x_gpio_get; + gpios->gc.get_direction = rtl838x_get_direction; + + if (of_property_read_bool(np, "take-port-leds")) { + if (of_property_read_u32(np, "leds-per-port", &gpios->leds_per_port)) + gpios->leds_per_port = 2; + if (of_property_read_u32(np, "led-mode", &gpios->led_mode)) + gpios->led_mode = (0x1ea << 15) | 0x1ea; + if (of_property_read_u32(np, "num-leds", &gpios->num_leds)) + gpios->num_leds = 32; + if (of_property_read_u32(np, "min-led", &gpios->min_led)) + gpios->min_led = 0; + take_port_leds(gpios); + } + + err = devm_gpiochip_add_data(dev, &gpios->gc, gpios); + return err; +} + +static struct platform_driver rtl838x_gpio_driver = { + .driver = { + .name = "rtl838x-gpio", + .of_match_table = rtl838x_gpio_of_match, + }, + .probe = rtl838x_gpio_probe, +}; + +module_platform_driver(rtl838x_gpio_driver); + +MODULE_DESCRIPTION("Realtek RTL838X GPIO API support"); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c b/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c new file mode 100644 index 0000000000..35bf53ea5a --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c @@ -0,0 +1,603 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rtl838x-spi.h" +#include + +extern struct rtl83xx_soc_info soc_info; + +struct rtl838x_nor { + struct spi_nor nor; + struct device *dev; + volatile void __iomem *base; + bool fourByteMode; + u32 chipSize; + uint32_t flags; + uint32_t io_status; +}; + +static uint32_t spi_prep(struct rtl838x_nor *rtl838x_nor) +{ + /* Needed because of MMU constraints */ + SPI_WAIT_READY; + spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1 + spi_w32w(0, SFCSR); //activate CS0,CS1 + spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1 + + return (CS0 & rtl838x_nor->flags) ? (SPI_eCS0 & SPI_LEN_INIT) + : ((SPI_eCS1 & SPI_LEN_INIT) | SFCSR_CHIP_SEL); +} + +static uint32_t rtl838x_nor_get_SR(struct rtl838x_nor *rtl838x_nor) +{ + uint32_t sfcsr, sfdr; + + sfcsr = spi_prep(rtl838x_nor); + sfdr = (SPINOR_OP_RDSR)<<24; + + pr_debug("%s: rdid,sfcsr_val = %.8x,SFDR = %.8x\n", __func__, sfcsr, sfdr); + pr_debug("rdid,sfcsr = %.8x\n", sfcsr | SPI_LEN4); + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + spi_w32_mask(0, SPI_LEN4, SFCSR); + SPI_WAIT_READY; + + return spi_r32(SFDR); +} + +static void spi_write_disable(struct rtl838x_nor *rtl838x_nor) +{ + uint32_t sfcsr, sfdr; + + sfcsr = spi_prep(rtl838x_nor); + sfdr = (SPINOR_OP_WRDI) << 24; + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr); + + spi_prep(rtl838x_nor); +} + +static void spi_write_enable(struct rtl838x_nor *rtl838x_nor) +{ + uint32_t sfcsr, sfdr; + + sfcsr = spi_prep(rtl838x_nor); + sfdr = (SPINOR_OP_WREN) << 24; + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr); + + spi_prep(rtl838x_nor); +} + +static void spi_4b_set(struct rtl838x_nor *rtl838x_nor, bool enable) +{ + uint32_t sfcsr, sfdr; + + sfcsr = spi_prep(rtl838x_nor); + if (enable) + sfdr = (SPINOR_OP_EN4B) << 24; + else + sfdr = (SPINOR_OP_EX4B) << 24; + + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr); + + spi_prep(rtl838x_nor); +} + +static int rtl838x_get_addr_mode(struct rtl838x_nor *rtl838x_nor) +{ + int res = 3; + u32 reg; + + sw_w32(0x3, RTL838X_INT_RW_CTRL); + if (!sw_r32(RTL838X_EXT_VERSION)) { + if (sw_r32(RTL838X_STRAP_DBG) & (1 << 29)) + res = 4; + } else { + reg = sw_r32(RTL838X_PLL_CML_CTRL); + if ((reg & (1 << 30)) && (reg & (1 << 31))) + res = 4; + if ((!(reg & (1 << 30))) + && sw_r32(RTL838X_STRAP_DBG) & (1 << 29)) + res = 4; + } + sw_w32(0x0, RTL838X_INT_RW_CTRL); + return res; +} + +static int rtl8390_get_addr_mode(struct rtl838x_nor *rtl838x_nor) +{ + if (spi_r32(RTL8390_SOC_SPI_MMIO_CONF) & (1 << 9)) + return 4; + return 3; +} + +ssize_t rtl838x_do_read(struct rtl838x_nor *rtl838x_nor, loff_t from, + size_t length, u_char *buffer, uint8_t command) +{ + uint32_t sfcsr, sfdr; + uint32_t len = length; + + sfcsr = spi_prep(rtl838x_nor); + sfdr = command << 24; + + /* Perform SPINOR_OP_READ: 1 byte command & 3 byte addr*/ + sfcsr |= SPI_LEN4; + sfdr |= from; + + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + + /* Read Data, 4 bytes at a time */ + while (length >= 4) { + SPI_WAIT_READY; + *((uint32_t *) buffer) = spi_r32(SFDR); + buffer += 4; + length -= 4; + } + + /* The rest needs to be read 1 byte a time */ + sfcsr &= SPI_LEN_INIT|SPI_LEN1; + SPI_WAIT_READY; + spi_w32w(sfcsr, SFCSR); + while (length > 0) { + SPI_WAIT_READY; + *(buffer) = spi_r32(SFDR) >> 24; + buffer++; + length--; + } + return len; +} + +/* + * Do fast read in 3 or 4 Byte addressing mode + */ +static ssize_t rtl838x_do_4bf_read(struct rtl838x_nor *rtl838x_nor, loff_t from, + size_t length, u_char *buffer, uint8_t command) +{ + int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2; + int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8; + uint32_t sfcsr; + uint32_t len = length; + + pr_debug("Fast read from %llx, len %x, shift %d\n", + from, sfcsr_addr_len, sfdr_addr_shift); + sfcsr = spi_prep(rtl838x_nor); + + /* Send read command */ + spi_w32w(sfcsr | SPI_LEN1, SFCSR); + spi_w32w(command << 24, SFDR); + + /* Send address */ + spi_w32w(sfcsr | (sfcsr_addr_len << 28), SFCSR); + spi_w32w(from << sfdr_addr_shift, SFDR); + + /* Dummy cycles */ + spi_w32w(sfcsr | SPI_LEN1, SFCSR); + spi_w32w(0, SFDR); + + /* Start reading */ + spi_w32w(sfcsr | SPI_LEN4, SFCSR); + + /* Read Data, 4 bytes at a time */ + while (length >= 4) { + SPI_WAIT_READY; + *((uint32_t *) buffer) = spi_r32(SFDR); + buffer += 4; + length -= 4; + } + + /* The rest needs to be read 1 byte a time */ + sfcsr &= SPI_LEN_INIT|SPI_LEN1; + SPI_WAIT_READY; + spi_w32w(sfcsr, SFCSR); + while (length > 0) { + SPI_WAIT_READY; + *(buffer) = spi_r32(SFDR) >> 24; + buffer++; + length--; + } + return len; + +} + +/* + * Do write (Page Programming) in 3 or 4 Byte addressing mode + */ +static ssize_t rtl838x_do_4b_write(struct rtl838x_nor *rtl838x_nor, loff_t to, + size_t length, const u_char *buffer, + uint8_t command) +{ + int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2; + int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8; + uint32_t sfcsr; + uint32_t len = length; + + pr_debug("Write to %llx, len %x, shift %d\n", + to, sfcsr_addr_len, sfdr_addr_shift); + sfcsr = spi_prep(rtl838x_nor); + + /* Send write command, command IO-width is 1 (bit 25/26) */ + spi_w32w(sfcsr | SPI_LEN1 | (0 << 25), SFCSR); + spi_w32w(command << 24, SFDR); + + /* Send address */ + spi_w32w(sfcsr | (sfcsr_addr_len << 28) | (0 << 25), SFCSR); + spi_w32w(to << sfdr_addr_shift, SFDR); + + /* Write Data, 1 byte at a time, if we are not 4-byte aligned */ + if (((long)buffer) % 4) { + spi_w32w(sfcsr | SPI_LEN1, SFCSR); + while (length > 0 && (((long)buffer) % 4)) { + SPI_WAIT_READY; + spi_w32(*(buffer) << 24, SFDR); + buffer += 1; + length -= 1; + } + } + + /* Now we can write 4 bytes at a time */ + SPI_WAIT_READY; + spi_w32w(sfcsr | SPI_LEN4, SFCSR); + while (length >= 4) { + SPI_WAIT_READY; + spi_w32(*((uint32_t *)buffer), SFDR); + buffer += 4; + length -= 4; + } + + /* Final bytes might need to be written 1 byte at a time, again */ + SPI_WAIT_READY; + spi_w32w(sfcsr | SPI_LEN1, SFCSR); + while (length > 0) { + SPI_WAIT_READY; + spi_w32(*(buffer) << 24, SFDR); + buffer++; + length--; + } + return len; +} + +static ssize_t rtl838x_nor_write(struct spi_nor *nor, loff_t to, size_t len, + const u_char *buffer) +{ + int ret = 0; + uint32_t offset = 0; + struct rtl838x_nor *rtl838x_nor = nor->priv; + size_t l = len; + uint8_t cmd = SPINOR_OP_PP; + + /* Do write in 4-byte mode on large Macronix chips */ + if (rtl838x_nor->fourByteMode) { + cmd = SPINOR_OP_PP_4B; + spi_4b_set(rtl838x_nor, true); + } + + pr_debug("In %s %8x to: %llx\n", __func__, + (unsigned int) rtl838x_nor, to); + + while (l >= SPI_MAX_TRANSFER_SIZE) { + while + (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); + do { + spi_write_enable(rtl838x_nor); + } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); + ret = rtl838x_do_4b_write(rtl838x_nor, to + offset, + SPI_MAX_TRANSFER_SIZE, buffer+offset, cmd); + l -= SPI_MAX_TRANSFER_SIZE; + offset += SPI_MAX_TRANSFER_SIZE; + } + + if (l > 0) { + while + (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); + do { + spi_write_enable(rtl838x_nor); + } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); + ret = rtl838x_do_4b_write(rtl838x_nor, to+offset, + len, buffer+offset, cmd); + } + + return len; +} + +static ssize_t rtl838x_nor_read(struct spi_nor *nor, loff_t from, + size_t length, u_char *buffer) +{ + uint32_t offset = 0; + uint8_t cmd = SPINOR_OP_READ_FAST; + size_t l = length; + struct rtl838x_nor *rtl838x_nor = nor->priv; + + /* Do fast read in 3, or 4-byte mode on large Macronix chips */ + if (rtl838x_nor->fourByteMode) { + cmd = SPINOR_OP_READ_FAST_4B; + spi_4b_set(rtl838x_nor, true); + } + + /* TODO: do timeout and return error */ + pr_debug("Waiting for pending writes\n"); + while + (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); + do { + spi_write_enable(rtl838x_nor); + } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); + + pr_debug("cmd is %d\n", cmd); + pr_debug("%s: addr %.8llx to addr %.8x, cmd %.8x, size %d\n", __func__, + from, (u32)buffer, (u32)cmd, length); + + while (l >= SPI_MAX_TRANSFER_SIZE) { + rtl838x_do_4bf_read(rtl838x_nor, from + offset, + SPI_MAX_TRANSFER_SIZE, buffer+offset, cmd); + l -= SPI_MAX_TRANSFER_SIZE; + offset += SPI_MAX_TRANSFER_SIZE; + } + + if (l > 0) + rtl838x_do_4bf_read(rtl838x_nor, from + offset, l, buffer+offset, cmd); + + return length; +} + +static int rtl838x_erase(struct spi_nor *nor, loff_t offs) +{ + struct rtl838x_nor *rtl838x_nor = nor->priv; + int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2; + int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8; + uint32_t sfcsr; + uint8_t cmd = SPINOR_OP_SE; + + pr_debug("Erasing sector at %llx\n", offs); + + /* Do erase in 4-byte mode on large Macronix chips */ + if (rtl838x_nor->fourByteMode) { + cmd = SPINOR_OP_SE_4B; + spi_4b_set(rtl838x_nor, true); + } + /* TODO: do timeout and return error */ + while + (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); + do { + spi_write_enable(rtl838x_nor); + } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); + + sfcsr = spi_prep(rtl838x_nor); + + /* Send erase command, command IO-width is 1 (bit 25/26) */ + spi_w32w(sfcsr | SPI_LEN1 | (0 << 25), SFCSR); + spi_w32w(cmd << 24, SFDR); + + /* Send address */ + spi_w32w(sfcsr | (sfcsr_addr_len << 28) | (0 << 25), SFCSR); + spi_w32w(offs << sfdr_addr_shift, SFDR); + + return 0; +} + +static int rtl838x_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) +{ + int length = len; + u8 *buffer = buf; + uint32_t sfcsr, sfdr; + struct rtl838x_nor *rtl838x_nor = nor->priv; + + pr_debug("In %s: opcode %x, len %x\n", __func__, opcode, len); + + sfcsr = spi_prep(rtl838x_nor); + sfdr = opcode << 24; + + sfcsr |= SPI_LEN1; + + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + + while (length > 0) { + SPI_WAIT_READY; + *(buffer) = spi_r32(SFDR) >> 24; + buffer++; + length--; + } + + return len; +} + +static int rtl838x_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) +{ + uint32_t sfcsr, sfdr; + struct rtl838x_nor *rtl838x_nor = nor->priv; + + pr_debug("In %s, opcode %x, len %x\n", __func__, opcode, len); + sfcsr = spi_prep(rtl838x_nor); + sfdr = opcode << 24; + + if (len == 1) { /* SPINOR_OP_WRSR */ + sfdr |= buf[0]; + sfcsr |= SPI_LEN2; + } + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + return 0; +} + +static int spi_enter_sio(struct spi_nor *nor) +{ + uint32_t sfcsr, sfcr2, sfdr; + uint32_t ret = 0, reg = 0, size_bits; + struct rtl838x_nor *rtl838x_nor = nor->priv; + + pr_debug("In %s\n", __func__); + rtl838x_nor->io_status = 0; + sfdr = SPI_C_RSTQIO << 24; + sfcsr = spi_prep(rtl838x_nor); + + reg = spi_r32(SFCR2); + pr_debug("SFCR2: %x, size %x, rdopt: %x\n", reg, SFCR2_GETSIZE(reg), + (reg & SFCR2_RDOPT)); + size_bits = rtl838x_nor->fourByteMode ? SFCR2_SIZE(0x6) : SFCR2_SIZE(0x7); + + sfcr2 = SFCR2_HOLD_TILL_SFDR2 | size_bits + | (reg & SFCR2_RDOPT) | SFCR2_CMDIO(0) + | SFCR2_ADDRIO(0) | SFCR2_DUMMYCYCLE(4) + | SFCR2_DATAIO(0) | SFCR2_SFCMD(SPINOR_OP_READ_FAST); + pr_debug("SFCR2: %x, size %x\n", reg, SFCR2_GETSIZE(reg)); + + SPI_WAIT_READY; + spi_w32w(sfcr2, SFCR2); + spi_w32w(sfcsr, SFCSR); + spi_w32w(sfdr, SFDR); + + spi_w32_mask(SFCR2_HOLD_TILL_SFDR2, 0, SFCR2); + rtl838x_nor->io_status &= ~IOSTATUS_CIO_MASK; + rtl838x_nor->io_status |= CIO1; + + spi_prep(rtl838x_nor); + + return ret; +} + +int rtl838x_spi_nor_scan(struct spi_nor *nor, const char *name) +{ + static const struct spi_nor_hwcaps hwcaps = { + .mask = SNOR_HWCAPS_READ | SNOR_HWCAPS_PP + | SNOR_HWCAPS_READ_FAST + }; + + struct rtl838x_nor *rtl838x_nor = nor->priv; + + pr_debug("In %s\n", __func__); + + spi_w32_mask(0, SFCR_EnableWBO, SFCR); + spi_w32_mask(0, SFCR_EnableRBO, SFCR); + + rtl838x_nor->flags = CS0 | R_MODE; + + spi_nor_scan(nor, NULL, &hwcaps); + pr_debug("------------- Got size: %llx\n", nor->mtd.size); + + return 0; +} + +int rtl838x_nor_init(struct rtl838x_nor *rtl838x_nor, + struct device_node *flash_node) +{ + int ret; + struct spi_nor *nor; + + pr_info("%s called\n", __func__); + nor = &rtl838x_nor->nor; + nor->dev = rtl838x_nor->dev; + nor->priv = rtl838x_nor; + spi_nor_set_flash_node(nor, flash_node); + + nor->read_reg = rtl838x_nor_read_reg; + nor->write_reg = rtl838x_nor_write_reg; + nor->read = rtl838x_nor_read; + nor->write = rtl838x_nor_write; + nor->erase = rtl838x_erase; + nor->mtd.name = "rtl838x_nor"; + nor->erase_opcode = rtl838x_nor->fourByteMode ? SPINOR_OP_SE_4B + : SPINOR_OP_SE; + /* initialized with NULL */ + ret = rtl838x_spi_nor_scan(nor, NULL); + if (ret) + return ret; + + spi_enter_sio(nor); + spi_write_disable(rtl838x_nor); + + ret = mtd_device_parse_register(&nor->mtd, NULL, NULL, NULL, 0); + return ret; +} + +static int rtl838x_nor_drv_probe(struct platform_device *pdev) +{ + struct device_node *flash_np; + struct resource *res; + int ret; + struct rtl838x_nor *rtl838x_nor; + int addrMode; + + pr_info("Initializing rtl838x_nor_driver\n"); + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + rtl838x_nor = devm_kzalloc(&pdev->dev, sizeof(*rtl838x_nor), GFP_KERNEL); + if (!rtl838x_nor) + return -ENOMEM; + platform_set_drvdata(pdev, rtl838x_nor); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rtl838x_nor->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR((void *)rtl838x_nor->base)) + return PTR_ERR((void *)rtl838x_nor->base); + + pr_info("SPI resource base is %08x\n", (u32)rtl838x_nor->base); + rtl838x_nor->dev = &pdev->dev; + + /* only support one attached flash */ + flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); + if (!flash_np) { + dev_err(&pdev->dev, "no SPI flash device to configure\n"); + ret = -ENODEV; + goto nor_free; + } + + /* Get the 3/4 byte address mode as configure by bootloader */ + if (soc_info.family == RTL8390_FAMILY_ID) + addrMode = rtl8390_get_addr_mode(rtl838x_nor); + else + addrMode = rtl838x_get_addr_mode(rtl838x_nor); + pr_info("Address mode is %d bytes\n", addrMode); + if (addrMode == 4) + rtl838x_nor->fourByteMode = true; + + ret = rtl838x_nor_init(rtl838x_nor, flash_np); + +nor_free: + return ret; +} + +static int rtl838x_nor_drv_remove(struct platform_device *pdev) +{ +/* struct rtl8xx_nor *rtl838x_nor = platform_get_drvdata(pdev); */ + return 0; +} + +static const struct of_device_id rtl838x_nor_of_ids[] = { + { .compatible = "realtek,rtl838x-nor"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rtl838x_nor_of_ids); + +static struct platform_driver rtl838x_nor_driver = { + .probe = rtl838x_nor_drv_probe, + .remove = rtl838x_nor_drv_remove, + .driver = { + .name = "rtl838x-nor", + .pm = NULL, + .of_match_table = rtl838x_nor_of_ids, + }, +}; + +module_platform_driver(rtl838x_nor_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("RTL838x SPI NOR Flash Driver"); diff --git a/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h b/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h new file mode 100644 index 0000000000..de424c647a --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2009 Realtek Semiconductor Corp. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _RTL838X_SPI_H +#define _RTL838X_SPI_H + + +/* + * Register access macros + */ + +#define spi_r32(reg) readl(rtl838x_nor->base + reg) +#define spi_w32(val, reg) writel(val, rtl838x_nor->base + reg) +#define spi_w32_mask(clear, set, reg) \ + spi_w32((spi_r32(reg) & ~(clear)) | (set), reg) + +#define SPI_WAIT_READY do { \ + } while (!(spi_r32(SFCSR) & SFCSR_SPI_RDY)) + +#define spi_w32w(val, reg) do { \ + writel(val, rtl838x_nor->base + reg); \ + SPI_WAIT_READY; \ + } while (0) + +#define SFCR (0x00) /*SPI Flash Configuration Register*/ + #define SFCR_CLK_DIV(val) ((val)<<29) + #define SFCR_EnableRBO (1<<28) + #define SFCR_EnableWBO (1<<27) + #define SFCR_SPI_TCS(val) ((val)<<23) /*4 bit, 1111 */ + +#define SFCR2 (0x04) /*For memory mapped I/O */ + #define SFCR2_SFCMD(val) ((val)<<24) /*8 bit, 1111_1111 */ + #define SFCR2_SIZE(val) ((val)<<21) /*3 bit, 111 */ + #define SFCR2_RDOPT (1<<20) + #define SFCR2_CMDIO(val) ((val)<<18) /*2 bit, 11 */ + #define SFCR2_ADDRIO(val) ((val)<<16) /*2 bit, 11 */ + #define SFCR2_DUMMYCYCLE(val) ((val)<<13) /*3 bit, 111 */ + #define SFCR2_DATAIO(val) ((val)<<11) /*2 bit, 11 */ + #define SFCR2_HOLD_TILL_SFDR2 (1<<10) + #define SFCR2_GETSIZE(x) (((x)&0x00E00000)>>21) + +#define SFCSR (0x08) /*SPI Flash Control&Status Register*/ + #define SFCSR_SPI_CSB0 (1<<31) + #define SFCSR_SPI_CSB1 (1<<30) + #define SFCSR_LEN(val) ((val)<<28) /*2 bits*/ + #define SFCSR_SPI_RDY (1<<27) + #define SFCSR_IO_WIDTH(val) ((val)<<25) /*2 bits*/ + #define SFCSR_CHIP_SEL (1<<24) + #define SFCSR_CMD_BYTE(val) ((val)<<16) /*8 bit, 1111_1111 */ + +#define SFDR (0x0C) /*SPI Flash Data Register*/ +#define SFDR2 (0x10) /*SPI Flash Data Register - for post SPI bootup setting*/ + #define SPI_CS_INIT (SFCSR_SPI_CSB0 | SFCSR_SPI_CSB1 | SPI_LEN1) + #define SPI_CS0 SFCSR_SPI_CSB0 + #define SPI_CS1 SFCSR_SPI_CSB1 + #define SPI_eCS0 ((SFCSR_SPI_CSB1)) /*and SFCSR to active CS0*/ + #define SPI_eCS1 ((SFCSR_SPI_CSB0)) /*and SFCSR to active CS1*/ + + #define SPI_WIP (1) /* Write In Progress */ + #define SPI_WEL (1<<1) /* Write Enable Latch*/ + #define SPI_SST_QIO_WIP (1<<7) /* SST QIO Flash Write In Progress */ + #define SPI_LEN_INIT 0xCFFFFFFF /* and SFCSR to init */ + #define SPI_LEN4 0x30000000 /* or SFCSR to set */ + #define SPI_LEN3 0x20000000 /* or SFCSR to set */ + #define SPI_LEN2 0x10000000 /* or SFCSR to set */ + #define SPI_LEN1 0x00000000 /* or SFCSR to set */ + #define SPI_SETLEN(val) do { \ + SPI_REG(SFCSR) &= 0xCFFFFFFF; \ + SPI_REG(SFCSR) |= (val-1)<<28; \ + } while (0) +/* + * SPI interface control + */ +#define RTL8390_SOC_SPI_MMIO_CONF (0x04) + +#define IOSTATUS_CIO_MASK (0x00000038) + +/* Chip select: bits 4-7*/ +#define CS0 (1<<4) +#define R_MODE 0x04 + +/* io_status */ +#define IO1 (1<<0) +#define IO2 (1<<1) +#define CIO1 (1<<3) +#define CIO2 (1<<4) +#define CMD_IO1 (1<<6) +#define W_ADDR_IO1 ((1)<<12) +#define R_ADDR_IO2 ((2)<<9) +#define R_DATA_IO2 ((2)<<15) +#define W_DATA_IO1 ((1)<<18) + +/* Commands */ +#define SPI_C_RSTQIO 0xFF + +#define SPI_MAX_TRANSFER_SIZE 256 + +#endif /* _RTL838X_SPI_H */ diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig new file mode 100644 index 0000000000..f293832eb5 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-only +config NET_DSA_RTL83XX + tristate "Realtek RTL838x/RTL839x switch support" + depends on RTL838X + select NET_DSA_TAG_TRAILER + ---help--- + This driver adds support for Realtek RTL83xx series switching. + diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile new file mode 100644 index 0000000000..016184c3d9 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_NET_DSA_RTL83XX) += common.o dsa.o \ + rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o 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 new file mode 100644 index 0000000000..a380906b92 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -0,0 +1,722 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include +#include "rtl83xx.h" + +extern struct rtl83xx_soc_info soc_info; + +extern const struct rtl838x_reg rtl838x_reg; +extern const struct rtl838x_reg rtl839x_reg; +extern const struct rtl838x_reg rtl930x_reg; +extern const struct rtl838x_reg rtl931x_reg; + +extern const struct dsa_switch_ops rtl83xx_switch_ops; +extern const struct dsa_switch_ops rtl930x_switch_ops; + +DEFINE_MUTEX(smi_lock); + +int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port) +{ + u32 msti = 0; + u32 port_state[4]; + int index, bit; + int pos = port; + int n = priv->port_width << 1; + + /* Ports above or equal CPU port can never be configured */ + if (port >= priv->cpu_port) + return -1; + + mutex_lock(&priv->reg_mutex); + + /* For the RTL839x and following, the bits are left-aligned in the 64/128 bit field */ + if (priv->family_id == RTL8390_FAMILY_ID) + pos += 12; + if (priv->family_id == RTL9300_FAMILY_ID) + pos += 3; + if (priv->family_id == RTL9310_FAMILY_ID) + pos += 8; + + index = n - (pos >> 4) - 1; + bit = (pos << 1) % 32; + + priv->r->stp_get(priv, msti, port_state); + + mutex_unlock(&priv->reg_mutex); + + return (port_state[index] >> bit) & 3; +} + +static struct table_reg rtl838x_tbl_regs[] = { + TBL_DESC(0x6900, 0x6908, 3, 15, 13, 1), // RTL8380_TBL_L2 + TBL_DESC(0x6914, 0x6918, 18, 14, 12, 1), // RTL8380_TBL_0 + TBL_DESC(0xA4C8, 0xA4CC, 6, 14, 12, 1), // RTL8380_TBL_1 + + TBL_DESC(0x1180, 0x1184, 3, 16, 14, 0), // RTL8390_TBL_L2 + TBL_DESC(0x1190, 0x1194, 17, 15, 12, 0), // RTL8390_TBL_0 + TBL_DESC(0x6B80, 0x6B84, 4, 14, 12, 0), // RTL8390_TBL_1 + TBL_DESC(0x611C, 0x6120, 9, 8, 6, 0), // RTL8390_TBL_2 + + TBL_DESC(0xB320, 0xB334, 3, 18, 16, 0), // RTL9300_TBL_L2 + TBL_DESC(0xB340, 0xB344, 19, 16, 12, 0), // RTL9300_TBL_0 + TBL_DESC(0xB3A0, 0xB3A4, 20, 16, 13, 0), // RTL9300_TBL_1 + TBL_DESC(0xCE04, 0xCE08, 6, 14, 12, 0), // RTL9300_TBL_2 + TBL_DESC(0xD600, 0xD604, 30, 7, 6, 0), // RTL9300_TBL_HSB + TBL_DESC(0x7880, 0x7884, 22, 9, 8, 0), // RTL9300_TBL_HSA + + TBL_DESC(0x8500, 0x8508, 8, 19, 15, 0), // RTL9310_TBL_0 + TBL_DESC(0x40C0, 0x40C4, 22, 16, 14, 0), // RTL9310_TBL_1 + TBL_DESC(0x8528, 0x852C, 6, 18, 14, 0), // RTL9310_TBL_2 + TBL_DESC(0x0200, 0x0204, 9, 15, 12, 0), // RTL9310_TBL_3 + TBL_DESC(0x20dc, 0x20e0, 29, 7, 6, 0), // RTL9310_TBL_4 + TBL_DESC(0x7e1c, 0x7e20, 53, 8, 6, 0), // RTL9310_TBL_5 +}; + +void rtl_table_init(void) +{ + int i; + + for (i = 0; i < RTL_TBL_END; i++) + mutex_init(&rtl838x_tbl_regs[i].lock); +} + +/* + * Request access to table t in table access register r + * Returns a handle to a lock for that table + */ +struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t) +{ + if (r >= RTL_TBL_END) + return NULL; + + if (t >= BIT(rtl838x_tbl_regs[r].c_bit-rtl838x_tbl_regs[r].t_bit)) + return NULL; + + mutex_lock(&rtl838x_tbl_regs[r].lock); + rtl838x_tbl_regs[r].tbl = t; + + return &rtl838x_tbl_regs[r]; +} + +/* + * Release a table r, unlock the corresponding lock + */ +void rtl_table_release(struct table_reg *r) +{ + if (!r) + return; + +// pr_info("Unlocking %08x\n", (u32)r); + mutex_unlock(&r->lock); +// pr_info("Unlock done\n"); +} + +/* + * Reads table index idx into the data registers of the table + */ +void rtl_table_read(struct table_reg *r, int idx) +{ + u32 cmd = r->rmode ? BIT(r->c_bit) : 0; + + cmd |= BIT(r->c_bit + 1) | (r->tbl << r->t_bit) | (idx & (BIT(r->t_bit) - 1)); + sw_w32(cmd, r->addr); + do { } while (sw_r32(r->addr) & BIT(r->c_bit + 1)); +} + +/* + * Writes the content of the table data registers into the table at index idx + */ +void rtl_table_write(struct table_reg *r, int idx) +{ + u32 cmd = r->rmode ? 0 : BIT(r->c_bit); + + cmd |= BIT(r->c_bit + 1) | (r->tbl << r->t_bit) | (idx & (BIT(r->t_bit) - 1)); + sw_w32(cmd, r->addr); + do { } while (sw_r32(r->addr) & BIT(r->c_bit + 1)); +} + +/* + * Returns the address of the ith data register of table register r + * the address is relative to the beginning of the Switch-IO block at 0xbb000000 + */ +inline u16 rtl_table_data(struct table_reg *r, int i) +{ + if (i >= r->max_data) + i = r->max_data - 1; + return r->data + i * 4; +} + +inline u32 rtl_table_data_r(struct table_reg *r, int i) +{ + return sw_r32(rtl_table_data(r, i)); +} + +inline void rtl_table_data_w(struct table_reg *r, u32 v, int i) +{ + sw_w32(v, rtl_table_data(r, i)); +} + +/* Port register accessor functions for the RTL838x and RTL930X SoCs */ +void rtl838x_mask_port_reg(u64 clear, u64 set, int reg) +{ + sw_w32_mask((u32)clear, (u32)set, reg); +} + +void rtl838x_set_port_reg(u64 set, int reg) +{ + sw_w32((u32)set, reg); +} + +u64 rtl838x_get_port_reg(int reg) +{ + return ((u64) sw_r32(reg)); +} + +/* Port register accessor functions for the RTL839x and RTL931X SoCs */ +void rtl839x_mask_port_reg_be(u64 clear, u64 set, int reg) +{ + sw_w32_mask((u32)(clear >> 32), (u32)(set >> 32), reg); + sw_w32_mask((u32)(clear & 0xffffffff), (u32)(set & 0xffffffff), reg + 4); +} + +u64 rtl839x_get_port_reg_be(int reg) +{ + u64 v = sw_r32(reg); + + v <<= 32; + v |= sw_r32(reg + 4); + return v; +} + +void rtl839x_set_port_reg_be(u64 set, int reg) +{ + sw_w32(set >> 32, reg); + sw_w32(set & 0xffffffff, reg + 4); +} + +void rtl839x_mask_port_reg_le(u64 clear, u64 set, int reg) +{ + sw_w32_mask((u32)clear, (u32)set, reg); + sw_w32_mask((u32)(clear >> 32), (u32)(set >> 32), reg + 4); +} + +void rtl839x_set_port_reg_le(u64 set, int reg) +{ + sw_w32(set, reg); + sw_w32(set >> 32, reg + 4); +} + +u64 rtl839x_get_port_reg_le(int reg) +{ + u64 v = sw_r32(reg + 4); + + v <<= 32; + v |= sw_r32(reg); + return v; +} + +int read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + return rtl838x_read_phy(port, page, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_read_phy(port, page, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_read_phy(port, page, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_read_phy(port, page, reg, val); + } + return -1; +} + +int write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + return rtl838x_write_phy(port, page, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_write_phy(port, page, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_write_phy(port, page, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_write_phy(port, page, reg, val); + } + return -1; +} + +static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) +{ + struct device *dev = priv->dev; + struct device_node *dn, *mii_np = dev->of_node; + struct mii_bus *bus; + int ret; + u32 pn; + + pr_debug("In %s\n", __func__); + mii_np = of_find_compatible_node(NULL, NULL, "realtek,rtl838x-mdio"); + if (mii_np) { + pr_debug("Found compatible MDIO node!\n"); + } else { + dev_err(priv->dev, "no %s child node found", "mdio-bus"); + return -ENODEV; + } + + priv->mii_bus = of_mdio_find_bus(mii_np); + if (!priv->mii_bus) { + pr_debug("Deferring probe of mdio bus\n"); + return -EPROBE_DEFER; + } + if (!of_device_is_available(mii_np)) + ret = -ENODEV; + + bus = devm_mdiobus_alloc(priv->ds->dev); + if (!bus) + return -ENOMEM; + + bus->name = "rtl838x slave mii"; + + /* + * Since the NIC driver is loaded first, we can use the mdio rw functions + * assigned there. + */ + bus->read = priv->mii_bus->read; + bus->write = priv->mii_bus->write; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", bus->name, dev->id); + + bus->parent = dev; + priv->ds->slave_mii_bus = bus; + priv->ds->slave_mii_bus->priv = priv; + + ret = mdiobus_register(priv->ds->slave_mii_bus); + if (ret && mii_np) { + of_node_put(dn); + return ret; + } + + dn = mii_np; + for_each_node_by_name(dn, "ethernet-phy") { + if (of_property_read_u32(dn, "reg", &pn)) + continue; + + priv->ports[pn].dp = dsa_to_port(priv->ds, pn); + + // Check for the integrated SerDes of the RTL8380M first + if (of_property_read_bool(dn, "phy-is-integrated") + && priv->id == 0x8380 && pn >= 24) { + pr_debug("----> FÓUND A SERDES\n"); + priv->ports[pn].phy = PHY_RTL838X_SDS; + continue; + } + + if (of_property_read_bool(dn, "phy-is-integrated") + && !of_property_read_bool(dn, "sfp")) { + priv->ports[pn].phy = PHY_RTL8218B_INT; + continue; + } + + if (!of_property_read_bool(dn, "phy-is-integrated") + && of_property_read_bool(dn, "sfp")) { + priv->ports[pn].phy = PHY_RTL8214FC; + continue; + } + + if (!of_property_read_bool(dn, "phy-is-integrated") + && !of_property_read_bool(dn, "sfp")) { + priv->ports[pn].phy = PHY_RTL8218B_EXT; + continue; + } + } + + // TODO: Do this needs to come from the .dts, at least the SerDes number + if (priv->family_id == RTL9300_FAMILY_ID) { + priv->ports[24].is2G5 = true; + priv->ports[25].is2G5 = true; + priv->ports[24].sds_num = 1; + priv->ports[24].sds_num = 2; + } + + /* Disable MAC polling the PHY so that we can start configuration */ + priv->r->set_port_reg_le(0ULL, priv->r->smi_poll_ctrl); + + /* Enable PHY control via SoC */ + if (priv->family_id == RTL8380_FAMILY_ID) { + /* Enable SerDes NWAY and PHY control via SoC */ + sw_w32_mask(BIT(7), BIT(15), RTL838X_SMI_GLB_CTRL); + } else { + /* Disable PHY polling via SoC */ + sw_w32_mask(BIT(7), 0, RTL839X_SMI_GLB_CTRL); + } + + /* Power on fibre ports and reset them if necessary */ + if (priv->ports[24].phy == PHY_RTL838X_SDS) { + pr_debug("Powering on fibre ports & reset\n"); + rtl8380_sds_power(24, 1); + rtl8380_sds_power(26, 1); + } + + // TODO: Only power on SerDes with external PHYs connected + if (priv->family_id == RTL9300_FAMILY_ID) { + pr_info("RTL9300 Powering on SerDes ports\n"); + rtl9300_sds_power(24, 1); + rtl9300_sds_power(25, 1); + rtl9300_sds_power(26, 1); + rtl9300_sds_power(27, 1); + } + + pr_debug("%s done\n", __func__); + return 0; +} + +static int __init rtl83xx_get_l2aging(struct rtl838x_switch_priv *priv) +{ + int t = sw_r32(priv->r->l2_ctrl_1); + + t &= priv->family_id == RTL8380_FAMILY_ID ? 0x7fffff : 0x1FFFFF; + + if (priv->family_id == RTL8380_FAMILY_ID) + t = t * 128 / 625; /* Aging time in seconds. 0: L2 aging disabled */ + else + t = (t * 3) / 5; + + pr_debug("L2 AGING time: %d sec\n", t); + pr_debug("Dynamic aging for ports: %x\n", sw_r32(priv->r->l2_port_aging_out)); + return t; +} + +/* Caller must hold priv->reg_mutex */ +int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port) +{ + struct rtl838x_switch_priv *priv = ds->priv; + int i; + + pr_info("%s: Adding port %d to LA-group %d\n", __func__, port, group); + if (group >= priv->n_lags) { + pr_err("Link Agrregation group too large.\n"); + return -EINVAL; + } + + if (port >= priv->cpu_port) { + pr_err("Invalid port number.\n"); + return -EINVAL; + } + + for (i = 0; i < priv->n_lags; i++) { + if (priv->lags_port_members[i] & BIT_ULL(i)) + break; + } + if (i != priv->n_lags) { + pr_err("%s: Port already member of LAG: %d\n", __func__, i); + return -ENOSPC; + } + + priv->r->mask_port_reg_be(0, BIT_ULL(port), priv->r->trk_mbr_ctr(group)); + priv->lags_port_members[group] |= BIT_ULL(port); + + pr_info("lags_port_members %d now %016llx\n", group, priv->lags_port_members[group]); + return 0; +} + +/* Caller must hold priv->reg_mutex */ +int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + pr_info("%s: Removing port %d from LA-group %d\n", __func__, port, group); + + if (group >= priv->n_lags) { + pr_err("Link Agrregation group too large.\n"); + return -EINVAL; + } + + if (port >= priv->cpu_port) { + pr_err("Invalid port number.\n"); + return -EINVAL; + } + + + if (!(priv->lags_port_members[group] & BIT_ULL(port))) { + pr_err("%s: Port not member of LAG: %d\n", __func__, group + ); + return -ENOSPC; + } + + priv->r->mask_port_reg_be(BIT_ULL(port), 0, priv->r->trk_mbr_ctr(group)); + priv->lags_port_members[group] &= ~BIT_ULL(port); + + pr_info("lags_port_members %d now %016llx\n", group, priv->lags_port_members[group]); + return 0; +} + +static int rtl83xx_handle_changeupper(struct rtl838x_switch_priv *priv, + struct net_device *ndev, + struct netdev_notifier_changeupper_info *info) +{ + struct net_device *upper = info->upper_dev; + int i, j, err; + + if (!netif_is_lag_master(upper)) + return 0; + + mutex_lock(&priv->reg_mutex); + + for (i = 0; i < priv->n_lags; i++) { + if ((!priv->lag_devs[i]) || (priv->lag_devs[i] == upper)) + break; + } + for (j = 0; j < priv->cpu_port; j++) { + if (priv->ports[j].dp->slave == ndev) + break; + } + if (j >= priv->cpu_port) { + err = -EINVAL; + goto out; + } + + if (info->linking) { + if (!priv->lag_devs[i]) + priv->lag_devs[i] = upper; + err = rtl83xx_lag_add(priv->ds, i, priv->ports[j].dp->index); + if (err) { + err = -EINVAL; + goto out; + } + } else { + if (!priv->lag_devs[i]) + err = -EINVAL; + err = rtl83xx_lag_del(priv->ds, i, priv->ports[j].dp->index); + if (err) { + err = -EINVAL; + goto out; + } + if (!priv->lags_port_members[i]) + priv->lag_devs[i] = NULL; + } + +out: + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int rtl83xx_netdevice_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *ndev = netdev_notifier_info_to_dev(ptr); + struct rtl838x_switch_priv *priv; + int err; + + pr_debug("In: %s, event: %lu\n", __func__, event); + + if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE)) + return NOTIFY_DONE; + + priv = container_of(this, struct rtl838x_switch_priv, nb); + switch (event) { + case NETDEV_CHANGEUPPER: + err = rtl83xx_handle_changeupper(priv, ndev, ptr); + break; + } + + if (err) + return err; + + return NOTIFY_DONE; +} + +static int __init rtl83xx_sw_probe(struct platform_device *pdev) +{ + int err = 0, i; + struct rtl838x_switch_priv *priv; + struct device *dev = &pdev->dev; + u64 bpdu_mask; + + pr_debug("Probing RTL838X switch device\n"); + if (!pdev->dev.of_node) { + dev_err(dev, "No DT found\n"); + return -EINVAL; + } + + // Initialize access to RTL switch tables + rtl_table_init(); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->ds = dsa_switch_alloc(dev, DSA_MAX_PORTS); + + if (!priv->ds) + return -ENOMEM; + priv->ds->dev = dev; + priv->ds->priv = priv; + priv->ds->ops = &rtl83xx_switch_ops; + priv->dev = dev; + + priv->family_id = soc_info.family; + priv->id = soc_info.id; + switch(soc_info.family) { + case RTL8380_FAMILY_ID: + priv->ds->ops = &rtl83xx_switch_ops; + priv->cpu_port = RTL838X_CPU_PORT; + priv->port_mask = 0x1f; + priv->port_width = 1; + priv->irq_mask = 0x0FFFFFFF; + priv->r = &rtl838x_reg; + priv->ds->num_ports = 29; + priv->fib_entries = 8192; + rtl8380_get_version(priv); + priv->n_lags = 8; + priv->l2_bucket_size = 4; + break; + case RTL8390_FAMILY_ID: + priv->ds->ops = &rtl83xx_switch_ops; + priv->cpu_port = RTL839X_CPU_PORT; + priv->port_mask = 0x3f; + priv->port_width = 2; + priv->irq_mask = 0xFFFFFFFFFFFFFULL; + priv->r = &rtl839x_reg; + priv->ds->num_ports = 53; + priv->fib_entries = 16384; + rtl8390_get_version(priv); + priv->n_lags = 16; + priv->l2_bucket_size = 4; + break; + case RTL9300_FAMILY_ID: + priv->ds->ops = &rtl930x_switch_ops; + priv->cpu_port = RTL930X_CPU_PORT; + priv->port_mask = 0x1f; + priv->port_width = 1; + priv->irq_mask = 0x0FFFFFFF; + priv->r = &rtl930x_reg; + priv->ds->num_ports = 29; + priv->fib_entries = 16384; + priv->version = RTL8390_VERSION_A; + priv->n_lags = 16; + sw_w32(1, RTL930X_ST_CTRL); + priv->l2_bucket_size = 8; + break; + case RTL9310_FAMILY_ID: + priv->ds->ops = &rtl930x_switch_ops; + priv->cpu_port = RTL931X_CPU_PORT; + priv->port_mask = 0x3f; + priv->port_width = 2; + priv->irq_mask = 0xFFFFFFFFFFFFFULL; + priv->r = &rtl931x_reg; + priv->ds->num_ports = 57; + priv->fib_entries = 16384; + priv->version = RTL8390_VERSION_A; + priv->n_lags = 16; + priv->l2_bucket_size = 8; + break; + } + pr_debug("Chip version %c\n", priv->version); + + err = rtl83xx_mdio_probe(priv); + if (err) { + /* Probing fails the 1st time because of missing ethernet driver + * initialization. Use this to disable traffic in case the bootloader left if on + */ + return err; + } + err = dsa_register_switch(priv->ds); + if (err) { + dev_err(dev, "Error registering switch: %d\n", err); + return err; + } + + /* Enable link and media change interrupts. Are the SERDES masks needed? */ + sw_w32_mask(0, 3, priv->r->isr_glb_src); + + priv->r->set_port_reg_le(priv->irq_mask, priv->r->isr_port_link_sts_chg); + priv->r->set_port_reg_le(priv->irq_mask, priv->r->imr_port_link_sts_chg); + + priv->link_state_irq = platform_get_irq(pdev, 0); + pr_info("LINK state irq: %d\n", priv->link_state_irq); + switch (priv->family_id) { + case RTL8380_FAMILY_ID: + err = request_irq(priv->link_state_irq, rtl838x_switch_irq, + IRQF_SHARED, "rtl838x-link-state", priv->ds); + break; + case RTL8390_FAMILY_ID: + err = request_irq(priv->link_state_irq, rtl839x_switch_irq, + IRQF_SHARED, "rtl839x-link-state", priv->ds); + break; + case RTL9300_FAMILY_ID: + err = request_irq(priv->link_state_irq, rtl930x_switch_irq, + IRQF_SHARED, "rtl930x-link-state", priv->ds); + break; + case RTL9310_FAMILY_ID: + err = request_irq(priv->link_state_irq, rtl931x_switch_irq, + IRQF_SHARED, "rtl931x-link-state", priv->ds); + break; + } + if (err) { + dev_err(dev, "Error setting up switch interrupt.\n"); + /* Need to free allocated switch here */ + } + + /* Enable interrupts for switch, on RTL931x, the IRQ is always on globally */ + if (soc_info.family != RTL9310_FAMILY_ID) + sw_w32(0x1, priv->r->imr_glb); + + rtl83xx_get_l2aging(priv); + + rtl83xx_setup_qos(priv); + + /* Clear all destination ports for mirror groups */ + for (i = 0; i < 4; i++) + priv->mirror_group_ports[i] = -1; + + priv->nb.notifier_call = rtl83xx_netdevice_event; + if (register_netdevice_notifier(&priv->nb)) { + priv->nb.notifier_call = NULL; + dev_err(dev, "Failed to register LAG netdev notifier\n"); + } + + // Flood BPDUs to all ports including cpu-port + if (soc_info.family != RTL9300_FAMILY_ID) { // TODO: Port this functionality + bpdu_mask = soc_info.family == RTL8380_FAMILY_ID ? 0x1FFFFFFF : 0x1FFFFFFFFFFFFF; + priv->r->set_port_reg_be(bpdu_mask, priv->r->rma_bpdu_fld_pmask); + + // TRAP 802.1X frames (EAPOL) to the CPU-Port, bypass STP and VLANs + sw_w32(7, priv->r->spcl_trap_eapol_ctrl); + + rtl838x_dbgfs_init(priv); + } + + return err; +} + +static int rtl83xx_sw_remove(struct platform_device *pdev) +{ + // TODO: + pr_debug("Removing platform driver for rtl83xx-sw\n"); + return 0; +} + +static const struct of_device_id rtl83xx_switch_of_ids[] = { + { .compatible = "realtek,rtl83xx-switch"}, + { /* sentinel */ } +}; + + +MODULE_DEVICE_TABLE(of, rtl83xx_switch_of_ids); + +static struct platform_driver rtl83xx_switch_driver = { + .probe = rtl83xx_sw_probe, + .remove = rtl83xx_sw_remove, + .driver = { + .name = "rtl83xx-switch", + .pm = NULL, + .of_match_table = rtl83xx_switch_of_ids, + }, +}; + +module_platform_driver(rtl83xx_switch_driver); + +MODULE_AUTHOR("B. Koblitz"); +MODULE_DESCRIPTION("RTL83XX SoC Switch Driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c new file mode 100644 index 0000000000..4f81408453 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include +#include "rtl83xx.h" + +#define RTL838X_DRIVER_NAME "rtl838x" + +#define RTL8380_LED_GLB_CTRL (0xA000) +#define RTL8380_LED_MODE_SEL (0x1004) +#define RTL8380_LED_MODE_CTRL (0xA004) +#define RTL8380_LED_P_EN_CTRL (0xA008) +#define RTL8380_LED_SW_CTRL (0xA00C) +#define RTL8380_LED0_SW_P_EN_CTRL (0xA010) +#define RTL8380_LED1_SW_P_EN_CTRL (0xA014) +#define RTL8380_LED2_SW_P_EN_CTRL (0xA018) +#define RTL8380_LED_SW_P_CTRL(p) (0xA01C + (((p) << 2))) + +#define RTL8390_LED_GLB_CTRL (0x00E4) +#define RTL8390_LED_SET_2_3_CTRL (0x00E8) +#define RTL8390_LED_SET_0_1_CTRL (0x00EC) +#define RTL8390_LED_COPR_SET_SEL_CTRL(p) (0x00F0 + (((p >> 4) << 2))) +#define RTL8390_LED_FIB_SET_SEL_CTRL(p) (0x0100 + (((p >> 4) << 2))) +#define RTL8390_LED_COPR_PMASK_CTRL(p) (0x0110 + (((p >> 5) << 2))) +#define RTL8390_LED_FIB_PMASK_CTRL(p) (0x00118 + (((p >> 5) << 2))) +#define RTL8390_LED_COMBO_CTRL(p) (0x0120 + (((p >> 5) << 2))) +#define RTL8390_LED_SW_CTRL (0x0128) +#define RTL8390_LED_SW_P_EN_CTRL(p) (0x012C + (((p / 10) << 2))) +#define RTL8390_LED_SW_P_CTRL(p) (0x0144 + (((p) << 2))) + +#define RTL838X_MIR_QID_CTRL(grp) (0xAD44 + (((grp) << 2))) +#define RTL838X_MIR_RSPAN_VLAN_CTRL(grp) (0xA340 + (((grp) << 2))) +#define RTL838X_MIR_RSPAN_VLAN_CTRL_MAC(grp) (0xAA70 + (((grp) << 2))) +#define RTL838X_MIR_RSPAN_TX_CTRL (0xA350) +#define RTL838X_MIR_RSPAN_TX_TAG_RM_CTRL (0xAA80) +#define RTL838X_MIR_RSPAN_TX_TAG_EN_CTRL (0xAA84) +#define RTL839X_MIR_RSPAN_VLAN_CTRL(grp) (0xA340 + (((grp) << 2))) +#define RTL839X_MIR_RSPAN_TX_CTRL (0x69b0) +#define RTL839X_MIR_RSPAN_TX_TAG_RM_CTRL (0x2550) +#define RTL839X_MIR_RSPAN_TX_TAG_EN_CTRL (0x2554) +#define RTL839X_MIR_SAMPLE_RATE_CTRL (0x2558) + +int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port); +void rtl83xx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); +void rtl83xx_fast_age(struct dsa_switch *ds, int port); +u32 rtl838x_get_egress_rate(struct rtl838x_switch_priv *priv, int port); +u32 rtl839x_get_egress_rate(struct rtl838x_switch_priv *priv, int port); +int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate); +int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate); + +static ssize_t rtl838x_common_read(char __user *buffer, size_t count, + loff_t *ppos, unsigned int value) +{ + char *buf; + ssize_t len; + + if (*ppos != 0) + return 0; + + buf = kasprintf(GFP_KERNEL, "0x%08x\n", value); + if (!buf) + return -ENOMEM; + + if (count < strlen(buf)) { + kfree(buf); + return -ENOSPC; + } + + len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); + kfree(buf); + + return len; +} + +static ssize_t rtl838x_common_write(const char __user *buffer, size_t count, + loff_t *ppos, unsigned int *value) +{ + char b[32]; + ssize_t len; + int ret; + + if (*ppos != 0) + return -EINVAL; + + if (count >= sizeof(b)) + return -ENOSPC; + + len = simple_write_to_buffer(b, sizeof(b) - 1, ppos, + buffer, count); + if (len < 0) + return len; + + b[len] = '\0'; + ret = kstrtouint(b, 16, value); + if (ret) + return -EIO; + + return len; +} + +static ssize_t stp_state_read(struct file *filp, char __user *buffer, size_t count, + loff_t *ppos) +{ + struct rtl838x_port *p = filp->private_data; + struct dsa_switch *ds = p->dp->ds; + int value = rtl83xx_port_get_stp_state(ds->priv, p->dp->index); + + if (value < 0) + return -EINVAL; + + return rtl838x_common_read(buffer, count, ppos, (u32)value); +} + +static ssize_t stp_state_write(struct file *filp, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct rtl838x_port *p = filp->private_data; + u32 value; + size_t res = rtl838x_common_write(buffer, count, ppos, &value); + if (res < 0) + return res; + + rtl83xx_port_stp_state_set(p->dp->ds, p->dp->index, (u8)value); + + return res; +} + +static const struct file_operations stp_state_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = stp_state_read, + .write = stp_state_write, +}; + +static ssize_t age_out_read(struct file *filp, char __user *buffer, size_t count, + loff_t *ppos) +{ + struct rtl838x_port *p = filp->private_data; + struct dsa_switch *ds = p->dp->ds; + struct rtl838x_switch_priv *priv = ds->priv; + int value = sw_r32(priv->r->l2_port_aging_out); + + if (value < 0) + return -EINVAL; + + return rtl838x_common_read(buffer, count, ppos, (u32)value); +} + +static ssize_t age_out_write(struct file *filp, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct rtl838x_port *p = filp->private_data; + u32 value; + size_t res = rtl838x_common_write(buffer, count, ppos, &value); + if (res < 0) + return res; + + rtl83xx_fast_age(p->dp->ds, p->dp->index); + + return res; +} + +static const struct file_operations age_out_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = age_out_read, + .write = age_out_write, +}; + +static ssize_t port_egress_rate_read(struct file *filp, char __user *buffer, size_t count, + loff_t *ppos) +{ + struct rtl838x_port *p = filp->private_data; + struct dsa_switch *ds = p->dp->ds; + struct rtl838x_switch_priv *priv = ds->priv; + int value; + if (priv->family_id == RTL8380_FAMILY_ID) + value = rtl838x_get_egress_rate(priv, p->dp->index); + else + value = rtl839x_get_egress_rate(priv, p->dp->index); + + if (value < 0) + return -EINVAL; + + return rtl838x_common_read(buffer, count, ppos, (u32)value); +} + +static ssize_t port_egress_rate_write(struct file *filp, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct rtl838x_port *p = filp->private_data; + struct dsa_switch *ds = p->dp->ds; + struct rtl838x_switch_priv *priv = ds->priv; + u32 value; + size_t res = rtl838x_common_write(buffer, count, ppos, &value); + if (res < 0) + return res; + + if (priv->family_id == RTL8380_FAMILY_ID) + rtl838x_set_egress_rate(priv, p->dp->index, value); + else + rtl839x_set_egress_rate(priv, p->dp->index, value); + + return res; +} + +static const struct file_operations port_egress_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = port_egress_rate_read, + .write = port_egress_rate_write, +}; + + +static const struct debugfs_reg32 port_ctrl_regs[] = { + { .name = "port_isolation", .offset = RTL838X_PORT_ISO_CTRL(0), }, + { .name = "mac_force_mode", .offset = RTL838X_MAC_FORCE_MODE_CTRL, }, +}; + +void rtl838x_dbgfs_cleanup(struct rtl838x_switch_priv *priv) +{ + debugfs_remove_recursive(priv->dbgfs_dir); + +// kfree(priv->dbgfs_entries); +} + +static int rtl838x_dbgfs_port_init(struct dentry *parent, struct rtl838x_switch_priv *priv, + int port) +{ + struct dentry *port_dir; + struct debugfs_regset32 *port_ctrl_regset; + + port_dir = debugfs_create_dir(priv->ports[port].dp->name, parent); + + if (priv->family_id == RTL8380_FAMILY_ID) { + debugfs_create_x32("storm_rate_uc", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_STORM_CTRL_PORT_UC(port))); + + debugfs_create_x32("storm_rate_mc", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_STORM_CTRL_PORT_MC(port))); + + debugfs_create_x32("storm_rate_bc", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_STORM_CTRL_PORT_BC(port))); + + debugfs_create_x32("vlan_port_tag_sts_ctrl", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_VLAN_PORT_TAG_STS_CTRL + + (port << 2))); + } else { + debugfs_create_x32("storm_rate_uc", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_STORM_CTRL_PORT_UC_0(port))); + + debugfs_create_x32("storm_rate_mc", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_STORM_CTRL_PORT_MC_0(port))); + + debugfs_create_x32("storm_rate_bc", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_STORM_CTRL_PORT_BC_0(port))); + + debugfs_create_x32("vlan_port_tag_sts_ctrl", 0644, port_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_VLAN_PORT_TAG_STS_CTRL + + (port << 2))); + } + + debugfs_create_u32("id", 0444, port_dir, (u32 *)&priv->ports[port].dp->index); + + port_ctrl_regset = devm_kzalloc(priv->dev, sizeof(*port_ctrl_regset), GFP_KERNEL); + if (!port_ctrl_regset) + return -ENOMEM; + + port_ctrl_regset->regs = port_ctrl_regs; + port_ctrl_regset->nregs = ARRAY_SIZE(port_ctrl_regs); + port_ctrl_regset->base = (void *)(RTL838X_SW_BASE + (port << 2)); + debugfs_create_regset32("port_ctrl", 0400, port_dir, port_ctrl_regset); + + debugfs_create_file("stp_state", 0600, port_dir, &priv->ports[port], &stp_state_fops); + debugfs_create_file("age_out", 0600, port_dir, &priv->ports[port], &age_out_fops); + debugfs_create_file("port_egress_rate", 0600, port_dir, &priv->ports[port], + &port_egress_fops); + return 0; +} + +static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv *priv) +{ + struct dentry *led_dir; + int p; + char led_sw_p_ctrl_name[20]; + char port_led_name[20]; + + led_dir = debugfs_create_dir("led", parent); + + if (priv->family_id == RTL8380_FAMILY_ID) { + debugfs_create_x32("led_glb_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED_GLB_CTRL)); + debugfs_create_x32("led_mode_sel", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_SEL)); + debugfs_create_x32("led_mode_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_CTRL)); + debugfs_create_x32("led_p_en_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED_P_EN_CTRL)); + debugfs_create_x32("led_sw_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_CTRL)); + debugfs_create_x32("led0_sw_p_en_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED0_SW_P_EN_CTRL)); + debugfs_create_x32("led1_sw_p_en_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED1_SW_P_EN_CTRL)); + debugfs_create_x32("led2_sw_p_en_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED2_SW_P_EN_CTRL)); + for (p = 0; p < 28; p++) { + snprintf(led_sw_p_ctrl_name, sizeof(led_sw_p_ctrl_name), + "led_sw_p_ctrl.%02d", p); + debugfs_create_x32(led_sw_p_ctrl_name, 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_P_CTRL(p))); + } + } else if (priv->family_id == RTL8390_FAMILY_ID) { + debugfs_create_x32("led_glb_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_GLB_CTRL)); + debugfs_create_x32("led_set_2_3", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_SET_2_3_CTRL)); + debugfs_create_x32("led_set_0_1", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_SET_0_1_CTRL)); + for (p = 0; p < 4; p++) { + snprintf(port_led_name, sizeof(port_led_name), "led_copr_set_sel.%1d", p); + debugfs_create_x32(port_led_name, 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_SET_SEL_CTRL(p << 4))); + snprintf(port_led_name, sizeof(port_led_name), "led_fib_set_sel.%1d", p); + debugfs_create_x32(port_led_name, 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_FIB_SET_SEL_CTRL(p << 4))); + } + debugfs_create_x32("led_copr_pmask_ctrl_0", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_PMASK_CTRL(0))); + debugfs_create_x32("led_copr_pmask_ctrl_1", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_PMASK_CTRL(32))); + debugfs_create_x32("led_fib_pmask_ctrl_0", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_FIB_PMASK_CTRL(0))); + debugfs_create_x32("led_fib_pmask_ctrl_1", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_FIB_PMASK_CTRL(32))); + debugfs_create_x32("led_combo_ctrl_0", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_COMBO_CTRL(0))); + debugfs_create_x32("led_combo_ctrl_1", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_COMBO_CTRL(32))); + debugfs_create_x32("led_sw_ctrl", 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_CTRL)); + for (p = 0; p < 5; p++) { + snprintf(port_led_name, sizeof(port_led_name), "led_sw_p_en_ctrl.%1d", p); + debugfs_create_x32(port_led_name, 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_P_EN_CTRL(p * 10))); + } + for (p = 0; p < 28; p++) { + snprintf(port_led_name, sizeof(port_led_name), "led_sw_p_ctrl.%02d", p); + debugfs_create_x32(port_led_name, 0644, led_dir, + (u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_P_CTRL(p))); + } + } + return 0; +} + +void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv) +{ + struct dentry *rtl838x_dir; + struct dentry *port_dir; + struct dentry *mirror_dir; + struct debugfs_regset32 *port_ctrl_regset; + int ret, i; + char lag_name[10]; + char mirror_name[10]; + + pr_info("%s called\n", __func__); + rtl838x_dir = debugfs_lookup(RTL838X_DRIVER_NAME, NULL); + if (!rtl838x_dir) + rtl838x_dir = debugfs_create_dir(RTL838X_DRIVER_NAME, NULL); + + priv->dbgfs_dir = rtl838x_dir; + + debugfs_create_u32("soc", 0444, rtl838x_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MODEL_NAME_INFO)); + + /* Create one directory per port */ + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) { + ret = rtl838x_dbgfs_port_init(rtl838x_dir, priv, i); + if (ret) + goto err; + } + } + + /* Create directory for CPU-port */ + port_dir = debugfs_create_dir("cpu_port", rtl838x_dir); + port_ctrl_regset = devm_kzalloc(priv->dev, sizeof(*port_ctrl_regset), GFP_KERNEL); + if (!port_ctrl_regset) { + ret = -ENOMEM; + goto err; + } + + port_ctrl_regset->regs = port_ctrl_regs; + port_ctrl_regset->nregs = ARRAY_SIZE(port_ctrl_regs); + port_ctrl_regset->base = (void *)(RTL838X_SW_BASE + (priv->cpu_port << 2)); + debugfs_create_regset32("port_ctrl", 0400, port_dir, port_ctrl_regset); + debugfs_create_u8("id", 0444, port_dir, &priv->cpu_port); + + /* Create entries for LAGs */ + for (i = 0; i < priv->n_lags; i++) { + snprintf(lag_name, sizeof(lag_name), "lag.%02d", i); + if (priv->family_id == RTL8380_FAMILY_ID) + debugfs_create_x32(lag_name, 0644, rtl838x_dir, + (u32 *)(RTL838X_SW_BASE + priv->r->trk_mbr_ctr(i))); + else + debugfs_create_x64(lag_name, 0644, rtl838x_dir, + (u64 *)(RTL838X_SW_BASE + priv->r->trk_mbr_ctr(i))); + } + + /* Create directories for mirror groups */ + for (i = 0; i < 4; i++) { + snprintf(mirror_name, sizeof(mirror_name), "mirror.%1d", i); + mirror_dir = debugfs_create_dir(mirror_name, rtl838x_dir); + if (priv->family_id == RTL8380_FAMILY_ID) { + debugfs_create_x32("ctrl", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_CTRL + i * 4)); + debugfs_create_x32("ingress_pm", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + priv->r->mir_spm + i * 4)); + debugfs_create_x32("egress_pm", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + priv->r->mir_dpm + i * 4)); + debugfs_create_x32("qid", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_QID_CTRL(i))); + debugfs_create_x32("rspan_vlan", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_VLAN_CTRL(i))); + debugfs_create_x32("rspan_vlan_mac", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_VLAN_CTRL_MAC(i))); + debugfs_create_x32("rspan_tx", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_TX_CTRL)); + debugfs_create_x32("rspan_tx_tag_rm", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_TX_TAG_RM_CTRL)); + debugfs_create_x32("rspan_tx_tag_en", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_TX_TAG_EN_CTRL)); + } else { + debugfs_create_x32("ctrl", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_CTRL + i * 4)); + debugfs_create_x64("ingress_pm", 0644, mirror_dir, + (u64 *)(RTL838X_SW_BASE + priv->r->mir_spm + i * 8)); + debugfs_create_x64("egress_pm", 0644, mirror_dir, + (u64 *)(RTL838X_SW_BASE + priv->r->mir_dpm + i * 8)); + debugfs_create_x32("rspan_vlan", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_VLAN_CTRL(i))); + debugfs_create_x32("rspan_tx", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_TX_CTRL)); + debugfs_create_x32("rspan_tx_tag_rm", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_TX_TAG_RM_CTRL)); + debugfs_create_x32("rspan_tx_tag_en", 0644, mirror_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_TX_TAG_EN_CTRL)); + debugfs_create_x64("sample_rate", 0644, mirror_dir, + (u64 *)(RTL838X_SW_BASE + RTL839X_MIR_SAMPLE_RATE_CTRL)); + } + } + + if (priv->family_id == RTL8380_FAMILY_ID) + debugfs_create_x32("bpdu_flood_mask", 0644, rtl838x_dir, + (u32 *)(RTL838X_SW_BASE + priv->r->rma_bpdu_fld_pmask)); + else + debugfs_create_x64("bpdu_flood_mask", 0644, rtl838x_dir, + (u64 *)(RTL838X_SW_BASE + priv->r->rma_bpdu_fld_pmask)); + + if (priv->family_id == RTL8380_FAMILY_ID) + debugfs_create_x32("vlan_ctrl", 0644, rtl838x_dir, + (u32 *)(RTL838X_SW_BASE + RTL838X_VLAN_CTRL)); + else + debugfs_create_x32("vlan_ctrl", 0644, rtl838x_dir, + (u32 *)(RTL838X_SW_BASE + RTL839X_VLAN_CTRL)); + + ret = rtl838x_dbgfs_leds(rtl838x_dir, priv); + if (ret) + goto err; + + return; +err: + rtl838x_dbgfs_cleanup(priv); +} 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 new file mode 100644 index 0000000000..c2a230c4cb --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -0,0 +1,1587 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include +#include "rtl83xx.h" + + +extern struct rtl83xx_soc_info soc_info; + + +static void rtl83xx_init_stats(struct rtl838x_switch_priv *priv) +{ + mutex_lock(&priv->reg_mutex); + + /* Enable statistics module: all counters plus debug. + * On RTL839x all counters are enabled by default + */ + if (priv->family_id == RTL8380_FAMILY_ID) + sw_w32_mask(0, 3, RTL838X_STAT_CTRL); + + /* Reset statistics counters */ + sw_w32_mask(0, 1, priv->r->stat_rst); + + mutex_unlock(&priv->reg_mutex); +} + +static void rtl83xx_enable_phy_polling(struct rtl838x_switch_priv *priv) +{ + int i; + u64 v = 0; + + msleep(1000); + /* Enable all ports with a PHY, including the SFP-ports */ + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) + v |= BIT_ULL(i); + } + + pr_debug("%s: %16llx\n", __func__, v); + priv->r->set_port_reg_le(v, priv->r->smi_poll_ctrl); + + /* PHY update complete, there is no global PHY polling enable bit on the 9300 */ + if (priv->family_id == RTL8390_FAMILY_ID) + sw_w32_mask(0, BIT(7), RTL839X_SMI_GLB_CTRL); + else if(priv->family_id == RTL9300_FAMILY_ID) + sw_w32_mask(0, 0x8000, RTL838X_SMI_GLB_CTRL); +} + +const struct rtl83xx_mib_desc rtl83xx_mib[] = { + MIB_DESC(2, 0xf8, "ifInOctets"), + MIB_DESC(2, 0xf0, "ifOutOctets"), + MIB_DESC(1, 0xec, "dot1dTpPortInDiscards"), + MIB_DESC(1, 0xe8, "ifInUcastPkts"), + MIB_DESC(1, 0xe4, "ifInMulticastPkts"), + MIB_DESC(1, 0xe0, "ifInBroadcastPkts"), + MIB_DESC(1, 0xdc, "ifOutUcastPkts"), + MIB_DESC(1, 0xd8, "ifOutMulticastPkts"), + MIB_DESC(1, 0xd4, "ifOutBroadcastPkts"), + MIB_DESC(1, 0xd0, "ifOutDiscards"), + MIB_DESC(1, 0xcc, ".3SingleCollisionFrames"), + MIB_DESC(1, 0xc8, ".3MultipleCollisionFrames"), + MIB_DESC(1, 0xc4, ".3DeferredTransmissions"), + MIB_DESC(1, 0xc0, ".3LateCollisions"), + MIB_DESC(1, 0xbc, ".3ExcessiveCollisions"), + MIB_DESC(1, 0xb8, ".3SymbolErrors"), + MIB_DESC(1, 0xb4, ".3ControlInUnknownOpcodes"), + MIB_DESC(1, 0xb0, ".3InPauseFrames"), + MIB_DESC(1, 0xac, ".3OutPauseFrames"), + MIB_DESC(1, 0xa8, "DropEvents"), + MIB_DESC(1, 0xa4, "tx_BroadcastPkts"), + MIB_DESC(1, 0xa0, "tx_MulticastPkts"), + MIB_DESC(1, 0x9c, "CRCAlignErrors"), + MIB_DESC(1, 0x98, "tx_UndersizePkts"), + MIB_DESC(1, 0x94, "rx_UndersizePkts"), + MIB_DESC(1, 0x90, "rx_UndersizedropPkts"), + MIB_DESC(1, 0x8c, "tx_OversizePkts"), + MIB_DESC(1, 0x88, "rx_OversizePkts"), + MIB_DESC(1, 0x84, "Fragments"), + MIB_DESC(1, 0x80, "Jabbers"), + MIB_DESC(1, 0x7c, "Collisions"), + MIB_DESC(1, 0x78, "tx_Pkts64Octets"), + MIB_DESC(1, 0x74, "rx_Pkts64Octets"), + MIB_DESC(1, 0x70, "tx_Pkts65to127Octets"), + MIB_DESC(1, 0x6c, "rx_Pkts65to127Octets"), + MIB_DESC(1, 0x68, "tx_Pkts128to255Octets"), + MIB_DESC(1, 0x64, "rx_Pkts128to255Octets"), + MIB_DESC(1, 0x60, "tx_Pkts256to511Octets"), + MIB_DESC(1, 0x5c, "rx_Pkts256to511Octets"), + MIB_DESC(1, 0x58, "tx_Pkts512to1023Octets"), + MIB_DESC(1, 0x54, "rx_Pkts512to1023Octets"), + MIB_DESC(1, 0x50, "tx_Pkts1024to1518Octets"), + MIB_DESC(1, 0x4c, "rx_StatsPkts1024to1518Octets"), + MIB_DESC(1, 0x48, "tx_Pkts1519toMaxOctets"), + MIB_DESC(1, 0x44, "rx_Pkts1519toMaxOctets"), + MIB_DESC(1, 0x40, "rxMacDiscards") +}; + + +/* DSA callbacks */ + + +static enum dsa_tag_protocol rtl83xx_get_tag_protocol(struct dsa_switch *ds, int port) +{ + /* The switch does not tag the frames, instead internally the header + * structure for each packet is tagged accordingly. + */ + return DSA_TAG_PROTO_TRAILER; +} + +/* + * Initialize all VLANS + */ +static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv) +{ + struct rtl838x_vlan_info info; + int i; + + pr_info("In %s\n", __func__); + + priv->r->vlan_profile_setup(0); + priv->r->vlan_profile_setup(1); + pr_info("UNKNOWN_MC_PMASK: %016llx\n", priv->r->read_mcast_pmask(UNKNOWN_MC_PMASK)); + priv->r->vlan_profile_dump(0); + + info.fid = 0; // Default Forwarding ID / MSTI + info.hash_uc_fid = false; // Do not build the L2 lookup hash with FID, but VID + info.hash_mc_fid = false; // Do the same for Multicast packets + info.profile_id = 0; // Use default Vlan Profile 0 + info.tagged_ports = 0; // Initially no port members + + // Initialize all vlans 0-4095 + for (i = 0; i < MAX_VLANS; i ++) + priv->r->vlan_set_tagged(i, &info); + + // reset PVIDs; defaults to 1 on reset + for (i = 0; i <= priv->ds->num_ports; i++) + sw_w32(0, priv->r->vlan_port_pb + (i << 2)); + + // Set forwarding action based on inner VLAN tag + for (i = 0; i < priv->cpu_port; i++) + priv->r->vlan_fwd_on_inner(i, true); +} + +static int rtl83xx_setup(struct dsa_switch *ds) +{ + int i; + struct rtl838x_switch_priv *priv = ds->priv; + u64 port_bitmap = BIT_ULL(priv->cpu_port); + + pr_debug("%s called\n", __func__); + + /* Disable MAC polling the PHY so that we can start configuration */ + priv->r->set_port_reg_le(0ULL, priv->r->smi_poll_ctrl); + + for (i = 0; i < ds->num_ports; i++) + priv->ports[i].enable = false; + priv->ports[priv->cpu_port].enable = true; + + /* Isolate ports from each other: traffic only CPU <-> port */ + /* Setting bit j in register RTL838X_PORT_ISO_CTRL(i) allows + * traffic from source port i to destination port j + */ + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) { + priv->r->set_port_reg_be(BIT_ULL(priv->cpu_port) | BIT_ULL(i), + priv->r->port_iso_ctrl(i)); + port_bitmap |= BIT_ULL(i); + } + } + priv->r->set_port_reg_be(port_bitmap, priv->r->port_iso_ctrl(priv->cpu_port)); + + if (priv->family_id == RTL8380_FAMILY_ID) + rtl838x_print_matrix(); + else + rtl839x_print_matrix(); + + rtl83xx_init_stats(priv); + + rtl83xx_vlan_setup(priv); + + ds->configure_vlan_while_not_filtering = true; + + /* Enable MAC Polling PHY again */ + rtl83xx_enable_phy_polling(priv); + pr_debug("Please wait until PHY is settled\n"); + msleep(1000); + return 0; +} + +static int rtl930x_setup(struct dsa_switch *ds) +{ + int i; + struct rtl838x_switch_priv *priv = ds->priv; + u32 port_bitmap = BIT(priv->cpu_port); + + pr_info("%s called\n", __func__); + + // Enable CSTI STP mode +// sw_w32(1, RTL930X_ST_CTRL); + + /* Disable MAC polling the PHY so that we can start configuration */ + sw_w32(0, RTL930X_SMI_POLL_CTRL); + + // Disable all ports except CPU port + for (i = 0; i < ds->num_ports; i++) + priv->ports[i].enable = false; + priv->ports[priv->cpu_port].enable = true; + + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) { + priv->r->traffic_set(i, BIT_ULL(priv->cpu_port) | BIT_ULL(i)); + port_bitmap |= BIT_ULL(i); + } + } + priv->r->traffic_set(priv->cpu_port, port_bitmap); + + rtl930x_print_matrix(); + + // TODO: Initialize statistics + + rtl83xx_vlan_setup(priv); + + ds->configure_vlan_while_not_filtering = true; + + rtl83xx_enable_phy_polling(priv); + + return 0; +} + +static void rtl83xx_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ + struct rtl838x_switch_priv *priv = ds->priv; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + pr_debug("In %s port %d, state is %d", __func__, port, state->interface); + + if (!phy_interface_mode_is_rgmii(state->interface) && + state->interface != PHY_INTERFACE_MODE_NA && + state->interface != PHY_INTERFACE_MODE_1000BASEX && + state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII && + state->interface != PHY_INTERFACE_MODE_GMII && + state->interface != PHY_INTERFACE_MODE_QSGMII && + state->interface != PHY_INTERFACE_MODE_INTERNAL && + state->interface != PHY_INTERFACE_MODE_SGMII) { + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + dev_err(ds->dev, + "Unsupported interface: %d for port %d\n", + state->interface, port); + return; + } + + /* Allow all the expected bits */ + phylink_set(mask, Autoneg); + phylink_set_port_modes(mask); + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + + /* With the exclusion of MII and Reverse MII, we support Gigabit, + * including Half duplex + */ + if (state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseT_Half); + } + + /* On both the 8380 and 8382, ports 24-27 are SFP ports */ + if (port >= 24 && port <= 27 && priv->family_id == RTL8380_FAMILY_ID) + phylink_set(mask, 1000baseX_Full); + + /* On the RTL839x family of SoCs, ports 48 to 51 are SFP ports */ + if (port >=48 && port <= 51 && priv->family_id == RTL8390_FAMILY_ID) + phylink_set(mask, 1000baseX_Full); + + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + + bitmap_and(supported, supported, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + +static int rtl83xx_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 speed; + u64 link; + + if (port < 0 || port > priv->cpu_port) + return -EINVAL; + + /* + * On the RTL9300 for at least the RTL8226B PHY, the MAC-side link + * state needs to be read twice in order to read a correct result. + * This would not be necessary for ports connected e.g. to RTL8218D + * PHYs. + */ + state->link = 0; + link = priv->r->get_port_reg_le(priv->r->mac_link_sts); + link = priv->r->get_port_reg_le(priv->r->mac_link_sts); + if (link & BIT_ULL(port)) + state->link = 1; + pr_debug("%s: link state port %d: %llx\n", __func__, port, link & BIT_ULL(port)); + + state->duplex = 0; + if (priv->r->get_port_reg_le(priv->r->mac_link_dup_sts) & BIT_ULL(port)) + state->duplex = 1; + + speed = priv->r->get_port_reg_le(priv->r->mac_link_spd_sts(port)); + speed >>= (port % 16) << 1; + switch (speed & 0x3) { + case 0: + state->speed = SPEED_10; + break; + case 1: + state->speed = SPEED_100; + break; + case 2: + state->speed = SPEED_1000; + break; + case 3: + if (priv->family_id == RTL9300_FAMILY_ID + && (port == 24 || port == 26)) /* Internal serdes */ + state->speed = SPEED_2500; + else + state->speed = SPEED_100; /* Is in fact 500Mbit */ + } + + state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); + if (priv->r->get_port_reg_le(priv->r->mac_rx_pause_sts) & BIT_ULL(port)) + state->pause |= MLO_PAUSE_RX; + if (priv->r->get_port_reg_le(priv->r->mac_tx_pause_sts) & BIT_ULL(port)) + state->pause |= MLO_PAUSE_TX; + return 1; +} + +static void rtl83xx_config_interface(int port, phy_interface_t interface) +{ + u32 old, int_shift, sds_shift; + + switch (port) { + case 24: + int_shift = 0; + sds_shift = 5; + break; + case 26: + int_shift = 3; + sds_shift = 0; + break; + default: + return; + } + + old = sw_r32(RTL838X_SDS_MODE_SEL); + switch (interface) { + case PHY_INTERFACE_MODE_1000BASEX: + if ((old >> sds_shift & 0x1f) == 4) + return; + sw_w32_mask(0x7 << int_shift, 1 << int_shift, RTL838X_INT_MODE_CTRL); + sw_w32_mask(0x1f << sds_shift, 4 << sds_shift, RTL838X_SDS_MODE_SEL); + break; + case PHY_INTERFACE_MODE_SGMII: + if ((old >> sds_shift & 0x1f) == 2) + return; + sw_w32_mask(0x7 << int_shift, 2 << int_shift, RTL838X_INT_MODE_CTRL); + sw_w32_mask(0x1f << sds_shift, 2 << sds_shift, RTL838X_SDS_MODE_SEL); + break; + default: + return; + } + pr_debug("configured port %d for interface %s\n", port, phy_modes(interface)); +} + +static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u32 reg; + int speed_bit = priv->family_id == RTL8380_FAMILY_ID ? 4 : 3; + + pr_debug("%s port %d, mode %x\n", __func__, port, mode); + + // BUG: Make this work on RTL93XX + if (priv->family_id >= RTL9300_FAMILY_ID) + return; + + if (port == priv->cpu_port) { + /* Set Speed, duplex, flow control + * FORCE_EN | LINK_EN | NWAY_EN | DUP_SEL + * | SPD_SEL = 0b10 | FORCE_FC_EN | PHY_MASTER_SLV_MANUAL_EN + * | MEDIA_SEL + */ + if (priv->family_id == RTL8380_FAMILY_ID) { + sw_w32(0x6192F, priv->r->mac_force_mode_ctrl(priv->cpu_port)); + /* allow CRC errors on CPU-port */ + sw_w32_mask(0, 0x8, RTL838X_MAC_PORT_CTRL(priv->cpu_port)); + } else { + sw_w32_mask(0, 3, priv->r->mac_force_mode_ctrl(priv->cpu_port)); + } + return; + } + + reg = sw_r32(priv->r->mac_force_mode_ctrl(port)); + /* Auto-Negotiation does not work for MAC in RTL8390 */ + if (priv->family_id == RTL8380_FAMILY_ID) { + if (mode == MLO_AN_PHY || phylink_autoneg_inband(mode)) { + pr_debug("PHY autonegotiates\n"); + reg |= BIT(2); + sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); + rtl83xx_config_interface(port, state->interface); + return; + } + } + + if (mode != MLO_AN_FIXED) + pr_debug("Fixed state.\n"); + + if (priv->family_id == RTL8380_FAMILY_ID) { + /* Clear id_mode_dis bit, and the existing port mode, let + * RGMII_MODE_EN bet set by mac_link_{up,down} + */ + reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN); + + if (state->pause & MLO_PAUSE_TXRX_MASK) { + if (state->pause & MLO_PAUSE_TX) + reg |= TX_PAUSE_EN; + reg |= RX_PAUSE_EN; + } + } + + reg &= ~(3 << speed_bit); + switch (state->speed) { + case SPEED_1000: + reg |= 2 << speed_bit; + break; + case SPEED_100: + reg |= 1 << speed_bit; + break; + } + + if (priv->family_id == RTL8380_FAMILY_ID) { + reg &= ~(DUPLEX_FULL | FORCE_LINK_EN); + if (state->link) + reg |= FORCE_LINK_EN; + if (state->duplex == DUPLEX_FULL) + reg |= DUPLX_MODE; + } + + // Disable AN + if (priv->family_id == RTL8380_FAMILY_ID) + reg &= ~BIT(2); + sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); +} + +static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +{ + struct rtl838x_switch_priv *priv = ds->priv; + /* Stop TX/RX to port */ + sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port)); +} + +static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev) +{ + struct rtl838x_switch_priv *priv = ds->priv; + /* Restart TX/RX to port */ + sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port)); +} + +static void rtl83xx_get_strings(struct dsa_switch *ds, + int port, u32 stringset, u8 *data) +{ + int i; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++) + strncpy(data + i * ETH_GSTRING_LEN, rtl83xx_mib[i].name, + ETH_GSTRING_LEN); +} + +static void rtl83xx_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *data) +{ + struct rtl838x_switch_priv *priv = ds->priv; + const struct rtl83xx_mib_desc *mib; + int i; + u64 h; + + for (i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++) { + mib = &rtl83xx_mib[i]; + + data[i] = sw_r32(priv->r->stat_port_std_mib + (port << 8) + 252 - mib->offset); + if (mib->size == 2) { + h = sw_r32(priv->r->stat_port_std_mib + (port << 8) + 248 - mib->offset); + data[i] |= h << 32; + } + } +} + +static int rtl83xx_get_sset_count(struct dsa_switch *ds, int port, int sset) +{ + if (sset != ETH_SS_STATS) + return 0; + + return ARRAY_SIZE(rtl83xx_mib); +} + +static int rtl83xx_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phydev) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 v; + + pr_debug("%s: %x %d", __func__, (u32) priv, port); + priv->ports[port].enable = true; + + /* enable inner tagging on egress, do not keep any tags */ + if (priv->family_id == RTL9310_FAMILY_ID) + sw_w32(BIT(4), priv->r->vlan_port_tag_sts_ctrl + (port << 2)); + else + sw_w32(1, priv->r->vlan_port_tag_sts_ctrl + (port << 2)); + + if (dsa_is_cpu_port(ds, port)) + return 0; + + /* add port to switch mask of CPU_PORT */ + priv->r->traffic_enable(priv->cpu_port, port); + + /* add all other ports in the same bridge to switch mask of port */ + v = priv->r->traffic_get(port); + v |= priv->ports[port].pm; + priv->r->traffic_set(port, v); + + // TODO: Figure out if this is necessary + if (priv->family_id == RTL9300_FAMILY_ID) { + sw_w32_mask(0, BIT(port), RTL930X_L2_PORT_SABLK_CTRL); + sw_w32_mask(0, BIT(port), RTL930X_L2_PORT_DABLK_CTRL); + } + + return 0; +} + +static void rtl83xx_port_disable(struct dsa_switch *ds, int port) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 v; + + pr_debug("%s %x: %d", __func__, (u32)priv, port); + /* you can only disable user ports */ + if (!dsa_is_user_port(ds, port)) + return; + + // BUG: This does not work on RTL931X + /* remove port from switch mask of CPU_PORT */ + priv->r->traffic_disable(priv->cpu_port, port); + + /* remove all other ports in the same bridge from switch mask of port */ + v = priv->r->traffic_get(port); + v &= ~priv->ports[port].pm; + priv->r->traffic_set(port, v); + + priv->ports[port].enable = false; +} + +static int rtl83xx_set_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_eee *e) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + if (e->eee_enabled && !priv->eee_enabled) { + pr_info("Globally enabling EEE\n"); + priv->r->init_eee(priv, true); + } + + priv->r->port_eee_set(priv, port, e->eee_enabled); + + if (e->eee_enabled) + pr_info("Enabled EEE for port %d\n", port); + else + pr_info("Disabled EEE for port %d\n", port); + return 0; +} + +static int rtl83xx_get_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_eee *e) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + e->supported = SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full; + + priv->r->eee_port_ability(priv, e, port); + + e->eee_enabled = priv->ports[port].eee_enabled; + + e->eee_active = !!(e->advertised & e->lp_advertised); + + return 0; +} + +static int rtl93xx_get_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_eee *e) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + e->supported = SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full + | SUPPORTED_2500baseX_Full; + + priv->r->eee_port_ability(priv, e, port); + + e->eee_enabled = priv->ports[port].eee_enabled; + + e->eee_active = !!(e->advertised & e->lp_advertised); + + return 0; +} + +/* + * Set Switch L2 Aging time, t is time in milliseconds + * t = 0: aging is disabled + */ +static int rtl83xx_set_l2aging(struct dsa_switch *ds, u32 t) +{ + struct rtl838x_switch_priv *priv = ds->priv; + int t_max = priv->family_id == RTL8380_FAMILY_ID ? 0x7fffff : 0x1FFFFF; + + /* Convert time in mseconds to internal value */ + if (t > 0x10000000) { /* Set to maximum */ + t = t_max; + } else { + if (priv->family_id == RTL8380_FAMILY_ID) + t = ((t * 625) / 1000 + 127) / 128; + else + t = (t * 5 + 2) / 3; + } + sw_w32(t, priv->r->l2_ctrl_1); + return 0; +} + +static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port, + struct net_device *bridge) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 port_bitmap = BIT_ULL(priv->cpu_port), v; + int i; + + pr_debug("%s %x: %d %llx", __func__, (u32)priv, port, port_bitmap); + mutex_lock(&priv->reg_mutex); + for (i = 0; i < ds->num_ports; i++) { + /* Add this port to the port matrix of the other ports in the + * same bridge. If the port is disabled, port matrix is kept + * and not being setup until the port becomes enabled. + */ + if (dsa_is_user_port(ds, i) && i != port) { + if (dsa_to_port(ds, i)->bridge_dev != bridge) + continue; + if (priv->ports[i].enable) + priv->r->traffic_enable(i, port); + + priv->ports[i].pm |= BIT_ULL(port); + port_bitmap |= BIT_ULL(i); + } + } + + /* Add all other ports to this port matrix. */ + if (priv->ports[port].enable) { + priv->r->traffic_enable(priv->cpu_port, port); + v = priv->r->traffic_get(port); + v |= port_bitmap; + priv->r->traffic_set(port, v); + } + priv->ports[port].pm |= port_bitmap; + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port, + struct net_device *bridge) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 port_bitmap = BIT_ULL(priv->cpu_port), v; + int i; + + pr_debug("%s %x: %d", __func__, (u32)priv, port); + mutex_lock(&priv->reg_mutex); + for (i = 0; i < ds->num_ports; i++) { + /* Remove this port from the port matrix of the other ports + * in the same bridge. If the port is disabled, port matrix + * is kept and not being setup until the port becomes enabled. + * And the other port's port matrix cannot be broken when the + * other port is still a VLAN-aware port. + */ + if (dsa_is_user_port(ds, i) && i != port) { + if (dsa_to_port(ds, i)->bridge_dev != bridge) + continue; + if (priv->ports[i].enable) + priv->r->traffic_disable(i, port); + + priv->ports[i].pm |= BIT_ULL(port); + port_bitmap &= ~BIT_ULL(i); + } + } + + /* Add all other ports to this port matrix. */ + if (priv->ports[port].enable) { + v = priv->r->traffic_get(port); + v |= port_bitmap; + priv->r->traffic_set(port, v); + } + priv->ports[port].pm &= ~port_bitmap; + + mutex_unlock(&priv->reg_mutex); +} + +void rtl83xx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) +{ + u32 msti = 0; + u32 port_state[4]; + int index, bit; + int pos = port; + struct rtl838x_switch_priv *priv = ds->priv; + int n = priv->port_width << 1; + + /* Ports above or equal CPU port can never be configured */ + if (port >= priv->cpu_port) + return; + + mutex_lock(&priv->reg_mutex); + + /* For the RTL839x and following, the bits are left-aligned, 838x and 930x + * have 64 bit fields, 839x and 931x have 128 bit fields + */ + if (priv->family_id == RTL8390_FAMILY_ID) + pos += 12; + if (priv->family_id == RTL9300_FAMILY_ID) + pos += 3; + if (priv->family_id == RTL9310_FAMILY_ID) + pos += 8; + + index = n - (pos >> 4) - 1; + bit = (pos << 1) % 32; + + priv->r->stp_get(priv, msti, port_state); + + pr_debug("Current state, port %d: %d\n", port, (port_state[index] >> bit) & 3); + port_state[index] &= ~(3 << bit); + + switch (state) { + case BR_STATE_DISABLED: /* 0 */ + port_state[index] |= (0 << bit); + break; + case BR_STATE_BLOCKING: /* 4 */ + case BR_STATE_LISTENING: /* 1 */ + port_state[index] |= (1 << bit); + break; + case BR_STATE_LEARNING: /* 2 */ + port_state[index] |= (2 << bit); + break; + case BR_STATE_FORWARDING: /* 3*/ + port_state[index] |= (3 << bit); + default: + break; + } + + priv->r->stp_set(priv, msti, port_state); + + mutex_unlock(&priv->reg_mutex); +} + +void rtl83xx_fast_age(struct dsa_switch *ds, int port) +{ + struct rtl838x_switch_priv *priv = ds->priv; + int s = priv->family_id == RTL8390_FAMILY_ID ? 2 : 0; + + pr_debug("FAST AGE port %d\n", port); + mutex_lock(&priv->reg_mutex); + /* RTL838X_L2_TBL_FLUSH_CTRL register bits, 839x has 1 bit larger + * port fields: + * 0-4: Replacing port + * 5-9: Flushed/replaced port + * 10-21: FVID + * 22: Entry types: 1: dynamic, 0: also static + * 23: Match flush port + * 24: Match FVID + * 25: Flush (0) or replace (1) L2 entries + * 26: Status of action (1: Start, 0: Done) + */ + sw_w32(1 << (26 + s) | 1 << (23 + s) | port << (5 + (s / 2)), priv->r->l2_tbl_flush_ctrl); + + do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & BIT(26 + s)); + + mutex_unlock(&priv->reg_mutex); +} + +void rtl930x_fast_age(struct dsa_switch *ds, int port) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + pr_debug("FAST AGE port %d\n", port); + mutex_lock(&priv->reg_mutex); + sw_w32(port << 11, RTL930X_L2_TBL_FLUSH_CTRL + 4); + + sw_w32(BIT(26) | BIT(30), RTL930X_L2_TBL_FLUSH_CTRL); + + do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & BIT(30)); + + mutex_unlock(&priv->reg_mutex); +} + +static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + pr_debug("%s: port %d\n", __func__, port); + mutex_lock(&priv->reg_mutex); + + if (vlan_filtering) { + /* Enable ingress and egress filtering + * The VLAN_PORT_IGR_FILTER register uses 2 bits for each port to define + * the filter action: + * 0: Always Forward + * 1: Drop packet + * 2: Trap packet to CPU port + * The Egress filter used 1 bit per state (0: DISABLED, 1: ENABLED) + */ + if (port != priv->cpu_port) + sw_w32_mask(0b10 << ((port % 16) << 1), 0b01 << ((port % 16) << 1), + priv->r->vlan_port_igr_filter + ((port >> 5) << 2)); + sw_w32_mask(0, BIT(port % 32), priv->r->vlan_port_egr_filter + ((port >> 4) << 2)); + } else { + /* Disable ingress and egress filtering */ + if (port != priv->cpu_port) + sw_w32_mask(0b11 << ((port % 16) << 1), 0, + priv->r->vlan_port_igr_filter + ((port >> 5) << 2)); + sw_w32_mask(BIT(port % 32), 0, priv->r->vlan_port_egr_filter + ((port >> 4) << 2)); + } + + /* Do we need to do something to the CPU-Port, too? */ + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int rtl83xx_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct rtl838x_vlan_info info; + struct rtl838x_switch_priv *priv = ds->priv; + + priv->r->vlan_tables_read(0, &info); + + pr_debug("VLAN 0: Tagged ports %llx, untag %llx, profile %d, MC# %d, UC# %d, FID %x\n", + info.tagged_ports, info.untagged_ports, info.profile_id, + info.hash_mc_fid, info.hash_uc_fid, info.fid); + + priv->r->vlan_tables_read(1, &info); + pr_debug("VLAN 1: Tagged ports %llx, untag %llx, profile %d, MC# %d, UC# %d, FID %x\n", + info.tagged_ports, info.untagged_ports, info.profile_id, + info.hash_mc_fid, info.hash_uc_fid, info.fid); + priv->r->vlan_set_untagged(1, info.untagged_ports); + pr_debug("SET: Untagged ports, VLAN %d: %llx\n", 1, info.untagged_ports); + + priv->r->vlan_set_tagged(1, &info); + pr_debug("SET: Tagged ports, VLAN %d: %llx\n", 1, info.tagged_ports); + + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static void rtl83xx_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct rtl838x_vlan_info info; + struct rtl838x_switch_priv *priv = ds->priv; + int v; + + pr_debug("%s port %d, vid_end %d, vid_end %d, flags %x\n", __func__, + port, vlan->vid_begin, vlan->vid_end, vlan->flags); + + if (vlan->vid_begin > 4095 || vlan->vid_end > 4095) { + dev_err(priv->dev, "VLAN out of range: %d - %d", + vlan->vid_begin, vlan->vid_end); + return; + } + + mutex_lock(&priv->reg_mutex); + + if (vlan->flags & BRIDGE_VLAN_INFO_PVID) { + for (v = vlan->vid_begin; v <= vlan->vid_end; v++) { + if (!v) + continue; + /* Set both inner and outer PVID of the port */ + sw_w32((v << 16) | v << 2, priv->r->vlan_port_pb + (port << 2)); + priv->ports[port].pvid = vlan->vid_end; + } + } + + for (v = vlan->vid_begin; v <= vlan->vid_end; v++) { + /* Get port memberships of this vlan */ + priv->r->vlan_tables_read(v, &info); + + /* new VLAN? */ + if (!info.tagged_ports) { + info.fid = 0; + info.hash_mc_fid = false; + info.hash_uc_fid = false; + info.profile_id = 0; + } + + /* sanitize untagged_ports - must be a subset */ + if (info.untagged_ports & ~info.tagged_ports) + info.untagged_ports = 0; + + info.tagged_ports |= BIT_ULL(port); + if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED) + info.untagged_ports |= BIT_ULL(port); + + priv->r->vlan_set_untagged(v, info.untagged_ports); + pr_debug("Untagged ports, VLAN %d: %llx\n", v, info.untagged_ports); + + priv->r->vlan_set_tagged(v, &info); + pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports); + } + + mutex_unlock(&priv->reg_mutex); +} + +static int rtl83xx_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct rtl838x_vlan_info info; + struct rtl838x_switch_priv *priv = ds->priv; + int v; + u16 pvid; + + pr_debug("%s: port %d, vid_end %d, vid_end %d, flags %x\n", __func__, + port, vlan->vid_begin, vlan->vid_end, vlan->flags); + + if (vlan->vid_begin > 4095 || vlan->vid_end > 4095) { + dev_err(priv->dev, "VLAN out of range: %d - %d", + vlan->vid_begin, vlan->vid_end); + return -ENOTSUPP; + } + + mutex_lock(&priv->reg_mutex); + pvid = priv->ports[port].pvid; + + for (v = vlan->vid_begin; v <= vlan->vid_end; v++) { + /* Reset to default if removing the current PVID */ + if (v == pvid) + sw_w32(0, priv->r->vlan_port_pb + (port << 2)); + + /* Get port memberships of this vlan */ + priv->r->vlan_tables_read(v, &info); + + /* remove port from both tables */ + info.untagged_ports &= (~BIT_ULL(port)); + info.tagged_ports &= (~BIT_ULL(port)); + + priv->r->vlan_set_untagged(v, info.untagged_ports); + pr_debug("Untagged ports, VLAN %d: %llx\n", v, info.untagged_ports); + + priv->r->vlan_set_tagged(v, &info); + pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports); + } + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static void dump_l2_entry(struct rtl838x_l2_entry *e) +{ + pr_info("MAC: %02x:%02x:%02x:%02x:%02x:%02x vid: %d, rvid: %d, port: %d, valid: %d\n", + e->mac[0], e->mac[1], e->mac[2], e->mac[3], e->mac[4], e->mac[5], + e->vid, e->rvid, e->port, e->valid); + + if (e->type != L2_MULTICAST) { + pr_info("Type: %d, is_static: %d, is_ip_mc: %d, is_ipv6_mc: %d, block_da: %d\n", + e->type, e->is_static, e->is_ip_mc, e->is_ipv6_mc, e->block_da); + pr_info(" block_sa: %d, susp: %d, nh: %d, age: %d, is_trunk: %d, trunk: %d\n", + e->block_sa, e->suspended, e->next_hop, e->age, e->is_trunk, e->trunk); + } + if (e->type == L2_MULTICAST) + pr_info(" L2_MULTICAST mc_portmask_index: %d\n", e->mc_portmask_index); + if (e->is_ip_mc || e->is_ipv6_mc) + pr_info(" mc_portmask_index: %d, mc_gip: %d, mc_sip: %d\n", + e->mc_portmask_index, e->mc_gip, e->mc_sip); + pr_info(" stack_dev: %d\n", e->stack_dev); + if (e->next_hop) + pr_info(" nh_route_id: %d\n", e->nh_route_id); +} + +static void rtl83xx_setup_l2_uc_entry(struct rtl838x_l2_entry *e, int port, int vid, u64 mac) +{ + e->is_ip_mc = e->is_ipv6_mc = false; + e->valid = true; + e->age = 3; + e->port = port, + e->vid = vid; + u64_to_ether_addr(mac, e->mac); +} + +static void rtl83xx_setup_l2_mc_entry(struct rtl838x_switch_priv *priv, + struct rtl838x_l2_entry *e, int vid, u64 mac, int mc_group) +{ + e->is_ip_mc = e->is_ipv6_mc = false; + e->valid = true; + e->mc_portmask_index = mc_group; + e->type = L2_MULTICAST; + e->rvid = e->vid = vid; + pr_debug("%s: vid: %d, rvid: %d\n", __func__, e->vid, e->rvid); + u64_to_ether_addr(mac, e->mac); +} + +/* + * Uses the seed to identify a hash bucket in the L2 using the derived hash key and then loops + * over the entries in the bucket until either a matching entry is found or an empty slot + * Returns the filled in rtl838x_l2_entry and the index in the bucket when an entry was found + * when an empty slot was found and must exist is false, the index of the slot is returned + * when no slots are available returns -1 + */ +static int rtl83xx_find_l2_hash_entry(struct rtl838x_switch_priv *priv, u64 seed, + bool must_exist, struct rtl838x_l2_entry *e) +{ + int i, idx = -1; + u32 key = priv->r->l2_hash_key(priv, seed); + u64 entry; + + pr_debug("%s: using key %x, for seed %016llx\n", __func__, key, seed); + // Loop over all entries in the hash-bucket and over the second block on 93xx SoCs + for (i = 0; i < priv->l2_bucket_size; i++) { + entry = priv->r->read_l2_entry_using_hash(key, i, e); + pr_debug("valid %d, mac %016llx\n", e->valid, ether_addr_to_u64(&e->mac[0])); + if (must_exist && !e->valid) + continue; + if (!e->valid || ((entry & 0x0fffffffffffffffULL) == seed)) { + idx = i > 3 ? ((key >> 14) & 0xffff) | i >> 1 : ((key << 2) | i) & 0xffff; + break; + } + } + + return idx; +} + +/* + * Uses the seed to identify an entry in the CAM by looping over all its entries + * Returns the filled in rtl838x_l2_entry and the index in the CAM when an entry was found + * when an empty slot was found the index of the slot is returned + * when no slots are available returns -1 + */ +static int rtl83xx_find_l2_cam_entry(struct rtl838x_switch_priv *priv, u64 seed, + bool must_exist, struct rtl838x_l2_entry *e) +{ + int i, idx = -1; + u64 entry; + + for (i = 0; i < 64; i++) { + entry = priv->r->read_cam(i, e); + if (!must_exist && !e->valid) { + if (idx < 0) /* First empty entry? */ + idx = i; + break; + } else if ((entry & 0x0fffffffffffffffULL) == seed) { + pr_debug("Found entry in CAM\n"); + idx = i; + break; + } + } + return idx; +} + +static int rtl83xx_port_fdb_add(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 mac = ether_addr_to_u64(addr); + struct rtl838x_l2_entry e; + int err = 0, idx; + u64 seed = priv->r->l2_hash_seed(mac, vid); + + mutex_lock(&priv->reg_mutex); + + idx = rtl83xx_find_l2_hash_entry(priv, seed, false, &e); + + // Found an existing or empty entry + if (idx >= 0) { + rtl83xx_setup_l2_uc_entry(&e, port, vid, mac); + priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); + goto out; + } + + // Hash buckets full, try CAM + rtl83xx_find_l2_cam_entry(priv, seed, false, &e); + + if (idx >= 0) { + rtl83xx_setup_l2_uc_entry(&e, port, vid, mac); + priv->r->write_cam(idx, &e); + goto out; + } + + err = -ENOTSUPP; +out: + mutex_unlock(&priv->reg_mutex); + return err; +} + +static int rtl83xx_port_fdb_del(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 mac = ether_addr_to_u64(addr); + struct rtl838x_l2_entry e; + int err = 0, idx; + u64 seed = priv->r->l2_hash_seed(mac, vid); + + pr_info("In %s, mac %llx, vid: %d\n", __func__, mac, vid); + mutex_lock(&priv->reg_mutex); + + idx = rtl83xx_find_l2_hash_entry(priv, seed, true, &e); + + pr_info("Found entry index %d, key %d and bucket %d\n", idx, idx >> 2, idx & 3); + if (idx >= 0) { + e.valid = false; + dump_l2_entry(&e); + priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); + goto out; + } + + /* Check CAM for spillover from hash buckets */ + rtl83xx_find_l2_cam_entry(priv, seed, true, &e); + + if (idx >= 0) { + e.valid = false; + priv->r->write_cam(idx, &e); + goto out; + } + err = -ENOENT; +out: + mutex_unlock(&priv->reg_mutex); + return err; +} + +static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port, + dsa_fdb_dump_cb_t *cb, void *data) +{ + struct rtl838x_l2_entry e; + struct rtl838x_switch_priv *priv = ds->priv; + int i; + u32 fid, pkey; + u64 mac; + + mutex_lock(&priv->reg_mutex); + + for (i = 0; i < priv->fib_entries; i++) { + priv->r->read_l2_entry_using_hash(i >> 2, i & 0x3, &e); + + if (!e.valid) + continue; + + if (e.port == port) { + fid = ((i >> 2) & 0x3ff) | (e.rvid & ~0x3ff); + mac = ether_addr_to_u64(&e.mac[0]); + pkey = priv->r->l2_hash_key(priv, priv->r->l2_hash_seed(mac, fid)); + fid = (pkey & 0x3ff) | (fid & ~0x3ff); + pr_info("-> index %d, key %x, bucket %d, dmac %016llx, fid: %x rvid: %x\n", + i, i >> 2, i & 0x3, mac, fid, e.rvid); + dump_l2_entry(&e); + u64 seed = priv->r->l2_hash_seed(mac, e.rvid); + u32 key = priv->r->l2_hash_key(priv, seed); + pr_info("seed: %016llx, key based on rvid: %08x\n", seed, key); + cb(e.mac, e.vid, e.is_static, data); + } + if (e.type == L2_MULTICAST) { + u64 portmask = priv->r->read_mcast_pmask(e.mc_portmask_index); + if (portmask & BIT_ULL(port)) { + dump_l2_entry(&e); + pr_info(" PM: %016llx\n", portmask); + } + } + } + + for (i = 0; i < 64; i++) { + priv->r->read_cam(i, &e); + + if (!e.valid) + continue; + + if (e.port == port) + cb(e.mac, e.vid, e.is_static, data); + } + + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int rtl83xx_port_mdb_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + if (priv->id >= 0x9300) + return -EOPNOTSUPP; + + return 0; +} + +static int rtl83xx_mc_group_alloc(struct rtl838x_switch_priv *priv, int port) +{ + int mc_group = find_first_zero_bit(priv->mc_group_bm, MAX_MC_GROUPS - 1); + u64 portmask; + + if (mc_group >= MAX_MC_GROUPS - 1) + return -1; + + pr_debug("Using MC group %d\n", mc_group); + set_bit(mc_group, priv->mc_group_bm); + mc_group++; // We cannot use group 0, as this is used for lookup miss flooding + portmask = BIT_ULL(port); + priv->r->write_mcast_pmask(mc_group, portmask); + + return mc_group; +} + +static u64 rtl83xx_mc_group_add_port(struct rtl838x_switch_priv *priv, int mc_group, int port) +{ + u64 portmask = priv->r->read_mcast_pmask(mc_group); + + portmask |= BIT_ULL(port); + priv->r->write_mcast_pmask(mc_group, portmask); + + return portmask; +} + +static u64 rtl83xx_mc_group_del_port(struct rtl838x_switch_priv *priv, int mc_group, int port) +{ + u64 portmask = priv->r->read_mcast_pmask(mc_group); + + portmask &= ~BIT_ULL(port); + priv->r->write_mcast_pmask(mc_group, portmask); + if (!portmask) + clear_bit(mc_group, priv->mc_group_bm); + + return portmask; +} + +static void rtl83xx_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 mac = ether_addr_to_u64(mdb->addr); + struct rtl838x_l2_entry e; + int err = 0, idx; + int vid = mdb->vid; + u64 seed = priv->r->l2_hash_seed(mac, vid); + int mc_group; + + pr_debug("In %s port %d, mac %llx, vid: %d\n", __func__, port, mac, vid); + mutex_lock(&priv->reg_mutex); + + idx = rtl83xx_find_l2_hash_entry(priv, seed, false, &e); + + // Found an existing or empty entry + if (idx >= 0) { + if (e.valid) { + pr_debug("Found an existing entry %016llx, mc_group %d\n", + ether_addr_to_u64(e.mac), e.mc_portmask_index); + rtl83xx_mc_group_add_port(priv, e.mc_portmask_index, port); + } else { + pr_debug("New entry for seed %016llx\n", seed); + mc_group = rtl83xx_mc_group_alloc(priv, port); + if (mc_group < 0) { + err = -ENOTSUPP; + goto out; + } + rtl83xx_setup_l2_mc_entry(priv, &e, vid, mac, mc_group); + priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); + } + goto out; + } + + // Hash buckets full, try CAM + rtl83xx_find_l2_cam_entry(priv, seed, false, &e); + + if (idx >= 0) { + if (e.valid) { + pr_debug("Found existing CAM entry %016llx, mc_group %d\n", + ether_addr_to_u64(e.mac), e.mc_portmask_index); + rtl83xx_mc_group_add_port(priv, e.mc_portmask_index, port); + } else { + pr_debug("New entry\n"); + mc_group = rtl83xx_mc_group_alloc(priv, port); + if (mc_group < 0) { + err = -ENOTSUPP; + goto out; + } + rtl83xx_setup_l2_mc_entry(priv, &e, vid, mac, mc_group); + priv->r->write_cam(idx, &e); + } + goto out; + } + + err = -ENOTSUPP; +out: + mutex_unlock(&priv->reg_mutex); + if (err) + dev_err(ds->dev, "failed to add MDB entry\n"); +} + +int rtl83xx_port_mdb_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 mac = ether_addr_to_u64(mdb->addr); + struct rtl838x_l2_entry e; + int err = 0, idx; + int vid = mdb->vid; + u64 seed = priv->r->l2_hash_seed(mac, vid); + u64 portmask; + + pr_debug("In %s, port %d, mac %llx, vid: %d\n", __func__, port, mac, vid); + mutex_lock(&priv->reg_mutex); + + idx = rtl83xx_find_l2_hash_entry(priv, seed, true, &e); + + pr_debug("Found entry index %d, key %d and bucket %d\n", idx, idx >> 2, idx & 3); + if (idx >= 0) { + portmask = rtl83xx_mc_group_del_port(priv, e.mc_portmask_index, port); + if (!portmask) { + e.valid = false; + // dump_l2_entry(&e); + priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); + } + goto out; + } + + /* Check CAM for spillover from hash buckets */ + rtl83xx_find_l2_cam_entry(priv, seed, true, &e); + + if (idx >= 0) { + portmask = rtl83xx_mc_group_del_port(priv, e.mc_portmask_index, port); + if (!portmask) { + e.valid = false; + // dump_l2_entry(&e); + priv->r->write_cam(idx, &e); + } + goto out; + } + // TODO: Re-enable with a newer kernel: err = -ENOENT; +out: + mutex_unlock(&priv->reg_mutex); + return err; +} + +static int rtl83xx_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) +{ + /* We support 4 mirror groups, one destination port per group */ + int group; + struct rtl838x_switch_priv *priv = ds->priv; + int ctrl_reg, dpm_reg, spm_reg; + + pr_debug("In %s\n", __func__); + + for (group = 0; group < 4; group++) { + if (priv->mirror_group_ports[group] == mirror->to_local_port) + break; + } + if (group >= 4) { + for (group = 0; group < 4; group++) { + if (priv->mirror_group_ports[group] < 0) + break; + } + } + + if (group >= 4) + return -ENOSPC; + + ctrl_reg = priv->r->mir_ctrl + group * 4; + dpm_reg = priv->r->mir_dpm + group * 4 * priv->port_width; + spm_reg = priv->r->mir_spm + group * 4 * priv->port_width; + + pr_debug("Using group %d\n", group); + mutex_lock(&priv->reg_mutex); + + if (priv->family_id == RTL8380_FAMILY_ID) { + /* Enable mirroring to port across VLANs (bit 11) */ + sw_w32(1 << 11 | (mirror->to_local_port << 4) | 1, ctrl_reg); + } else { + /* Enable mirroring to destination port */ + sw_w32((mirror->to_local_port << 4) | 1, ctrl_reg); + } + + if (ingress && (priv->r->get_port_reg_be(spm_reg) & (1ULL << port))) { + mutex_unlock(&priv->reg_mutex); + return -EEXIST; + } + if ((!ingress) && (priv->r->get_port_reg_be(dpm_reg) & (1ULL << port))) { + mutex_unlock(&priv->reg_mutex); + return -EEXIST; + } + + if (ingress) + priv->r->mask_port_reg_be(0, 1ULL << port, spm_reg); + else + priv->r->mask_port_reg_be(0, 1ULL << port, dpm_reg); + + priv->mirror_group_ports[group] = mirror->to_local_port; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static void rtl83xx_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + int group = 0; + struct rtl838x_switch_priv *priv = ds->priv; + int ctrl_reg, dpm_reg, spm_reg; + + pr_debug("In %s\n", __func__); + for (group = 0; group < 4; group++) { + if (priv->mirror_group_ports[group] == mirror->to_local_port) + break; + } + if (group >= 4) + return; + + ctrl_reg = priv->r->mir_ctrl + group * 4; + dpm_reg = priv->r->mir_dpm + group * 4 * priv->port_width; + spm_reg = priv->r->mir_spm + group * 4 * priv->port_width; + + mutex_lock(&priv->reg_mutex); + if (mirror->ingress) { + /* Ingress, clear source port matrix */ + priv->r->mask_port_reg_be(1ULL << port, 0, spm_reg); + } else { + /* Egress, clear destination port matrix */ + priv->r->mask_port_reg_be(1ULL << port, 0, dpm_reg); + } + + if (!(sw_r32(spm_reg) || sw_r32(dpm_reg))) { + priv->mirror_group_ports[group] = -1; + sw_w32(0, ctrl_reg); + } + + mutex_unlock(&priv->reg_mutex); +} + +int dsa_phy_read(struct dsa_switch *ds, int phy_addr, int phy_reg) +{ + u32 val; + u32 offset = 0; + struct rtl838x_switch_priv *priv = ds->priv; + + if (phy_addr >= 24 && phy_addr <= 27 + && priv->ports[24].phy == PHY_RTL838X_SDS) { + if (phy_addr == 26) + offset = 0x100; + val = sw_r32(RTL838X_SDS4_FIB_REG0 + offset + (phy_reg << 2)) & 0xffff; + return val; + } + + read_phy(phy_addr, 0, phy_reg, &val); + return val; +} + +int dsa_phy_write(struct dsa_switch *ds, int phy_addr, int phy_reg, u16 val) +{ + u32 offset = 0; + struct rtl838x_switch_priv *priv = ds->priv; + + if (phy_addr >= 24 && phy_addr <= 27 + && priv->ports[24].phy == PHY_RTL838X_SDS) { + if (phy_addr == 26) + offset = 0x100; + sw_w32(val, RTL838X_SDS4_FIB_REG0 + offset + (phy_reg << 2)); + return 0; + } + return write_phy(phy_addr, 0, phy_reg, val); +} + +const struct dsa_switch_ops rtl83xx_switch_ops = { + .get_tag_protocol = rtl83xx_get_tag_protocol, + .setup = rtl83xx_setup, + + .phy_read = dsa_phy_read, + .phy_write = dsa_phy_write, + + .phylink_validate = rtl83xx_phylink_validate, + .phylink_mac_link_state = rtl83xx_phylink_mac_link_state, + .phylink_mac_config = rtl83xx_phylink_mac_config, + .phylink_mac_link_down = rtl83xx_phylink_mac_link_down, + .phylink_mac_link_up = rtl83xx_phylink_mac_link_up, + + .get_strings = rtl83xx_get_strings, + .get_ethtool_stats = rtl83xx_get_ethtool_stats, + .get_sset_count = rtl83xx_get_sset_count, + + .port_enable = rtl83xx_port_enable, + .port_disable = rtl83xx_port_disable, + + .get_mac_eee = rtl83xx_get_mac_eee, + .set_mac_eee = rtl83xx_set_mac_eee, + + .set_ageing_time = rtl83xx_set_l2aging, + .port_bridge_join = rtl83xx_port_bridge_join, + .port_bridge_leave = rtl83xx_port_bridge_leave, + .port_stp_state_set = rtl83xx_port_stp_state_set, + .port_fast_age = rtl83xx_fast_age, + + .port_vlan_filtering = rtl83xx_vlan_filtering, + .port_vlan_prepare = rtl83xx_vlan_prepare, + .port_vlan_add = rtl83xx_vlan_add, + .port_vlan_del = rtl83xx_vlan_del, + + .port_fdb_add = rtl83xx_port_fdb_add, + .port_fdb_del = rtl83xx_port_fdb_del, + .port_fdb_dump = rtl83xx_port_fdb_dump, + + .port_mdb_prepare = rtl83xx_port_mdb_prepare, + .port_mdb_add = rtl83xx_port_mdb_add, + .port_mdb_del = rtl83xx_port_mdb_del, + + .port_mirror_add = rtl83xx_port_mirror_add, + .port_mirror_del = rtl83xx_port_mirror_del, +}; + +const struct dsa_switch_ops rtl930x_switch_ops = { + .get_tag_protocol = rtl83xx_get_tag_protocol, + .setup = rtl930x_setup, + + .phy_read = dsa_phy_read, + .phy_write = dsa_phy_write, + + .phylink_validate = rtl83xx_phylink_validate, + .phylink_mac_link_state = rtl83xx_phylink_mac_link_state, + .phylink_mac_config = rtl83xx_phylink_mac_config, + .phylink_mac_link_down = rtl83xx_phylink_mac_link_down, + .phylink_mac_link_up = rtl83xx_phylink_mac_link_up, + + .get_strings = rtl83xx_get_strings, + .get_ethtool_stats = rtl83xx_get_ethtool_stats, + .get_sset_count = rtl83xx_get_sset_count, + + .port_enable = rtl83xx_port_enable, + .port_disable = rtl83xx_port_disable, + + .get_mac_eee = rtl93xx_get_mac_eee, + .set_mac_eee = rtl83xx_set_mac_eee, + + .set_ageing_time = rtl83xx_set_l2aging, + .port_bridge_join = rtl83xx_port_bridge_join, + .port_bridge_leave = rtl83xx_port_bridge_leave, + .port_stp_state_set = rtl83xx_port_stp_state_set, + .port_fast_age = rtl930x_fast_age, + + .port_vlan_filtering = rtl83xx_vlan_filtering, + .port_vlan_prepare = rtl83xx_vlan_prepare, + .port_vlan_add = rtl83xx_vlan_add, + .port_vlan_del = rtl83xx_vlan_del, + + .port_fdb_add = rtl83xx_port_fdb_add, + .port_fdb_del = rtl83xx_port_fdb_del, + .port_fdb_dump = rtl83xx_port_fdb_dump, + + .port_mdb_prepare = rtl83xx_port_mdb_prepare, + .port_mdb_add = rtl83xx_port_mdb_add, + .port_mdb_del = rtl83xx_port_mdb_del, + +}; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/qos.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/qos.c new file mode 100644 index 0000000000..2fc8d37f3e --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/qos.c @@ -0,0 +1,576 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include +#include "rtl83xx.h" + +static struct rtl838x_switch_priv *switch_priv; +extern struct rtl83xx_soc_info soc_info; + +enum scheduler_type { + WEIGHTED_FAIR_QUEUE = 0, + WEIGHTED_ROUND_ROBIN, +}; + +int max_available_queue[] = {0, 1, 2, 3, 4, 5, 6, 7}; +int default_queue_weights[] = {1, 1, 1, 1, 1, 1, 1, 1}; +int dot1p_priority_remapping[] = {0, 1, 2, 3, 4, 5, 6, 7}; + +static void rtl839x_read_scheduling_table(int port) +{ + u32 cmd = 1 << 9 /* Execute cmd */ + | 0 << 8 /* Read */ + | 0 << 6 /* Table type 0b00 */ + | (port & 0x3f); + rtl839x_exec_tbl2_cmd(cmd); +} + +static void rtl839x_write_scheduling_table(int port) +{ + u32 cmd = 1 << 9 /* Execute cmd */ + | 1 << 8 /* Write */ + | 0 << 6 /* Table type 0b00 */ + | (port & 0x3f); + rtl839x_exec_tbl2_cmd(cmd); +} + +static void rtl839x_read_out_q_table(int port) +{ + u32 cmd = 1 << 9 /* Execute cmd */ + | 0 << 8 /* Read */ + | 2 << 6 /* Table type 0b10 */ + | (port & 0x3f); + rtl839x_exec_tbl2_cmd(cmd); +} + +static void rtl838x_storm_enable(struct rtl838x_switch_priv *priv, int port, bool enable) +{ + // Enable Storm control for that port for UC, MC, and BC + if (enable) + sw_w32(0x7, RTL838X_STORM_CTRL_LB_CTRL(port)); + else + sw_w32(0x0, RTL838X_STORM_CTRL_LB_CTRL(port)); +} + +u32 rtl838x_get_egress_rate(struct rtl838x_switch_priv *priv, int port) +{ + u32 rate; + + if (port > priv->cpu_port) + return 0; + rate = sw_r32(RTL838X_SCHED_P_EGR_RATE_CTRL(port)) & 0x3fff; + return rate; +} + +/* Sets the rate limit, 10MBit/s is equal to a rate value of 625 */ +int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate) +{ + u32 old_rate; + + if (port > priv->cpu_port) + return -1; + + old_rate = sw_r32(RTL838X_SCHED_P_EGR_RATE_CTRL(port)); + sw_w32(rate, RTL838X_SCHED_P_EGR_RATE_CTRL(port)); + + return old_rate; +} + +/* Set the rate limit for a particular queue in Bits/s + * units of the rate is 16Kbps + */ +void rtl838x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port, + int queue, u32 rate) +{ + if (port > priv->cpu_port) + return; + if (queue > 7) + return; + sw_w32(rate, RTL838X_SCHED_Q_EGR_RATE_CTRL(port, queue)); +} + +static void rtl838x_rate_control_init(struct rtl838x_switch_priv *priv) +{ + int i; + + pr_info("Enabling Storm control\n"); + // TICK_PERIOD_PPS + if (priv->id == 0x8380) + sw_w32_mask(0x3ff << 20, 434 << 20, RTL838X_SCHED_LB_TICK_TKN_CTRL_0); + + // Set burst rate + sw_w32(0x00008000, RTL838X_STORM_CTRL_BURST_0); // UC + sw_w32(0x80008000, RTL838X_STORM_CTRL_BURST_1); // MC and BC + + // Set burst Packets per Second to 32 + sw_w32(0x00000020, RTL838X_STORM_CTRL_BURST_PPS_0); // UC + sw_w32(0x00200020, RTL838X_STORM_CTRL_BURST_PPS_1); // MC and BC + + // Include IFG in storm control, rate based on bytes/s (0 = packets) + sw_w32_mask(0, 1 << 6 | 1 << 5, RTL838X_STORM_CTRL); + // Bandwidth control includes preamble and IFG (10 Bytes) + sw_w32_mask(0, 1, RTL838X_SCHED_CTRL); + + // On SoCs except RTL8382M, set burst size of port egress + if (priv->id != 0x8382) + sw_w32_mask(0xffff, 0x800, RTL838X_SCHED_LB_THR); + + /* Enable storm control on all ports with a PHY and limit rates, + * for UC and MC for both known and unknown addresses */ + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) { + sw_w32((1 << 18) | 0x8000, RTL838X_STORM_CTRL_PORT_UC(i)); + sw_w32((1 << 18) | 0x8000, RTL838X_STORM_CTRL_PORT_MC(i)); + sw_w32(0x8000, RTL838X_STORM_CTRL_PORT_BC(i)); + rtl838x_storm_enable(priv, i, true); + } + } + + // Attack prevention, enable all attack prevention measures + //sw_w32(0x1ffff, RTL838X_ATK_PRVNT_CTRL); + /* Attack prevention, drop (bit = 0) problematic packets on all ports. + * Setting bit = 1 means: trap to CPU + */ + //sw_w32(0, RTL838X_ATK_PRVNT_ACT); + // Enable attack prevention on all ports + //sw_w32(0x0fffffff, RTL838X_ATK_PRVNT_PORT_EN); +} + +/* Sets the rate limit, 10MBit/s is equal to a rate value of 625 */ +u32 rtl839x_get_egress_rate(struct rtl838x_switch_priv *priv, int port) +{ + u32 rate; + + pr_debug("%s: Getting egress rate on port %d to %d\n", __func__, port, rate); + if (port >= priv->cpu_port) + return 0; + + mutex_lock(&priv->reg_mutex); + + rtl839x_read_scheduling_table(port); + + rate = sw_r32(RTL839X_TBL_ACCESS_DATA_2(7)); + rate <<= 12; + rate |= sw_r32(RTL839X_TBL_ACCESS_DATA_2(8)) >> 20; + + mutex_unlock(&priv->reg_mutex); + + return rate; +} + +/* Sets the rate limit, 10MBit/s is equal to a rate value of 625, returns previous rate */ +int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate) +{ + u32 old_rate; + + pr_debug("%s: Setting egress rate on port %d to %d\n", __func__, port, rate); + if (port >= priv->cpu_port) + return -1; + + mutex_lock(&priv->reg_mutex); + + rtl839x_read_scheduling_table(port); + + old_rate = sw_r32(RTL839X_TBL_ACCESS_DATA_2(7)) & 0xff; + old_rate <<= 12; + old_rate |= sw_r32(RTL839X_TBL_ACCESS_DATA_2(8)) >> 20; + sw_w32_mask(0xff, (rate >> 12) & 0xff, RTL839X_TBL_ACCESS_DATA_2(7)); + sw_w32_mask(0xfff << 20, rate << 20, RTL839X_TBL_ACCESS_DATA_2(8)); + + rtl839x_write_scheduling_table(port); + + mutex_unlock(&priv->reg_mutex); + + return old_rate; +} + +/* Set the rate limit for a particular queue in Bits/s + * units of the rate is 16Kbps + */ +void rtl839x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port, + int queue, u32 rate) +{ + int lsb = 128 + queue * 20; + int low_byte = 8 - (lsb >> 5); + int start_bit = lsb - (low_byte << 5); + u32 high_mask = 0xfffff >> (32 - start_bit); + + pr_debug("%s: Setting egress rate on port %d, queue %d to %d\n", + __func__, port, queue, rate); + if (port >= priv->cpu_port) + return; + if (queue > 7) + return; + + mutex_lock(&priv->reg_mutex); + + rtl839x_read_scheduling_table(port); + + sw_w32_mask(0xfffff << start_bit, (rate & 0xfffff) << start_bit, + RTL839X_TBL_ACCESS_DATA_2(low_byte)); + if (high_mask) + sw_w32_mask(high_mask, (rate & 0xfffff) >> (32- start_bit), + RTL839X_TBL_ACCESS_DATA_2(low_byte - 1)); + + rtl839x_write_scheduling_table(port); + + mutex_unlock(&priv->reg_mutex); +} + +static void rtl839x_rate_control_init(struct rtl838x_switch_priv *priv) +{ + int p, q; + + pr_info("%s: enabling rate control\n", __func__); + /* Tick length and token size settings for SoC with 250MHz, + * RTL8350 family would use 50MHz + */ + // Set the special tick period + sw_w32(976563, RTL839X_STORM_CTRL_SPCL_LB_TICK_TKN_CTRL); + // Ingress tick period and token length 10G + sw_w32(18 << 11 | 151, RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_0); + // Ingress tick period and token length 1G + sw_w32(245 << 11 | 129, RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_1); + // Egress tick period 10G, bytes/token 10G and tick period 1G, bytes/token 1G + sw_w32(18 << 24 | 151 << 16 | 185 << 8 | 97, RTL839X_SCHED_LB_TICK_TKN_CTRL); + // Set the tick period of the CPU and the Token Len + sw_w32(3815 << 8 | 1, RTL839X_SCHED_LB_TICK_TKN_PPS_CTRL); + + // Set the Weighted Fair Queueing burst size + sw_w32_mask(0xffff, 4500, RTL839X_SCHED_LB_THR); + + // Storm-rate calculation is based on bytes/sec (bit 5), include IFG (bit 6) + sw_w32_mask(0, 1 << 5 | 1 << 6, RTL839X_STORM_CTRL); + + /* Based on the rate control mode being bytes/s + * set tick period and token length for 10G + */ + sw_w32(18 << 10 | 151, RTL839X_STORM_CTRL_LB_TICK_TKN_CTRL_0); + /* and for 1G ports */ + sw_w32(246 << 10 | 129, RTL839X_STORM_CTRL_LB_TICK_TKN_CTRL_1); + + /* Set default burst rates on all ports (the same for 1G / 10G) with a PHY + * for UC, MC and BC + * For 1G port, the minimum burst rate is 1700, maximum 65535, + * For 10G ports it is 2650 and 1048575 respectively */ + for (p = 0; p < priv->cpu_port; p++) { + if (priv->ports[p].phy && !priv->ports[p].is10G) { + sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_UC_1(p)); + sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_MC_1(p)); + sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_BC_1(p)); + } + } + + /* Setup ingress/egress per-port rate control */ + for (p = 0; p < priv->cpu_port; p++) { + if (!priv->ports[p].phy) + continue; + + if (priv->ports[p].is10G) + rtl839x_set_egress_rate(priv, p, 625000); // 10GB/s + else + rtl839x_set_egress_rate(priv, p, 62500); // 1GB/s + + // Setup queues: all RTL83XX SoCs have 8 queues, maximum rate + for (q = 0; q < 8; q++) + rtl839x_egress_rate_queue_limit(priv, p, q, 0xfffff); + + if (priv->ports[p].is10G) { + // Set high threshold to maximum + sw_w32_mask(0xffff, 0xffff, RTL839X_IGR_BWCTRL_PORT_CTRL_10G_0(p)); + } else { + // Set high threshold to maximum + sw_w32_mask(0xffff, 0xffff, RTL839X_IGR_BWCTRL_PORT_CTRL_1(p)); + } + } + + // Set global ingress low watermark rate + sw_w32(65532, RTL839X_IGR_BWCTRL_CTRL_LB_THR); +} + + + +void rtl838x_setup_prio2queue_matrix(int *min_queues) +{ + int i; + u32 v; + + pr_info("Current Intprio2queue setting: %08x\n", sw_r32(RTL838X_QM_INTPRI2QID_CTRL)); + for (i = 0; i < MAX_PRIOS; i++) + v |= i << (min_queues[i] * 3); + sw_w32(v, RTL838X_QM_INTPRI2QID_CTRL); +} + +void rtl839x_setup_prio2queue_matrix(int *min_queues) +{ + int i, q; + + pr_info("Current Intprio2queue setting: %08x\n", sw_r32(RTL839X_QM_INTPRI2QID_CTRL(0))); + for (i = 0; i < MAX_PRIOS; i++) { + q = min_queues[i]; + sw_w32(i << (q * 3), RTL839X_QM_INTPRI2QID_CTRL(q)); + } +} + +/* Sets the CPU queue depending on the internal priority of a packet */ +void rtl83xx_setup_prio2queue_cpu_matrix(int *max_queues) +{ + int reg = soc_info.family == RTL8380_FAMILY_ID ? RTL838X_QM_PKT2CPU_INTPRI_MAP + : RTL839X_QM_PKT2CPU_INTPRI_MAP; + int i; + u32 v; + + pr_info("QM_PKT2CPU_INTPRI_MAP: %08x\n", sw_r32(reg)); + for (i = 0; i < MAX_PRIOS; i++) + v |= max_queues[i] << (i * 3); + sw_w32(v, reg); +} + +void rtl83xx_setup_default_prio2queue(void) +{ + if (soc_info.family == RTL8380_FAMILY_ID) { + rtl838x_setup_prio2queue_matrix(max_available_queue); + } else { + rtl839x_setup_prio2queue_matrix(max_available_queue); + } + rtl83xx_setup_prio2queue_cpu_matrix(max_available_queue); +} + +/* Sets the output queue assigned to a port, the port can be the CPU-port */ +void rtl839x_set_egress_queue(int port, int queue) +{ + sw_w32(queue << ((port % 10) *3), RTL839X_QM_PORT_QNUM(port)); +} + +/* Sets the priority assigned of an ingress port, the port can be the CPU-port */ +void rtl83xx_set_ingress_priority(int port, int priority) +{ + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(priority << ((port % 10) *3), RTL838X_PRI_SEL_PORT_PRI(port)); + else + sw_w32(priority << ((port % 10) *3), RTL839X_PRI_SEL_PORT_PRI(port)); + +} + +int rtl839x_get_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port) +{ + u32 v; + + mutex_lock(&priv->reg_mutex); + + rtl839x_read_scheduling_table(port); + v = sw_r32(RTL839X_TBL_ACCESS_DATA_2(8)); + + mutex_unlock(&priv->reg_mutex); + + if (v & BIT(19)) + return WEIGHTED_ROUND_ROBIN; + return WEIGHTED_FAIR_QUEUE; +} + +void rtl839x_set_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port, + enum scheduler_type sched) +{ + enum scheduler_type t = rtl839x_get_scheduling_algorithm(priv, port); + u32 v, oam_state, oam_port_state; + u32 count; + int i, egress_rate; + + mutex_lock(&priv->reg_mutex); + /* Check whether we need to empty the egress queue of that port due to Errata E0014503 */ + if (sched == WEIGHTED_FAIR_QUEUE && t == WEIGHTED_ROUND_ROBIN && port != priv->cpu_port) { + // Read Operations, Adminstatrion and Management control register + oam_state = sw_r32(RTL839X_OAM_CTRL); + + // Get current OAM state + oam_port_state = sw_r32(RTL839X_OAM_PORT_ACT_CTRL(port)); + + // Disable OAM to block traffice + v = sw_r32(RTL839X_OAM_CTRL); + sw_w32_mask(0, 1, RTL839X_OAM_CTRL); + v = sw_r32(RTL839X_OAM_CTRL); + + // Set to trap action OAM forward (bits 1, 2) and OAM Mux Action Drop (bit 0) + sw_w32(0x2, RTL839X_OAM_PORT_ACT_CTRL(port)); + + // Set port egress rate to unlimited + egress_rate = rtl839x_set_egress_rate(priv, port, 0xFFFFF); + + // Wait until the egress used page count of that port is 0 + i = 0; + do { + usleep_range(100, 200); + rtl839x_read_out_q_table(port); + count = sw_r32(RTL839X_TBL_ACCESS_DATA_2(6)); + count >>= 20; + i++; + } while (i < 3500 && count > 0); + } + + // Actually set the scheduling algorithm + rtl839x_read_scheduling_table(port); + sw_w32_mask(BIT(19), sched ? BIT(19) : 0, RTL839X_TBL_ACCESS_DATA_2(8)); + rtl839x_write_scheduling_table(port); + + if (sched == WEIGHTED_FAIR_QUEUE && t == WEIGHTED_ROUND_ROBIN && port != priv->cpu_port) { + // Restore OAM state to control register + sw_w32(oam_state, RTL839X_OAM_CTRL); + + // Restore trap action state + sw_w32(oam_port_state, RTL839X_OAM_PORT_ACT_CTRL(port)); + + // Restore port egress rate + rtl839x_set_egress_rate(priv, port, egress_rate); + } + + mutex_unlock(&priv->reg_mutex); +} + +void rtl839x_set_scheduling_queue_weights(struct rtl838x_switch_priv *priv, int port, + int *queue_weights) +{ + int i, lsb, low_byte, start_bit, high_mask; + + mutex_lock(&priv->reg_mutex); + + rtl839x_read_scheduling_table(port); + + for (i = 0; i < 8; i++) { + lsb = 48 + i * 8; + low_byte = 8 - (lsb >> 5); + start_bit = lsb - (low_byte << 5); + high_mask = 0x3ff >> (32 - start_bit); + sw_w32_mask(0x3ff << start_bit, (queue_weights[i] & 0x3ff) << start_bit, + RTL839X_TBL_ACCESS_DATA_2(low_byte)); + if (high_mask) + sw_w32_mask(high_mask, (queue_weights[i] & 0x3ff) >> (32- start_bit), + RTL839X_TBL_ACCESS_DATA_2(low_byte - 1)); + } + + rtl839x_write_scheduling_table(port); + mutex_unlock(&priv->reg_mutex); +} + +void rtl838x_config_qos(void) +{ + int i, p; + u32 v; + + pr_info("Setting up RTL838X QoS\n"); + pr_info("RTL838X_PRI_SEL_TBL_CTRL(i): %08x\n", sw_r32(RTL838X_PRI_SEL_TBL_CTRL(0))); + rtl83xx_setup_default_prio2queue(); + + // Enable inner (bit 12) and outer (bit 13) priority remapping from DSCP + sw_w32_mask(0, BIT(12) | BIT(13), RTL838X_PRI_DSCP_INVLD_CTRL0); + + /* Set default weight for calculating internal priority, in prio selection group 0 + * Port based (prio 3), Port outer-tag (4), DSCP (5), Inner Tag (6), Outer Tag (7) + */ + v = 3 | (4 << 3) | (5 << 6) | (6 << 9) | (7 << 12); + sw_w32(v, RTL838X_PRI_SEL_TBL_CTRL(0)); + + // Set the inner and outer priority one-to-one to re-marked outer dot1p priority + v = 0; + for (p = 0; p < 8; p++) + v |= p << (3 * p); + sw_w32(v, RTL838X_RMK_OPRI_CTRL); + sw_w32(v, RTL838X_RMK_IPRI_CTRL); + + v = 0; + for (p = 0; p < 8; p++) + v |= (dot1p_priority_remapping[p] & 0x7) << (p * 3); + sw_w32(v, RTL838X_PRI_SEL_IPRI_REMAP); + + // On all ports set scheduler type to WFQ + for (i = 0; i <= soc_info.cpu_port; i++) + sw_w32(0, RTL838X_SCHED_P_TYPE_CTRL(i)); + + // Enable egress scheduler for CPU-Port + sw_w32_mask(0, BIT(8), RTL838X_SCHED_LB_CTRL(soc_info.cpu_port)); + + // Enable egress drop allways on + sw_w32_mask(0, BIT(11), RTL838X_FC_P_EGR_DROP_CTRL(soc_info.cpu_port)); + + // Give special trap frames priority 7 (BPDUs) and routing exceptions: + sw_w32_mask(0, 7 << 3 | 7, RTL838X_QM_PKT2CPU_INTPRI_2); + // Give RMA frames priority 7: + sw_w32_mask(0, 7, RTL838X_QM_PKT2CPU_INTPRI_1); +} + +void rtl839x_config_qos(void) +{ + int port, p, q; + u32 v; + struct rtl838x_switch_priv *priv = switch_priv; + + pr_info("Setting up RTL839X QoS\n"); + pr_info("RTL839X_PRI_SEL_TBL_CTRL(i): %08x\n", sw_r32(RTL839X_PRI_SEL_TBL_CTRL(0))); + rtl83xx_setup_default_prio2queue(); + + for (port = 0; port < soc_info.cpu_port; port++) + sw_w32(7, RTL839X_QM_PORT_QNUM(port)); + + // CPU-port gets queue number 7 + sw_w32(7, RTL839X_QM_PORT_QNUM(soc_info.cpu_port)); + + for (port = 0; port <= soc_info.cpu_port; port++) { + rtl83xx_set_ingress_priority(port, 0); + rtl839x_set_scheduling_algorithm(priv, port, WEIGHTED_FAIR_QUEUE); + rtl839x_set_scheduling_queue_weights(priv, port, default_queue_weights); + // Do re-marking based on outer tag + sw_w32_mask(0, BIT(port % 32), RTL839X_RMK_PORT_DEI_TAG_CTRL(port)); + } + + // Remap dot1p priorities to internal priority, for this the outer tag needs be re-marked + v = 0; + for (p = 0; p < 8; p++) + v |= (dot1p_priority_remapping[p] & 0x7) << (p * 3); + sw_w32(v, RTL839X_PRI_SEL_IPRI_REMAP); + + /* Configure Drop Precedence for Drop Eligible Indicator (DEI) + * Index 0: 0 + * Index 1: 2 + * Each indicator is 2 bits long + */ + sw_w32(2 << 2, RTL839X_PRI_SEL_DEI2DP_REMAP); + + // Re-mark DEI: 4 bit-fields of 2 bits each, field 0 is bits 0-1, ... + sw_w32((0x1 << 2) | (0x1 << 4), RTL839X_RMK_DEI_CTRL); + + /* Set Congestion avoidance drop probability to 0 for drop precedences 0-2 (bits 24-31) + * low threshold (bits 0-11) to 4095 and high threshold (bits 12-23) to 4095 + * Weighted Random Early Detection (WRED) is used + */ + sw_w32(4095 << 12| 4095, RTL839X_WRED_PORT_THR_CTRL(0)); + sw_w32(4095 << 12| 4095, RTL839X_WRED_PORT_THR_CTRL(1)); + sw_w32(4095 << 12| 4095, RTL839X_WRED_PORT_THR_CTRL(2)); + + /* Set queue-based congestion avoidance properties, register fields are as + * for forward RTL839X_WRED_PORT_THR_CTRL + */ + for (q = 0; q < 8; q++) { + sw_w32(255 << 24 | 78 << 12 | 68, RTL839X_WRED_QUEUE_THR_CTRL(q, 0)); + sw_w32(255 << 24 | 74 << 12 | 64, RTL839X_WRED_QUEUE_THR_CTRL(q, 0)); + sw_w32(255 << 24 | 70 << 12 | 60, RTL839X_WRED_QUEUE_THR_CTRL(q, 0)); + } +} + +void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv) +{ + switch_priv = priv; + + pr_info("In %s\n", __func__); + + if (priv->family_id == RTL8380_FAMILY_ID) + return rtl838x_config_qos(); + else if (priv->family_id == RTL8390_FAMILY_ID) + return rtl839x_config_qos(); + + if (priv->family_id == RTL8380_FAMILY_ID) + rtl838x_rate_control_init(priv); + else if (priv->family_id == RTL8390_FAMILY_ID) + rtl839x_rate_control_init(priv); + +} diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c new file mode 100644 index 0000000000..5d764b6a32 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c @@ -0,0 +1,859 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "rtl83xx.h" + +extern struct mutex smi_lock; + +void rtl838x_print_matrix(void) +{ + unsigned volatile int *ptr8; + int i; + + ptr8 = RTL838X_SW_BASE + RTL838X_PORT_ISO_CTRL(0); + for (i = 0; i < 28; i += 8) + pr_debug("> %8x %8x %8x %8x %8x %8x %8x %8x\n", + ptr8[i + 0], ptr8[i + 1], ptr8[i + 2], ptr8[i + 3], + ptr8[i + 4], ptr8[i + 5], ptr8[i + 6], ptr8[i + 7]); + pr_debug("CPU_PORT> %8x\n", ptr8[28]); +} + +static inline int rtl838x_port_iso_ctrl(int p) +{ + return RTL838X_PORT_ISO_CTRL(p); +} + +static inline void rtl838x_exec_tbl0_cmd(u32 cmd) +{ + sw_w32(cmd, RTL838X_TBL_ACCESS_CTRL_0); + do { } while (sw_r32(RTL838X_TBL_ACCESS_CTRL_0) & BIT(15)); +} + +static inline void rtl838x_exec_tbl1_cmd(u32 cmd) +{ + sw_w32(cmd, RTL838X_TBL_ACCESS_CTRL_1); + do { } while (sw_r32(RTL838X_TBL_ACCESS_CTRL_1) & BIT(15)); +} + +static inline int rtl838x_tbl_access_data_0(int i) +{ + return RTL838X_TBL_ACCESS_DATA_0(i); +} + +static void rtl838x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 v; + // Read VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 0); + + rtl_table_read(r, vlan); + info->tagged_ports = sw_r32(rtl_table_data(r, 0)); + v = sw_r32(rtl_table_data(r, 1)); + pr_debug("VLAN_READ %d: %016llx %08x\n", vlan, info->tagged_ports, v); + rtl_table_release(r); + + info->profile_id = v & 0x7; + info->hash_mc_fid = !!(v & 0x8); + info->hash_uc_fid = !!(v & 0x10); + info->fid = (v >> 5) & 0x3f; + + // Read UNTAG table (0) via table register 1 + r = rtl_table_get(RTL8380_TBL_1, 0); + rtl_table_read(r, vlan); + info->untagged_ports = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); +} + +static void rtl838x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 v; + // Access VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 0); + + sw_w32(info->tagged_ports, rtl_table_data(r, 0)); + + v = info->profile_id; + v |= info->hash_mc_fid ? 0x8 : 0; + v |= info->hash_uc_fid ? 0x10 : 0; + v |= ((u32)info->fid) << 5; + sw_w32(v, rtl_table_data(r, 1)); + + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +static void rtl838x_vlan_set_untagged(u32 vlan, u64 portmask) +{ + // Access UNTAG table (0) via register 1 + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 0); + + sw_w32(portmask & 0x1fffffff, rtl_table_data(r, 0)); + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +/* Sets the L2 forwarding to be based on either the inner VLAN tag or the outer + */ +static void rtl838x_vlan_fwd_on_inner(int port, bool is_set) +{ + if (is_set) + sw_w32_mask(BIT(port), 0, RTL838X_VLAN_PORT_FWD); + else + sw_w32_mask(0, BIT(port), RTL838X_VLAN_PORT_FWD); +} + +static u64 rtl838x_l2_hash_seed(u64 mac, u32 vid) +{ + return mac << 12 | vid; +} + +/* + * Applies the same hash algorithm as the one used currently by the ASIC to the seed + * and returns a key into the L2 hash table + */ +static u32 rtl838x_l2_hash_key(struct rtl838x_switch_priv *priv, u64 seed) +{ + u32 h1, h2, h3, h; + + if (sw_r32(priv->r->l2_ctrl_0) & 1) { + h1 = (seed >> 11) & 0x7ff; + h1 = ((h1 & 0x1f) << 6) | ((h1 >> 5) & 0x3f); + + h2 = (seed >> 33) & 0x7ff; + h2 = ((h2 & 0x3f) << 5) | ((h2 >> 6) & 0x1f); + + h3 = (seed >> 44) & 0x7ff; + h3 = ((h3 & 0x7f) << 4) | ((h3 >> 7) & 0xf); + + h = h1 ^ h2 ^ h3 ^ ((seed >> 55) & 0x1ff); + h ^= ((seed >> 22) & 0x7ff) ^ (seed & 0x7ff); + } else { + h = ((seed >> 55) & 0x1ff) ^ ((seed >> 44) & 0x7ff) + ^ ((seed >> 33) & 0x7ff) ^ ((seed >> 22) & 0x7ff) + ^ ((seed >> 11) & 0x7ff) ^ (seed & 0x7ff); + } + + return h; +} + +static inline int rtl838x_mac_force_mode_ctrl(int p) +{ + return RTL838X_MAC_FORCE_MODE_CTRL + (p << 2); +} + +static inline int rtl838x_mac_port_ctrl(int p) +{ + return RTL838X_MAC_PORT_CTRL(p); +} + +static inline int rtl838x_l2_port_new_salrn(int p) +{ + return RTL838X_L2_PORT_NEW_SALRN(p); +} + +static inline int rtl838x_l2_port_new_sa_fwd(int p) +{ + return RTL838X_L2_PORT_NEW_SA_FWD(p); +} + +static inline int rtl838x_mac_link_spd_sts(int p) +{ + return RTL838X_MAC_LINK_SPD_STS(p); +} + +inline static int rtl838x_trk_mbr_ctr(int group) +{ + return RTL838X_TRK_MBR_CTR + (group << 2); +} + +/* + * Fills an L2 entry structure from the SoC registers + */ +static void rtl838x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) +{ + /* Table contains different entry types, we need to identify the right one: + * Check for MC entries, first + * In contrast to the RTL93xx SoCs, there is no valid bit, use heuristics to + * identify valid entries + */ + e->is_ip_mc = !!(r[0] & BIT(22)); + e->is_ipv6_mc = !!(r[0] & BIT(21)); + e->type = L2_INVALID; + + if (!e->is_ip_mc && !e->is_ipv6_mc) { + e->mac[0] = (r[1] >> 20); + e->mac[1] = (r[1] >> 12); + e->mac[2] = (r[1] >> 4); + e->mac[3] = (r[1] & 0xf) << 4 | (r[2] >> 28); + e->mac[4] = (r[2] >> 20); + e->mac[5] = (r[2] >> 12); + + e->rvid = r[2] & 0xfff; + e->vid = r[0] & 0xfff; + + /* Is it a unicast entry? check multicast bit */ + if (!(e->mac[0] & 1)) { + e->is_static = !!((r[0] >> 19) & 1); + e->port = (r[0] >> 12) & 0x1f; + e->block_da = !!(r[1] & BIT(30)); + e->block_sa = !!(r[1] & BIT(31)); + e->suspended = !!(r[1] & BIT(29)); + e->next_hop = !!(r[1] & BIT(28)); + if (e->next_hop) { + pr_info("Found next hop entry, need to read extra data\n"); + e->nh_vlan_target = !!(r[0] & BIT(9)); + e->nh_route_id = r[0] & 0x1ff; + } + e->age = (r[0] >> 17) & 0x3; + e->valid = true; + + /* A valid entry has one of mutli-cast, aging, sa/da-blocking, + * next-hop or static entry bit set */ + if (!(r[0] & 0x007c0000) && !(r[1] & 0xd0000000)) + e->valid = false; + else + e->type = L2_UNICAST; + } else { // L2 multicast + pr_info("Got L2 MC entry: %08x %08x %08x\n", r[0], r[1], r[2]); + e->valid = true; + e->type = L2_MULTICAST; + e->mc_portmask_index = (r[0] >> 12) & 0x1ff; + } + } else { // IPv4 and IPv6 multicast + e->valid = true; + e->mc_portmask_index = (r[0] >> 12) & 0x1ff; + e->mc_gip = r[1]; + e->mc_sip = r[2]; + e->rvid = r[0] & 0xfff; + } + if (e->is_ip_mc) + e->type = IP4_MULTICAST; + if (e->is_ipv6_mc) + e->type = IP6_MULTICAST; +} + +/* + * Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry + */ +static void rtl838x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) +{ + u64 mac = ether_addr_to_u64(e->mac); + + if (!e->valid) { + r[0] = r[1] = r[2] = 0; + return; + } + + r[0] = e->is_ip_mc ? BIT(22) : 0; + r[0] |= e->is_ipv6_mc ? BIT(21) : 0; + + if (!e->is_ip_mc && !e->is_ipv6_mc) { + r[1] = mac >> 20; + r[2] = (mac & 0xfffff) << 12; + + /* Is it a unicast entry? check multicast bit */ + if (!(e->mac[0] & 1)) { + r[0] |= e->is_static ? BIT(19) : 0; + r[0] |= (e->port & 0x3f) << 12; + r[0] |= e->vid; + r[1] |= e->block_da ? BIT(30) : 0; + r[1] |= e->block_sa ? BIT(31) : 0; + r[1] |= e->suspended ? BIT(29) : 0; + r[2] |= e->rvid & 0xfff; + if (e->next_hop) { + r[1] |= BIT(28); + r[0] |= e->nh_vlan_target ? BIT(9) : 0; + r[0] |= e->nh_route_id &0x1ff; + } + r[0] |= (e->age & 0x3) << 17; + } else { // L2 Multicast + r[0] |= (e->mc_portmask_index & 0x1ff) << 12; + r[2] |= e->rvid & 0xfff; + r[0] |= e->vid & 0xfff; + pr_info("FILL MC: %08x %08x %08x\n", r[0], r[1], r[2]); + } + } else { // IPv4 and IPv6 multicast + r[1] = e->mc_gip; + r[2] = e->mc_sip; + r[0] |= e->rvid; + } +} + +/* + * Read an L2 UC or MC entry out of a hash bucket of the L2 forwarding table + * hash is the id of the bucket and pos is the position of the entry in that bucket + * The data read from the SoC is filled into rtl838x_l2_entry + */ +static u64 rtl838x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2_entry *e) +{ + u64 entry; + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 0); // Access L2 Table 0 + u32 idx = (0 << 14) | (hash << 2) | pos; // Search SRAM, with hash and at pos in bucket + int i; + + rtl_table_read(q, idx); + for (i= 0; i < 3; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl838x_fill_l2_entry(r, e); + if (!e->valid) + return 0; + + entry = (((u64) r[1]) << 32) | (r[2] & 0xfffff000) | (r[0] & 0xfff); + return entry; +} + +static void rtl838x_write_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 0); + int i; + + u32 idx = (0 << 14) | (hash << 2) | pos; // Access SRAM, with hash and at pos in bucket + + rtl838x_fill_l2_row(r, e); + + for (i= 0; i < 3; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static u64 rtl838x_read_cam(int idx, struct rtl838x_l2_entry *e) +{ + u64 entry; + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 1); // Access L2 Table 1 + int i; + + rtl_table_read(q, idx); + for (i= 0; i < 3; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl838x_fill_l2_entry(r, e); + if (!e->valid) + return 0; + + pr_debug("Found in CAM: R1 %x R2 %x R3 %x\n", r[0], r[1], r[2]); + + // Return MAC with concatenated VID ac concatenated ID + entry = (((u64) r[1]) << 32) | (r[2] & 0xfffff000) | (r[0] & 0xfff); + return entry; +} + +static void rtl838x_write_cam(int idx, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 1); // Access L2 Table 1 + int i; + + rtl838x_fill_l2_row(r, e); + + for (i= 0; i < 3; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static u64 rtl838x_read_mcast_pmask(int idx) +{ + u32 portmask; + // Read MC_PMSK (2) via register RTL8380_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 2); + + rtl_table_read(q, idx); + portmask = sw_r32(rtl_table_data(q, 0)); + rtl_table_release(q); + + return portmask; +} + +static void rtl838x_write_mcast_pmask(int idx, u64 portmask) +{ + // Access MC_PMSK (2) via register RTL8380_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8380_TBL_L2, 2); + + sw_w32(((u32)portmask) & 0x1fffffff, rtl_table_data(q, 0)); + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static void rtl838x_vlan_profile_setup(int profile) +{ + u32 pmask_id = UNKNOWN_MC_PMASK; + // Enable L2 Learning BIT 0, portmask UNKNOWN_MC_PMASK for unknown MC traffic flooding + u32 p = 1 | pmask_id << 1 | pmask_id << 10 | pmask_id << 19; + + sw_w32(p, RTL838X_VLAN_PROFILE(profile)); + + /* RTL8380 and RTL8390 use an index into the portmask table to set the + * unknown multicast portmask, setup a default at a safe location + * On RTL93XX, the portmask is directly set in the profile, + * see e.g. rtl9300_vlan_profile_setup + */ + rtl838x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0x1fffffff); +} + +static inline int rtl838x_vlan_port_egr_filter(int port) +{ + return RTL838X_VLAN_PORT_EGR_FLTR; +} + +static inline int rtl838x_vlan_port_igr_filter(int port) +{ + return RTL838X_VLAN_PORT_IGR_FLTR(port); +} + +static void rtl838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 15 /* Execute cmd */ + | 1 << 14 /* Read */ + | 2 << 12 /* Table type 0b10 */ + | (msti & 0xfff); + priv->r->exec_tbl0_cmd(cmd); + + for (i = 0; i < 2; i++) + port_state[i] = sw_r32(priv->r->tbl_access_data_0(i)); +} + +static void rtl838x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 15 /* Execute cmd */ + | 0 << 14 /* Write */ + | 2 << 12 /* Table type 0b10 */ + | (msti & 0xfff); + + for (i = 0; i < 2; i++) + sw_w32(port_state[i], priv->r->tbl_access_data_0(i)); + priv->r->exec_tbl0_cmd(cmd); +} + +u64 rtl838x_traffic_get(int source) +{ + return rtl838x_get_port_reg(rtl838x_port_iso_ctrl(source)); +} + +void rtl838x_traffic_set(int source, u64 dest_matrix) +{ + rtl838x_set_port_reg(dest_matrix, rtl838x_port_iso_ctrl(source)); +} + +void rtl838x_traffic_enable(int source, int dest) +{ + rtl838x_mask_port_reg(0, BIT(dest), rtl838x_port_iso_ctrl(source)); +} + +void rtl838x_traffic_disable(int source, int dest) +{ + rtl838x_mask_port_reg(BIT(dest), 0, rtl838x_port_iso_ctrl(source)); +} + +/* + * Enables or disables the EEE/EEEP capability of a port + */ +static void rtl838x_port_eee_set(struct rtl838x_switch_priv *priv, int port, bool enable) +{ + u32 v; + + // This works only for Ethernet ports, and on the RTL838X, ports from 24 are SFP + if (port >= 24) + return; + + pr_debug("In %s: setting port %d to %d\n", __func__, port, enable); + v = enable ? 0x3 : 0x0; + + // Set EEE state for 100 (bit 9) & 1000MBit (bit 10) + sw_w32_mask(0x3 << 9, v << 9, priv->r->mac_force_mode_ctrl(port)); + + // Set TX/RX EEE state + if (enable) { + sw_w32_mask(0, BIT(port), RTL838X_EEE_PORT_TX_EN); + sw_w32_mask(0, BIT(port), RTL838X_EEE_PORT_RX_EN); + } else { + sw_w32_mask(BIT(port), 0, RTL838X_EEE_PORT_TX_EN); + sw_w32_mask(BIT(port), 0, RTL838X_EEE_PORT_RX_EN); + } + priv->ports[port].eee_enabled = enable; +} + + +/* + * Get EEE own capabilities and negotiation result + */ +static int rtl838x_eee_port_ability(struct rtl838x_switch_priv *priv, + struct ethtool_eee *e, int port) +{ + u64 link; + + if (port >= 24) + return 0; + + link = rtl839x_get_port_reg_le(RTL838X_MAC_LINK_STS); + if (!(link & BIT(port))) + return 0; + + if (sw_r32(rtl838x_mac_force_mode_ctrl(port)) & BIT(9)) + e->advertised |= ADVERTISED_100baseT_Full; + + if (sw_r32(rtl838x_mac_force_mode_ctrl(port)) & BIT(10)) + e->advertised |= ADVERTISED_1000baseT_Full; + + if (sw_r32(RTL838X_MAC_EEE_ABLTY) & BIT(port)) { + e->lp_advertised = ADVERTISED_100baseT_Full; + e->lp_advertised |= ADVERTISED_1000baseT_Full; + return 1; + } + + return 0; +} + +static void rtl838x_init_eee(struct rtl838x_switch_priv *priv, bool enable) +{ + int i; + + pr_info("Setting up EEE, state: %d\n", enable); + sw_w32_mask(0x4, 0, RTL838X_SMI_GLB_CTRL); + + /* Set timers for EEE */ + sw_w32(0x5001411, RTL838X_EEE_TX_TIMER_GIGA_CTRL); + sw_w32(0x5001417, RTL838X_EEE_TX_TIMER_GELITE_CTRL); + + // Enable EEE MAC support on ports + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) + rtl838x_port_eee_set(priv, i, enable); + } + priv->eee_enabled = enable; +} + +const struct rtl838x_reg rtl838x_reg = { + .mask_port_reg_be = rtl838x_mask_port_reg, + .set_port_reg_be = rtl838x_set_port_reg, + .get_port_reg_be = rtl838x_get_port_reg, + .mask_port_reg_le = rtl838x_mask_port_reg, + .set_port_reg_le = rtl838x_set_port_reg, + .get_port_reg_le = rtl838x_get_port_reg, + .stat_port_rst = RTL838X_STAT_PORT_RST, + .stat_rst = RTL838X_STAT_RST, + .stat_port_std_mib = RTL838X_STAT_PORT_STD_MIB, + .port_iso_ctrl = rtl838x_port_iso_ctrl, + .traffic_enable = rtl838x_traffic_enable, + .traffic_disable = rtl838x_traffic_disable, + .traffic_get = rtl838x_traffic_get, + .traffic_set = rtl838x_traffic_set, + .l2_ctrl_0 = RTL838X_L2_CTRL_0, + .l2_ctrl_1 = RTL838X_L2_CTRL_1, + .l2_port_aging_out = RTL838X_L2_PORT_AGING_OUT, + .smi_poll_ctrl = RTL838X_SMI_POLL_CTRL, + .l2_tbl_flush_ctrl = RTL838X_L2_TBL_FLUSH_CTRL, + .exec_tbl0_cmd = rtl838x_exec_tbl0_cmd, + .exec_tbl1_cmd = rtl838x_exec_tbl1_cmd, + .tbl_access_data_0 = rtl838x_tbl_access_data_0, + .isr_glb_src = RTL838X_ISR_GLB_SRC, + .isr_port_link_sts_chg = RTL838X_ISR_PORT_LINK_STS_CHG, + .imr_port_link_sts_chg = RTL838X_IMR_PORT_LINK_STS_CHG, + .imr_glb = RTL838X_IMR_GLB, + .vlan_tables_read = rtl838x_vlan_tables_read, + .vlan_set_tagged = rtl838x_vlan_set_tagged, + .vlan_set_untagged = rtl838x_vlan_set_untagged, + .mac_force_mode_ctrl = rtl838x_mac_force_mode_ctrl, + .vlan_profile_dump = rtl838x_vlan_profile_dump, + .vlan_profile_setup = rtl838x_vlan_profile_setup, + .vlan_fwd_on_inner = rtl838x_vlan_fwd_on_inner, + .stp_get = rtl838x_stp_get, + .stp_set = rtl838x_stp_set, + .mac_port_ctrl = rtl838x_mac_port_ctrl, + .l2_port_new_salrn = rtl838x_l2_port_new_salrn, + .l2_port_new_sa_fwd = rtl838x_l2_port_new_sa_fwd, + .mir_ctrl = RTL838X_MIR_CTRL, + .mir_dpm = RTL838X_MIR_DPM_CTRL, + .mir_spm = RTL838X_MIR_SPM_CTRL, + .mac_link_sts = RTL838X_MAC_LINK_STS, + .mac_link_dup_sts = RTL838X_MAC_LINK_DUP_STS, + .mac_link_spd_sts = rtl838x_mac_link_spd_sts, + .mac_rx_pause_sts = RTL838X_MAC_RX_PAUSE_STS, + .mac_tx_pause_sts = RTL838X_MAC_TX_PAUSE_STS, + .read_l2_entry_using_hash = rtl838x_read_l2_entry_using_hash, + .write_l2_entry_using_hash = rtl838x_write_l2_entry_using_hash, + .read_cam = rtl838x_read_cam, + .write_cam = rtl838x_write_cam, + .vlan_port_egr_filter = RTL838X_VLAN_PORT_EGR_FLTR, + .vlan_port_igr_filter = RTL838X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_pb = RTL838X_VLAN_PORT_PB_VLAN, + .vlan_port_tag_sts_ctrl = RTL838X_VLAN_PORT_TAG_STS_CTRL, + .trk_mbr_ctr = rtl838x_trk_mbr_ctr, + .rma_bpdu_fld_pmask = RTL838X_RMA_BPDU_FLD_PMSK, + .spcl_trap_eapol_ctrl = RTL838X_SPCL_TRAP_EAPOL_CTRL, + .init_eee = rtl838x_init_eee, + .port_eee_set = rtl838x_port_eee_set, + .eee_port_ability = rtl838x_eee_port_ability, + .l2_hash_seed = rtl838x_l2_hash_seed, + .l2_hash_key = rtl838x_l2_hash_key, + .read_mcast_pmask = rtl838x_read_mcast_pmask, + .write_mcast_pmask = rtl838x_write_mcast_pmask, +}; + +irqreturn_t rtl838x_switch_irq(int irq, void *dev_id) +{ + struct dsa_switch *ds = dev_id; + u32 status = sw_r32(RTL838X_ISR_GLB_SRC); + u32 ports = sw_r32(RTL838X_ISR_PORT_LINK_STS_CHG); + u32 link; + int i; + + /* Clear status */ + sw_w32(ports, RTL838X_ISR_PORT_LINK_STS_CHG); + pr_info("RTL8380 Link change: status: %x, ports %x\n", status, ports); + + for (i = 0; i < 28; i++) { + if (ports & BIT(i)) { + link = sw_r32(RTL838X_MAC_LINK_STS); + if (link & BIT(i)) + dsa_port_phylink_mac_change(ds, i, true); + else + dsa_port_phylink_mac_change(ds, i, false); + } + } + return IRQ_HANDLED; +} + +int rtl838x_smi_wait_op(int timeout) +{ + do { + timeout--; + udelay(10); + } while ((sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_1) & 0x1) && (timeout >= 0)); + if (timeout <= 0) + return -1; + return 0; +} + +/* + * Reads a register in a page from the PHY + */ +int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + u32 v; + u32 park_page; + + if (port > 31) { + *val = 0xffff; + return 0; + } + + if (page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + park_page = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_1) & ((0x1f << 15) | 0x2); + v = reg << 20 | page << 3; + sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); + sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; + + mutex_unlock(&smi_lock); + return 0; + +timeout: + mutex_unlock(&smi_lock); + return -ETIMEDOUT; +} + +/* + * Write to a register in a page of the PHY + */ +int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + u32 v; + u32 park_page; + + val &= 0xffff; + if (port > 31 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + park_page = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_1) & ((0x1f << 15) | 0x2); + v = reg << 20 | page << 3 | 0x4; + sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); + sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + mutex_unlock(&smi_lock); + return 0; + +timeout: + mutex_unlock(&smi_lock); + return -ETIMEDOUT; +} + +/* + * Read an mmd register of a PHY + */ +int rtl838x_read_mmd_phy(u32 port, u32 addr, u32 reg, u32 *val) +{ + u32 v; + + mutex_lock(&smi_lock); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = addr << 16 | reg; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_3); + + /* mmd-access | read | cmd-start */ + v = 1 << 1 | 0 << 2 | 1; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; + + mutex_unlock(&smi_lock); + return 0; + +timeout: + mutex_unlock(&smi_lock); + return -ETIMEDOUT; +} + +/* + * Write to an mmd register of a PHY + */ +int rtl838x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val) +{ + u32 v; + + pr_debug("MMD write: port %d, dev %d, reg %d, val %x\n", port, addr, reg, val); + val &= 0xffff; + mutex_lock(&smi_lock); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + sw_w32_mask(0x1f << 16, addr << 16, RTL838X_SMI_ACCESS_PHY_CTRL_3); + sw_w32_mask(0xffff, reg, RTL838X_SMI_ACCESS_PHY_CTRL_3); + /* mmd-access | write | cmd-start */ + v = 1 << 1 | 1 << 2 | 1; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + if (rtl838x_smi_wait_op(10000)) + goto timeout; + + mutex_unlock(&smi_lock); + return 0; + +timeout: + mutex_unlock(&smi_lock); + return -ETIMEDOUT; +} + +void rtl8380_get_version(struct rtl838x_switch_priv *priv) +{ + u32 rw_save, info_save; + u32 info; + + rw_save = sw_r32(RTL838X_INT_RW_CTRL); + sw_w32(rw_save | 0x3, RTL838X_INT_RW_CTRL); + + info_save = sw_r32(RTL838X_CHIP_INFO); + sw_w32(info_save | 0xA0000000, RTL838X_CHIP_INFO); + + info = sw_r32(RTL838X_CHIP_INFO); + sw_w32(info_save, RTL838X_CHIP_INFO); + sw_w32(rw_save, RTL838X_INT_RW_CTRL); + + if ((info & 0xFFFF) == 0x6275) { + if (((info >> 16) & 0x1F) == 0x1) + priv->version = RTL8380_VERSION_A; + else if (((info >> 16) & 0x1F) == 0x2) + priv->version = RTL8380_VERSION_B; + else + priv->version = RTL8380_VERSION_B; + } else { + priv->version = '-'; + } +} + +void rtl838x_vlan_profile_dump(int profile) +{ + u32 p; + + if (profile < 0 || profile > 7) + return; + + p = sw_r32(RTL838X_VLAN_PROFILE(profile)); + + pr_info("VLAN profile %d: L2 learning: %d, UNKN L2MC FLD PMSK %d, \ + UNKN IPMC FLD PMSK %d, UNKN IPv6MC FLD PMSK: %d", + profile, p & 1, (p >> 1) & 0x1ff, (p >> 10) & 0x1ff, (p >> 19) & 0x1ff); +} + +void rtl8380_sds_rst(int mac) +{ + u32 offset = (mac == 24) ? 0 : 0x100; + + sw_w32_mask(1 << 11, 0, RTL838X_SDS4_FIB_REG0 + offset); + sw_w32_mask(0x3, 0, RTL838X_SDS4_REG28 + offset); + sw_w32_mask(0x3, 0x3, RTL838X_SDS4_REG28 + offset); + sw_w32_mask(0, 0x1 << 6, RTL838X_SDS4_DUMMY0 + offset); + sw_w32_mask(0x1 << 6, 0, RTL838X_SDS4_DUMMY0 + offset); + pr_debug("SERDES reset: %d\n", mac); +} + +int rtl8380_sds_power(int mac, int val) +{ + u32 mode = (val == 1) ? 0x4 : 0x9; + u32 offset = (mac == 24) ? 5 : 0; + + if ((mac != 24) && (mac != 26)) { + pr_err("%s: not a fibre port: %d\n", __func__, mac); + return -1; + } + + sw_w32_mask(0x1f << offset, mode << offset, RTL838X_SDS_MODE_SEL); + + rtl8380_sds_rst(mac); + + 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 new file mode 100644 index 0000000000..b2097363b9 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -0,0 +1,526 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _RTL838X_H +#define _RTL838X_H + +#include + +/* + * Register definition + */ +#define RTL838X_MAC_PORT_CTRL(port) (0xd560 + (((port) << 7))) +#define RTL839X_MAC_PORT_CTRL(port) (0x8004 + (((port) << 7))) +#define RTL930X_MAC_PORT_CTRL(port) (0x3260 + (((port) << 6))) +#define RTL930X_MAC_L2_PORT_CTRL(port) (0x3268 + (((port) << 6))) +#define RTL931X_MAC_PORT_CTRL(port) (0x6004 + (((port) << 7))) + +#define RTL838X_RST_GLB_CTRL_0 (0x003c) + +#define RTL838X_MAC_FORCE_MODE_CTRL (0xa104) +#define RTL839X_MAC_FORCE_MODE_CTRL (0x02bc) +#define RTL930X_MAC_FORCE_MODE_CTRL (0xCA1C) +#define RTL931X_MAC_FORCE_MODE_CTRL (0x0DCC) + +#define RTL838X_DMY_REG31 (0x3b28) +#define RTL838X_SDS_MODE_SEL (0x0028) +#define RTL838X_SDS_CFG_REG (0x0034) +#define RTL838X_INT_MODE_CTRL (0x005c) +#define RTL838X_CHIP_INFO (0x00d8) +#define RTL839X_CHIP_INFO (0x0ff4) +#define RTL838X_PORT_ISO_CTRL(port) (0x4100 + ((port) << 2)) +#define RTL839X_PORT_ISO_CTRL(port) (0x1400 + ((port) << 3)) + +/* Packet statistics */ +#define RTL838X_STAT_PORT_STD_MIB (0x1200) +#define RTL839X_STAT_PORT_STD_MIB (0xC000) +#define RTL930X_STAT_PORT_MIB_CNTR (0x0664) +#define RTL838X_STAT_RST (0x3100) +#define RTL839X_STAT_RST (0xF504) +#define RTL930X_STAT_RST (0x3240) +#define RTL931X_STAT_RST (0x7ef4) +#define RTL838X_STAT_PORT_RST (0x3104) +#define RTL839X_STAT_PORT_RST (0xF508) +#define RTL930X_STAT_PORT_RST (0x3244) +#define RTL931X_STAT_PORT_RST (0x7ef8) +#define RTL838X_STAT_CTRL (0x3108) +#define RTL839X_STAT_CTRL (0x04cc) +#define RTL930X_STAT_CTRL (0x3248) +#define RTL931X_STAT_CTRL (0x5720) + +/* Registers of the internal Serdes of the 8390 */ +#define RTL8390_SDS0_1_XSG0 (0xA000) +#define RTL8390_SDS0_1_XSG1 (0xA100) +#define RTL839X_SDS12_13_XSG0 (0xB800) +#define RTL839X_SDS12_13_XSG1 (0xB900) +#define RTL839X_SDS12_13_PWR0 (0xb880) +#define RTL839X_SDS12_13_PWR1 (0xb980) + +/* Registers of the internal Serdes of the 8380 */ +#define RTL838X_SDS4_FIB_REG0 (0xF800) +#define RTL838X_SDS4_REG28 (0xef80) +#define RTL838X_SDS4_DUMMY0 (0xef8c) +#define RTL838X_SDS5_EXT_REG6 (0xf18c) + +/* VLAN registers */ +#define RTL838X_VLAN_CTRL (0x3A74) +#define RTL838X_VLAN_PROFILE(idx) (0x3A88 + ((idx) << 2)) +#define RTL838X_VLAN_PORT_EGR_FLTR (0x3A84) +#define RTL838X_VLAN_PORT_PB_VLAN (0x3C00) +#define RTL838X_VLAN_PORT_IGR_FLTR(port) (0x3A7C + (((port >> 4) << 2))) +#define RTL838X_VLAN_PORT_IGR_FLTR_0 (0x3A7C) +#define RTL838X_VLAN_PORT_IGR_FLTR_1 (0x3A7C + 4) +#define RTL838X_VLAN_PORT_TAG_STS_CTRL (0xA530) + +#define RTL839X_VLAN_PROFILE(idx) (0x25C0 + (((idx) << 3))) +#define RTL839X_VLAN_CTRL (0x26D4) +#define RTL839X_VLAN_PORT_PB_VLAN (0x26D8) +#define RTL839X_VLAN_PORT_IGR_FLTR(port) (0x27B4 + (((port >> 4) << 2))) +#define RTL839X_VLAN_PORT_EGR_FLTR(port) (0x27C4 + (((port >> 5) << 2))) +#define RTL839X_VLAN_PORT_TAG_STS_CTRL (0x6828) + +#define RTL930X_VLAN_PROFILE_SET(idx) (0x9c60 + (((idx) * 20))) +#define RTL930X_VLAN_CTRL (0x82D4) +#define RTL930X_VLAN_PORT_PB_VLAN (0x82D8) +#define RTL930X_VLAN_PORT_IGR_FLTR(port) (0x83C0 + (((port >> 4) << 2))) +#define RTL930X_VLAN_PORT_EGR_FLTR (0x83C8) +#define RTL930X_VLAN_PORT_TAG_STS_CTRL (0xCE24) + +#define RTL931X_VLAN_PROFILE_SET(idx) (0x9800 + (((idx) * 28))) +#define RTL931X_VLAN_CTRL (0x94E4) +#define RTL931X_VLAN_PORT_IGR_FLTR(port) (0x96B4 + (((port >> 4) << 2))) +#define RTL931X_VLAN_PORT_EGR_FLTR(port) (0x96C4 + (((port >> 5) << 2))) +#define RTL931X_VLAN_PORT_TAG_CTRL (0x4860) + +/* Table access registers */ +#define RTL838X_TBL_ACCESS_CTRL_0 (0x6914) +#define RTL838X_TBL_ACCESS_DATA_0(idx) (0x6918 + ((idx) << 2)) +#define RTL838X_TBL_ACCESS_CTRL_1 (0xA4C8) +#define RTL838X_TBL_ACCESS_DATA_1(idx) (0xA4CC + ((idx) << 2)) + +#define RTL839X_TBL_ACCESS_CTRL_0 (0x1190) +#define RTL839X_TBL_ACCESS_DATA_0(idx) (0x1194 + ((idx) << 2)) +#define RTL839X_TBL_ACCESS_CTRL_1 (0x6b80) +#define RTL839X_TBL_ACCESS_DATA_1(idx) (0x6b84 + ((idx) << 2)) +#define RTL839X_TBL_ACCESS_CTRL_2 (0x611C) +#define RTL839X_TBL_ACCESS_DATA_2(i) (0x6120 + (((i) << 2))) + +#define RTL930X_TBL_ACCESS_CTRL_0 (0xB340) +#define RTL930X_TBL_ACCESS_DATA_0(idx) (0xB344 + ((idx) << 2)) +#define RTL930X_TBL_ACCESS_CTRL_1 (0xB3A0) +#define RTL930X_TBL_ACCESS_DATA_1(idx) (0xB3A4 + ((idx) << 2)) +#define RTL930X_TBL_ACCESS_CTRL_2 (0xCE04) +#define RTL930X_TBL_ACCESS_DATA_2(i) (0xCE08 + (((i) << 2))) + +#define RTL931X_TBL_ACCESS_CTRL_0 (0x8500) +#define RTL931X_TBL_ACCESS_DATA_0(idx) (0x8508 + ((idx) << 2)) +#define RTL931X_TBL_ACCESS_CTRL_1 (0x40C0) +#define RTL931X_TBL_ACCESS_DATA_1(idx) (0x40C4 + ((idx) << 2)) +#define RTL931X_TBL_ACCESS_CTRL_2 (0x8528) +#define RTL931X_TBL_ACCESS_DATA_2(i) (0x852C + (((i) << 2))) +#define RTL931X_TBL_ACCESS_CTRL_3 (0x0200) +#define RTL931X_TBL_ACCESS_DATA_3(i) (0x0204 + (((i) << 2))) +#define RTL931X_TBL_ACCESS_CTRL_4 (0x20DC) +#define RTL931X_TBL_ACCESS_DATA_4(i) (0x20E0 + (((i) << 2))) +#define RTL931X_TBL_ACCESS_CTRL_5 (0x7E1C) +#define RTL931X_TBL_ACCESS_DATA_5(i) (0x7E20 + (((i) << 2))) + +/* MAC handling */ +#define RTL838X_MAC_LINK_STS (0xa188) +#define RTL839X_MAC_LINK_STS (0x0390) +#define RTL930X_MAC_LINK_STS (0xCB10) +#define RTL931X_MAC_LINK_STS (0x0EC0) +#define RTL838X_MAC_LINK_SPD_STS(p) (0xa190 + (((p >> 4) << 2))) +#define RTL839X_MAC_LINK_SPD_STS(p) (0x03a0 + (((p >> 4) << 2))) +#define RTL930X_MAC_LINK_SPD_STS(p) (0xCB18 + (((p >> 3) << 2))) +#define RTL931X_MAC_LINK_SPD_STS(p) (0x0ED0 + (((p >> 3) << 2))) +#define RTL838X_MAC_LINK_DUP_STS (0xa19c) +#define RTL839X_MAC_LINK_DUP_STS (0x03b0) +#define RTL930X_MAC_LINK_DUP_STS (0xCB28) +#define RTL931X_MAC_LINK_DUP_STS (0x0EF0) +#define RTL838X_MAC_TX_PAUSE_STS (0xa1a0) +#define RTL839X_MAC_TX_PAUSE_STS (0x03b8) +#define RTL930X_MAC_TX_PAUSE_STS (0xCB2C) +#define RTL931X_MAC_TX_PAUSE_STS (0x0EF8) +#define RTL838X_MAC_RX_PAUSE_STS (0xa1a4) +#define RTL839X_MAC_RX_PAUSE_STS (0x03c0) +#define RTL930X_MAC_RX_PAUSE_STS (0xCB30) +#define RTL931X_MAC_RX_PAUSE_STS (0x0F00) + +/* MAC link state bits */ +#define FORCE_EN (1 << 0) +#define FORCE_LINK_EN (1 << 1) +#define NWAY_EN (1 << 2) +#define DUPLX_MODE (1 << 3) +#define TX_PAUSE_EN (1 << 6) +#define RX_PAUSE_EN (1 << 7) + +/* EEE */ +#define RTL838X_MAC_EEE_ABLTY (0xa1a8) +#define RTL838X_EEE_PORT_TX_EN (0x014c) +#define RTL838X_EEE_PORT_RX_EN (0x0150) +#define RTL838X_EEE_CLK_STOP_CTRL (0x0148) +#define RTL838X_EEE_TX_TIMER_GIGA_CTRL (0xaa04) +#define RTL838X_EEE_TX_TIMER_GELITE_CTRL (0xaa08) + +#define RTL839X_EEE_TX_TIMER_GELITE_CTRL (0x042C) +#define RTL839X_EEE_TX_TIMER_GIGA_CTRL (0x0430) +#define RTL839X_EEE_TX_TIMER_10G_CTRL (0x0434) +#define RTL839X_EEE_CTRL(p) (0x8008 + ((p) << 7)) +#define RTL839X_MAC_EEE_ABLTY (0x03C8) + +#define RTL930X_MAC_EEE_ABLTY (0xCB34) +#define RTL930X_EEE_CTRL(p) (0x3274 + ((p) << 6)) +#define RTL930X_EEEP_PORT_CTRL(p) (0x3278 + ((p) << 6)) + +/* L2 functionality */ +#define RTL838X_L2_CTRL_0 (0x3200) +#define RTL839X_L2_CTRL_0 (0x3800) +#define RTL930X_L2_CTRL (0x8FD8) +#define RTL931X_L2_CTRL (0xC800) +#define RTL838X_L2_CTRL_1 (0x3204) +#define RTL839X_L2_CTRL_1 (0x3804) +#define RTL930X_L2_AGE_CTRL (0x8FDC) +#define RTL931X_L2_AGE_CTRL (0xC804) +#define RTL838X_L2_PORT_AGING_OUT (0x3358) +#define RTL839X_L2_PORT_AGING_OUT (0x3b74) +#define RTL930X_L2_PORT_AGE_CTRL (0x8FE0) +#define RTL931X_L2_PORT_AGE_CTRL (0xc808) +#define RTL838X_TBL_ACCESS_L2_CTRL (0x6900) +#define RTL839X_TBL_ACCESS_L2_CTRL (0x1180) +#define RTL930X_TBL_ACCESS_L2_CTRL (0xB320) +#define RTL930X_TBL_ACCESS_L2_METHOD_CTRL (0xB324) +#define RTL838X_TBL_ACCESS_L2_DATA(idx) (0x6908 + ((idx) << 2)) +#define RTL839X_TBL_ACCESS_L2_DATA(idx) (0x1184 + ((idx) << 2)) +#define RTL930X_TBL_ACCESS_L2_DATA(idx) (0xab08 + ((idx) << 2)) +#define RTL838X_L2_TBL_FLUSH_CTRL (0x3370) +#define RTL839X_L2_TBL_FLUSH_CTRL (0x3ba0) +#define RTL930X_L2_TBL_FLUSH_CTRL (0x9404) +#define RTL931X_L2_TBL_FLUSH_CTRL (0xCD9C) + +#define RTL838X_L2_PORT_NEW_SALRN(p) (0x328c + (((p >> 4) << 2))) +#define RTL839X_L2_PORT_NEW_SALRN(p) (0x38F0 + (((p >> 4) << 2))) +#define RTL930X_L2_PORT_SALRN(p) (0x8FEC + (((p >> 4) << 2))) +#define RTL931X_L2_PORT_NEW_SALRN(p) (0xC820 + (((p >> 4) << 2))) +#define RTL838X_L2_PORT_NEW_SA_FWD(p) (0x3294 + (((p >> 4) << 2))) +#define RTL839X_L2_PORT_NEW_SA_FWD(p) (0x3900 + (((p >> 4) << 2))) +#define RTL930X_L2_PORT_NEW_SA_FWD(p) (0x8FF4 + (((p / 10) << 2))) +#define RTL931X_L2_PORT_NEW_SA_FWD(p) (0xC830 + (((p / 10) << 2))) + +#define RTL930X_ST_CTRL (0x8798) + +#define RTL930X_L2_PORT_SABLK_CTRL (0x905c) +#define RTL930X_L2_PORT_DABLK_CTRL (0x9060) + +#define RTL838X_RMA_BPDU_FLD_PMSK (0x4348) +#define RTL930X_RMA_BPDU_FLD_PMSK (0x9F18) +#define RTL931X_RMA_BPDU_FLD_PMSK (0x8950) +#define RTL839X_RMA_BPDU_FLD_PMSK (0x125C) + +#define RTL838X_L2_PORT_LM_ACT(p) (0x3208 + ((p) << 2)) +#define RTL838X_VLAN_PORT_FWD (0x3A78) +#define RTL839X_VLAN_PORT_FWD (0x27AC) +#define RTL930X_VLAN_PORT_FWD (0x834C) +#define RTL838X_VLAN_FID_CTRL (0x3aa8) + +/* Port Mirroring */ +#define RTL838X_MIR_CTRL (0x5D00) +#define RTL838X_MIR_DPM_CTRL (0x5D20) +#define RTL838X_MIR_SPM_CTRL (0x5D10) + +#define RTL839X_MIR_CTRL (0x2500) +#define RTL839X_MIR_DPM_CTRL (0x2530) +#define RTL839X_MIR_SPM_CTRL (0x2510) + +#define RTL930X_MIR_CTRL (0xA2A0) +#define RTL930X_MIR_DPM_CTRL (0xA2C0) +#define RTL930X_MIR_SPM_CTRL (0xA2B0) + +#define RTL931X_MIR_CTRL (0xAF00) +#define RTL931X_MIR_DPM_CTRL (0xAF30) +#define RTL931X_MIR_SPM_CTRL (0xAF10) + +/* Storm/rate control and scheduling */ +#define RTL838X_STORM_CTRL (0x4700) +#define RTL839X_STORM_CTRL (0x1800) +#define RTL838X_STORM_CTRL_LB_CTRL(p) (0x4884 + (((p) << 2))) +#define RTL838X_STORM_CTRL_BURST_PPS_0 (0x4874) +#define RTL838X_STORM_CTRL_BURST_PPS_1 (0x4878) +#define RTL838X_STORM_CTRL_BURST_0 (0x487c) +#define RTL838X_STORM_CTRL_BURST_1 (0x4880) +#define RTL839X_STORM_CTRL_LB_TICK_TKN_CTRL_0 (0x1804) +#define RTL839X_STORM_CTRL_LB_TICK_TKN_CTRL_1 (0x1808) +#define RTL838X_SCHED_CTRL (0xB980) +#define RTL839X_SCHED_CTRL (0x60F4) +#define RTL838X_SCHED_LB_TICK_TKN_CTRL_0 (0xAD58) +#define RTL838X_SCHED_LB_TICK_TKN_CTRL_1 (0xAD5C) +#define RTL839X_SCHED_LB_TICK_TKN_CTRL_0 (0x1804) +#define RTL839X_SCHED_LB_TICK_TKN_CTRL_1 (0x1808) +#define RTL839X_STORM_CTRL_SPCL_LB_TICK_TKN_CTRL (0x2000) +#define RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_0 (0x1604) +#define RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_1 (0x1608) +#define RTL839X_SCHED_LB_TICK_TKN_CTRL (0x60F8) +#define RTL839X_SCHED_LB_TICK_TKN_PPS_CTRL (0x6200) +#define RTL838X_SCHED_LB_THR (0xB984) +#define RTL839X_SCHED_LB_THR (0x60FC) +#define RTL838X_SCHED_P_EGR_RATE_CTRL(p) (0xC008 + (((p) << 7))) +#define RTL838X_SCHED_Q_EGR_RATE_CTRL(p, q) (0xC00C + (p << 7) + (((q) << 2))) +#define RTL838X_STORM_CTRL_PORT_BC_EXCEED (0x470C) +#define RTL838X_STORM_CTRL_PORT_MC_EXCEED (0x4710) +#define RTL838X_STORM_CTRL_PORT_UC_EXCEED (0x4714) +#define RTL839X_STORM_CTRL_PORT_BC_EXCEED(p) (0x180c + (((p >> 5) << 2))) +#define RTL839X_STORM_CTRL_PORT_MC_EXCEED(p) (0x1814 + (((p >> 5) << 2))) +#define RTL839X_STORM_CTRL_PORT_UC_EXCEED(p) (0x181c + (((p >> 5) << 2))) +#define RTL838X_STORM_CTRL_PORT_UC(p) (0x4718 + (((p) << 2))) +#define RTL838X_STORM_CTRL_PORT_MC(p) (0x478c + (((p) << 2))) +#define RTL838X_STORM_CTRL_PORT_BC(p) (0x4800 + (((p) << 2))) +#define RTL839X_STORM_CTRL_PORT_UC_0(p) (0x185C + (((p) << 3))) +#define RTL839X_STORM_CTRL_PORT_UC_1(p) (0x1860 + (((p) << 3))) +#define RTL839X_STORM_CTRL_PORT_MC_0(p) (0x19FC + (((p) << 3))) +#define RTL839X_STORM_CTRL_PORT_MC_1(p) (0x1a00 + (((p) << 3))) +#define RTL839X_STORM_CTRL_PORT_BC_0(p) (0x1B9C + (((p) << 3))) +#define RTL839X_STORM_CTRL_PORT_BC_1(p) (0x1BA0 + (((p) << 3))) +#define RTL839X_TBL_ACCESS_CTRL_2 (0x611C) +#define RTL839X_TBL_ACCESS_DATA_2(i) (0x6120 + (((i) << 2))) +#define RTL839X_IGR_BWCTRL_PORT_CTRL_10G_0(p) (0x1618 + (((p) << 3))) +#define RTL839X_IGR_BWCTRL_PORT_CTRL_10G_1(p) (0x161C + (((p) << 3))) +#define RTL839X_IGR_BWCTRL_PORT_CTRL_0(p) (0x1640 + (((p) << 3))) +#define RTL839X_IGR_BWCTRL_PORT_CTRL_1(p) (0x1644 + (((p) << 3))) +#define RTL839X_IGR_BWCTRL_CTRL_LB_THR (0x1614) + +/* Link aggregation (Trunking) */ +#define RTL839X_TRK_MBR_CTR (0x2200) +#define RTL838X_TRK_MBR_CTR (0x3E00) +#define RTL930X_TRK_MBR_CTRL (0xA41C) +#define RTL931X_TRK_MBR_CTRL (0xB8D0) + +/* Attack prevention */ +#define RTL838X_ATK_PRVNT_PORT_EN (0x5B00) +#define RTL838X_ATK_PRVNT_CTRL (0x5B04) +#define RTL838X_ATK_PRVNT_ACT (0x5B08) +#define RTL838X_ATK_PRVNT_STS (0x5B1C) + +/* 802.1X */ +#define RTL838X_SPCL_TRAP_EAPOL_CTRL (0x6988) +#define RTL839X_SPCL_TRAP_EAPOL_CTRL (0x105C) + +/* QoS */ +#define RTL838X_QM_INTPRI2QID_CTRL (0x5F00) +#define RTL839X_QM_INTPRI2QID_CTRL(q) (0x1110 + (q << 2)) +#define RTL839X_QM_PORT_QNUM(p) (0x1130 + (((p / 10) << 2))) +#define RTL838X_PRI_SEL_PORT_PRI(p) (0x5FB8 + (((p / 10) << 2))) +#define RTL839X_PRI_SEL_PORT_PRI(p) (0x10A8 + (((p / 10) << 2))) +#define RTL838X_QM_PKT2CPU_INTPRI_MAP (0x5F10) +#define RTL839X_QM_PKT2CPU_INTPRI_MAP (0x1154) +#define RTL838X_PRI_SEL_CTRL (0x10E0) +#define RTL839X_PRI_SEL_CTRL (0x10E0) +#define RTL838X_PRI_SEL_TBL_CTRL(i) (0x5FD8 + (((i) << 2))) +#define RTL839X_PRI_SEL_TBL_CTRL(i) (0x10D0 + (((i) << 2))) +#define RTL838X_QM_PKT2CPU_INTPRI_0 (0x5F04) +#define RTL838X_QM_PKT2CPU_INTPRI_1 (0x5F08) +#define RTL838X_QM_PKT2CPU_INTPRI_2 (0x5F0C) +#define RTL839X_OAM_CTRL (0x2100) +#define RTL839X_OAM_PORT_ACT_CTRL(p) (0x2104 + (((p) << 2))) +#define RTL839X_RMK_PORT_DEI_TAG_CTRL(p) (0x6A9C + (((p >> 5) << 2))) +#define RTL839X_PRI_SEL_IPRI_REMAP (0x1080) +#define RTL838X_PRI_SEL_IPRI_REMAP (0x5F8C) +#define RTL839X_PRI_SEL_DEI2DP_REMAP (0x10EC) +#define RTL839X_PRI_SEL_DSCP2DP_REMAP_ADDR(i) (0x10F0 + (((i >> 4) << 2))) +#define RTL839X_RMK_DEI_CTRL (0x6AA4) +#define RTL839X_WRED_PORT_THR_CTRL(i) (0x6084 + ((i) << 2)) +#define RTL839X_WRED_QUEUE_THR_CTRL(q, i) (0x6090 + ((q) * 12) + ((i) << 2)) +#define RTL838X_PRI_DSCP_INVLD_CTRL0 (0x5FE8) +#define RTL838X_RMK_IPRI_CTRL (0xA460) +#define RTL838X_RMK_OPRI_CTRL (0xA464) +#define RTL838X_SCHED_P_TYPE_CTRL(p) (0xC04C + (((p) << 7))) +#define RTL838X_SCHED_LB_CTRL(p) (0xC004 + (((p) << 7))) +#define RTL838X_FC_P_EGR_DROP_CTRL(p) (0x6B1C + (((p) << 2))) + +/* Debug features */ +#define RTL930X_STAT_PRVTE_DROP_COUNTER0 (0xB5B8) + +#define MAX_VLANS 4096 +#define MAX_LAGS 16 +#define MAX_PRIOS 8 +#define RTL930X_PORT_IGNORE 0x3f +#define MAX_MC_GROUPS 512 +#define UNKNOWN_MC_PMASK (MAX_MC_GROUPS - 1) + +enum phy_type { + PHY_NONE = 0, + PHY_RTL838X_SDS = 1, + PHY_RTL8218B_INT = 2, + PHY_RTL8218B_EXT = 3, + PHY_RTL8214FC = 4, + PHY_RTL839X_SDS = 5, +}; + +struct rtl838x_port { + bool enable; + u64 pm; + u16 pvid; + bool eee_enabled; + enum phy_type phy; + bool is10G; + bool is2G5; + u8 sds_num; + const struct dsa_port *dp; +}; + +struct rtl838x_vlan_info { + u64 untagged_ports; + u64 tagged_ports; + u8 profile_id; + bool hash_mc_fid; + bool hash_uc_fid; + u8 fid; +}; + +enum l2_entry_type { + L2_INVALID = 0, + L2_UNICAST = 1, + L2_MULTICAST = 2, + IP4_MULTICAST = 3, + IP6_MULTICAST = 4, +}; + +struct rtl838x_l2_entry { + u8 mac[6]; + u16 vid; + u16 rvid; + u8 port; + bool valid; + enum l2_entry_type type; + bool is_static; + bool is_ip_mc; + bool is_ipv6_mc; + bool block_da; + bool block_sa; + bool suspended; + bool next_hop; + int age; + u8 trunk; + bool is_trunk; + u8 stack_dev; + u16 mc_portmask_index; + u32 mc_gip; + u32 mc_sip; + u16 mc_mac_index; + u16 nh_route_id; + bool nh_vlan_target; // Only RTL83xx: VLAN used for next hop +}; + +struct rtl838x_nexthop { + u16 id; // ID in HW Nexthop table + u32 ip; // IP Addres of nexthop + u32 dev_id; + u16 port; + u16 vid; + u16 fid; + u64 mac; + u16 mac_id; + u16 l2_id; // Index of this next hop forwarding entry in L2 FIB table + u16 if_id; +}; + +struct rtl838x_switch_priv; + +struct rtl838x_reg { + void (*mask_port_reg_be)(u64 clear, u64 set, int reg); + void (*set_port_reg_be)(u64 set, int reg); + u64 (*get_port_reg_be)(int reg); + void (*mask_port_reg_le)(u64 clear, u64 set, int reg); + void (*set_port_reg_le)(u64 set, int reg); + u64 (*get_port_reg_le)(int reg); + int stat_port_rst; + int stat_rst; + int stat_port_std_mib; + int (*port_iso_ctrl)(int p); + void (*traffic_enable)(int source, int dest); + void (*traffic_disable)(int source, int dest); + void (*traffic_set)(int source, u64 dest_matrix); + u64 (*traffic_get)(int source); + int l2_ctrl_0; + int l2_ctrl_1; + int l2_port_aging_out; + int smi_poll_ctrl; + int l2_tbl_flush_ctrl; + void (*exec_tbl0_cmd)(u32 cmd); + void (*exec_tbl1_cmd)(u32 cmd); + int (*tbl_access_data_0)(int i); + int isr_glb_src; + int isr_port_link_sts_chg; + int imr_port_link_sts_chg; + int imr_glb; + void (*vlan_tables_read)(u32 vlan, struct rtl838x_vlan_info *info); + void (*vlan_set_tagged)(u32 vlan, struct rtl838x_vlan_info *info); + void (*vlan_set_untagged)(u32 vlan, u64 portmask); + void (*vlan_profile_dump)(int index); + void (*vlan_profile_setup)(int profile); + void (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]); + void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]); + int (*mac_force_mode_ctrl)(int port); + int (*mac_port_ctrl)(int port); + int (*l2_port_new_salrn)(int port); + int (*l2_port_new_sa_fwd)(int port); + int mir_ctrl; + int mir_dpm; + int mir_spm; + int mac_link_sts; + int mac_link_dup_sts; + int (*mac_link_spd_sts)(int port); + int mac_rx_pause_sts; + int mac_tx_pause_sts; + u64 (*read_l2_entry_using_hash)(u32 hash, u32 position, struct rtl838x_l2_entry *e); + void (*write_l2_entry_using_hash)(u32 hash, u32 pos, struct rtl838x_l2_entry *e); + u64 (*read_cam)(int idx, struct rtl838x_l2_entry *e); + void (*write_cam)(int idx, struct rtl838x_l2_entry *e); + int vlan_port_egr_filter; + int vlan_port_igr_filter; + int vlan_port_pb; + int vlan_port_tag_sts_ctrl; + int (*rtl838x_vlan_port_tag_sts_ctrl)(int port); + int (*trk_mbr_ctr)(int group); + int rma_bpdu_fld_pmask; + int spcl_trap_eapol_ctrl; + void (*init_eee)(struct rtl838x_switch_priv *priv, bool enable); + void (*port_eee_set)(struct rtl838x_switch_priv *priv, int port, bool enable); + int (*eee_port_ability)(struct rtl838x_switch_priv *priv, + struct ethtool_eee *e, int port); + u64 (*l2_hash_seed)(u64 mac, u32 vid); + u32 (*l2_hash_key)(struct rtl838x_switch_priv *priv, u64 seed); + u64 (*read_mcast_pmask)(int idx); + void (*write_mcast_pmask)(int idx, u64 portmask); + void (*vlan_fwd_on_inner)(int port, bool is_set); +}; + +struct rtl838x_switch_priv { + /* Switch operation */ + struct dsa_switch *ds; + struct device *dev; + u16 id; + u16 family_id; + char version; + struct rtl838x_port ports[57]; + struct mutex reg_mutex; + int link_state_irq; + int mirror_group_ports[4]; + struct mii_bus *mii_bus; + const struct rtl838x_reg *r; + u8 cpu_port; + u8 port_mask; + u8 port_width; + u64 irq_mask; + u32 fib_entries; + int l2_bucket_size; + struct dentry *dbgfs_dir; + int n_lags; + u64 lags_port_members[MAX_LAGS]; + struct net_device *lag_devs[MAX_LAGS]; + struct notifier_block nb; + bool eee_enabled; + unsigned long int mc_group_bm[MAX_MC_GROUPS >> 5]; +}; + +void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv); + +#endif /* _RTL838X_H */ diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c new file mode 100644 index 0000000000..c62dc441c1 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c @@ -0,0 +1,807 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "rtl83xx.h" + +extern struct mutex smi_lock; +extern struct rtl83xx_soc_info soc_info; + +void rtl839x_print_matrix(void) +{ + volatile u64 *ptr9; + int i; + + ptr9 = RTL838X_SW_BASE + RTL839X_PORT_ISO_CTRL(0); + for (i = 0; i < 52; i += 4) + pr_debug("> %16llx %16llx %16llx %16llx\n", + ptr9[i + 0], ptr9[i + 1], ptr9[i + 2], ptr9[i + 3]); + pr_debug("CPU_PORT> %16llx\n", ptr9[52]); +} + +static inline int rtl839x_port_iso_ctrl(int p) +{ + return RTL839X_PORT_ISO_CTRL(p); +} + +static inline void rtl839x_exec_tbl0_cmd(u32 cmd) +{ + sw_w32(cmd, RTL839X_TBL_ACCESS_CTRL_0); + do { } while (sw_r32(RTL839X_TBL_ACCESS_CTRL_0) & BIT(16)); +} + +static inline void rtl839x_exec_tbl1_cmd(u32 cmd) +{ + sw_w32(cmd, RTL839X_TBL_ACCESS_CTRL_1); + do { } while (sw_r32(RTL839X_TBL_ACCESS_CTRL_1) & BIT(16)); +} + +inline void rtl839x_exec_tbl2_cmd(u32 cmd) +{ + sw_w32(cmd, RTL839X_TBL_ACCESS_CTRL_2); + do { } while (sw_r32(RTL839X_TBL_ACCESS_CTRL_2) & (1 << 9)); +} + +static inline int rtl839x_tbl_access_data_0(int i) +{ + return RTL839X_TBL_ACCESS_DATA_0(i); +} + +static void rtl839x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 u, v, w; + // Read VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 0); + + rtl_table_read(r, vlan); + u = sw_r32(rtl_table_data(r, 0)); + v = sw_r32(rtl_table_data(r, 1)); + w = sw_r32(rtl_table_data(r, 2)); + rtl_table_release(r); + + info->tagged_ports = u; + info->tagged_ports = (info->tagged_ports << 21) | ((v >> 11) & 0x1fffff); + info->profile_id = w >> 30 | ((v & 1) << 2); + info->hash_mc_fid = !!(w & BIT(2)); + info->hash_uc_fid = !!(w & BIT(3)); + info->fid = (v >> 3) & 0xff; + + // Read UNTAG table (0) via table register 1 + r = rtl_table_get(RTL8390_TBL_1, 0); + rtl_table_read(r, vlan); + u = sw_r32(rtl_table_data(r, 0)); + v = sw_r32(rtl_table_data(r, 1)); + rtl_table_release(r); + + info->untagged_ports = u; + info->untagged_ports = (info->untagged_ports << 21) | ((v >> 11) & 0x1fffff); +} + +static void rtl839x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 u, v, w; + // Access VLAN table (0) via register 0 + struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 0); + + u = info->tagged_ports >> 21; + v = info->tagged_ports << 11; + v |= ((u32)info->fid) << 3; + v |= info->hash_uc_fid ? BIT(2) : 0; + v |= info->hash_mc_fid ? BIT(1) : 0; + v |= (info->profile_id & 0x4) ? 1 : 0; + w = ((u32)(info->profile_id & 3)) << 30; + + sw_w32(u, rtl_table_data(r, 0)); + sw_w32(v, rtl_table_data(r, 1)); + sw_w32(w, rtl_table_data(r, 2)); + + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +static void rtl839x_vlan_set_untagged(u32 vlan, u64 portmask) +{ + u32 u, v; + + // Access UNTAG table (0) via table register 1 + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 0); + + u = portmask >> 21; + v = portmask << 11; + + sw_w32(u, rtl_table_data(r, 0)); + sw_w32(v, rtl_table_data(r, 1)); + rtl_table_write(r, vlan); + + rtl_table_release(r); +} + +/* Sets the L2 forwarding to be based on either the inner VLAN tag or the outer + */ +static void rtl839x_vlan_fwd_on_inner(int port, bool is_set) +{ + if (is_set) + rtl839x_mask_port_reg_be(BIT_ULL(port), 0ULL, RTL839X_VLAN_PORT_FWD); + else + rtl839x_mask_port_reg_be(0ULL, BIT_ULL(port), RTL839X_VLAN_PORT_FWD); +} + +/* + * Hash seed is vid (actually rvid) concatenated with the MAC address + */ +static u64 rtl839x_l2_hash_seed(u64 mac, u32 vid) +{ + u64 v = vid; + + v <<= 48; + v |= mac; + + return v; +} + +/* + * Applies the same hash algorithm as the one used currently by the ASIC to the seed + * and returns a key into the L2 hash table + */ +static u32 rtl839x_l2_hash_key(struct rtl838x_switch_priv *priv, u64 seed) +{ + u32 h1, h2, h; + + if (sw_r32(priv->r->l2_ctrl_0) & 1) { + h1 = (u32) (((seed >> 60) & 0x3f) ^ ((seed >> 54) & 0x3f) + ^ ((seed >> 36) & 0x3f) ^ ((seed >> 30) & 0x3f) + ^ ((seed >> 12) & 0x3f) ^ ((seed >> 6) & 0x3f)); + h2 = (u32) (((seed >> 48) & 0x3f) ^ ((seed >> 42) & 0x3f) + ^ ((seed >> 24) & 0x3f) ^ ((seed >> 18) & 0x3f) + ^ (seed & 0x3f)); + h = (h1 << 6) | h2; + } else { + h = (seed >> 60) + ^ ((((seed >> 48) & 0x3f) << 6) | ((seed >> 54) & 0x3f)) + ^ ((seed >> 36) & 0xfff) ^ ((seed >> 24) & 0xfff) + ^ ((seed >> 12) & 0xfff) ^ (seed & 0xfff); + } + + return h; +} + +static inline int rtl839x_mac_force_mode_ctrl(int p) +{ + return RTL839X_MAC_FORCE_MODE_CTRL + (p << 2); +} + +static inline int rtl839x_mac_port_ctrl(int p) +{ + return RTL839X_MAC_PORT_CTRL(p); +} + +static inline int rtl839x_l2_port_new_salrn(int p) +{ + return RTL839X_L2_PORT_NEW_SALRN(p); +} + +static inline int rtl839x_l2_port_new_sa_fwd(int p) +{ + return RTL839X_L2_PORT_NEW_SA_FWD(p); +} + +static inline int rtl839x_mac_link_spd_sts(int p) +{ + return RTL839X_MAC_LINK_SPD_STS(p); +} + +static inline int rtl839x_trk_mbr_ctr(int group) +{ + return RTL839X_TRK_MBR_CTR + (group << 3); +} + +static void rtl839x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) +{ + /* Table contains different entry types, we need to identify the right one: + * Check for MC entries, first + */ + e->is_ip_mc = !!(r[2] & BIT(31)); + e->is_ipv6_mc = !!(r[2] & BIT(30)); + e->type = L2_INVALID; + if (!e->is_ip_mc) { + e->mac[0] = (r[0] >> 12); + e->mac[1] = (r[0] >> 4); + e->mac[2] = ((r[1] >> 28) | (r[0] << 4)); + e->mac[3] = (r[1] >> 20); + e->mac[4] = (r[1] >> 12); + e->mac[5] = (r[1] >> 4); + + /* Is it a unicast entry? check multicast bit */ + if (!(e->mac[0] & 1)) { + e->is_static = !!((r[2] >> 18) & 1); + e->vid = (r[2] >> 4) & 0xfff; + e->rvid = (r[0] >> 20) & 0xfff; + e->port = (r[2] >> 24) & 0x3f; + e->block_da = !!(r[2] & (1 << 19)); + e->block_sa = !!(r[2] & (1 << 20)); + e->suspended = !!(r[2] & (1 << 17)); + e->next_hop = !!(r[2] & (1 << 16)); + if (e->next_hop) + pr_info("Found next hop entry, need to read data\n"); + e->age = (r[2] >> 21) & 3; + e->valid = true; + if (!(r[2] & 0xc0fd0000)) /* Check for valid entry */ + e->valid = false; + else + e->type = L2_UNICAST; + } else { + e->valid = true; + e->type = L2_MULTICAST; + e->mc_portmask_index = (r[2]>>6) & 0xfff; + } + } + if (e->is_ip_mc) { + e->valid = true; + e->type = IP4_MULTICAST; + } + if (e->is_ipv6_mc) { + e->valid = true; + e->type = IP6_MULTICAST; + } +} + +/* + * Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry + */ +static void rtl839x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) +{ + if (!e->valid) { + r[0] = r[1] = r[2] = 0; + return; + } + + r[2] = e->is_ip_mc ? BIT(31) : 0; + r[2] |= e->is_ipv6_mc ? BIT(30) : 0; + + if (!e->is_ip_mc && !e->is_ipv6_mc) { + r[0] = ((u32)e->mac[0]) << 12; + r[0] |= ((u32)e->mac[1]) << 4; + r[0] |= ((u32)e->mac[2]) >> 4; + r[1] = ((u32)e->mac[2]) << 28; + r[1] |= ((u32)e->mac[3]) << 20; + r[1] |= ((u32)e->mac[4]) << 12; + r[1] |= ((u32)e->mac[5]) << 4; + + if (!(e->mac[0] & 1)) { // Not multicast + r[2] |= e->is_static ? BIT(18) : 0; + r[2] |= e->vid << 4; + r[0] |= ((u32)e->rvid) << 20; + r[2] |= e->port << 24; + r[2] |= e->block_da ? BIT(19) : 0; + r[2] |= e->block_sa ? BIT(20) : 0; + r[2] |= e->suspended ? BIT(17) : 0; + if (e->next_hop) { + r[2] |= BIT(16); + r[2] |= e->nh_vlan_target ? BIT(15) : 0; + r[2] |= (e->nh_route_id & 0x7ff) << 4; + } + r[2] |= ((u32)e->age) << 21; + } else { // L2 Multicast + r[0] |= ((u32)e->rvid) << 20; + r[2] |= ((u32)e->mc_portmask_index) << 6; + pr_debug("Write L2 MC entry: %08x %08x %08x\n", r[0], r[1], r[2]); + } + } else { // IPv4 or IPv6 MC entry + r[0] = ((u32)e->rvid) << 20; + r[2] |= ((u32)e->mc_portmask_index) << 6; + r[1] = e->mc_gip; + } +} + +/* + * Read an L2 UC or MC entry out of a hash bucket of the L2 forwarding table + * hash is the id of the bucket and pos is the position of the entry in that bucket + * The data read from the SoC is filled into rtl838x_l2_entry + */ +static u64 rtl839x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 0); + u32 idx = (0 << 14) | (hash << 2) | pos; // Search SRAM, with hash and at pos in bucket + int i; + + rtl_table_read(q, idx); + for (i= 0; i < 3; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl839x_fill_l2_entry(r, e); + if (!e->valid) + return 0; + + return rtl839x_l2_hash_seed(ether_addr_to_u64(&e->mac[0]), e->rvid); +} + +static void rtl839x_write_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 0); + int i; + + u32 idx = (0 << 14) | (hash << 2) | pos; // Access SRAM, with hash and at pos in bucket + + rtl839x_fill_l2_row(r, e); + + for (i= 0; i < 3; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static u64 rtl839x_read_cam(int idx, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 1); // Access L2 Table 1 + int i; + + rtl_table_read(q, idx); + for (i= 0; i < 3; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl839x_fill_l2_entry(r, e); + if (!e->valid) + return 0; + + pr_debug("Found in CAM: R1 %x R2 %x R3 %x\n", r[0], r[1], r[2]); + + // Return MAC with concatenated VID ac concatenated ID + return rtl839x_l2_hash_seed(ether_addr_to_u64(&e->mac[0]), e->rvid); +} + +static void rtl839x_write_cam(int idx, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 1); // Access L2 Table 1 + int i; + + rtl839x_fill_l2_row(r, e); + + for (i= 0; i < 3; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static u64 rtl839x_read_mcast_pmask(int idx) +{ + u64 portmask; + // Read MC_PMSK (2) via register RTL8390_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 2); + + rtl_table_read(q, idx); + portmask = sw_r32(rtl_table_data(q, 0)); + portmask <<= 32; + portmask |= sw_r32(rtl_table_data(q, 1)); + portmask >>= 11; // LSB is bit 11 in data registers + rtl_table_release(q); + + return portmask; +} + +static void rtl839x_write_mcast_pmask(int idx, u64 portmask) +{ + // Access MC_PMSK (2) via register RTL8380_TBL_L2 + struct table_reg *q = rtl_table_get(RTL8390_TBL_L2, 2); + + portmask <<= 11; // LSB is bit 11 in data registers + sw_w32((u32)(portmask >> 32), rtl_table_data(q, 0)); + sw_w32((u32)((portmask & 0xfffff800)), rtl_table_data(q, 1)); + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static void rtl839x_vlan_profile_setup(int profile) +{ + u32 p[2]; + u32 pmask_id = UNKNOWN_MC_PMASK; + + p[0] = pmask_id; // Use portmaks 0xfff for unknown IPv6 MC flooding + // Enable L2 Learning BIT 0, portmask UNKNOWN_MC_PMASK for IP/L2-MC traffic flooding + p[1] = 1 | pmask_id << 1 | pmask_id << 13; + + sw_w32(p[0], RTL839X_VLAN_PROFILE(profile)); + sw_w32(p[1], RTL839X_VLAN_PROFILE(profile) + 4); + + rtl839x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0x001fffffffffffff); +} + +static inline int rtl839x_vlan_port_egr_filter(int port) +{ + return RTL839X_VLAN_PORT_EGR_FLTR(port); +} + +static inline int rtl839x_vlan_port_igr_filter(int port) +{ + return RTL839X_VLAN_PORT_IGR_FLTR(port); +} + +u64 rtl839x_traffic_get(int source) +{ + return rtl839x_get_port_reg_be(rtl839x_port_iso_ctrl(source)); +} + +void rtl839x_traffic_set(int source, u64 dest_matrix) +{ + rtl839x_set_port_reg_be(dest_matrix, rtl839x_port_iso_ctrl(source)); +} + +void rtl839x_traffic_enable(int source, int dest) +{ + rtl839x_mask_port_reg_be(0, BIT_ULL(dest), rtl839x_port_iso_ctrl(source)); +} + +void rtl839x_traffic_disable(int source, int dest) +{ + rtl839x_mask_port_reg_be(BIT_ULL(dest), 0, rtl839x_port_iso_ctrl(source)); +} + +irqreturn_t rtl839x_switch_irq(int irq, void *dev_id) +{ + struct dsa_switch *ds = dev_id; + u32 status = sw_r32(RTL839X_ISR_GLB_SRC); + u64 ports = rtl839x_get_port_reg_le(RTL839X_ISR_PORT_LINK_STS_CHG); + u64 link; + int i; + + /* Clear status */ + rtl839x_set_port_reg_le(ports, RTL839X_ISR_PORT_LINK_STS_CHG); + pr_debug("RTL8390 Link change: status: %x, ports %llx\n", status, ports); + + for (i = 0; i < RTL839X_CPU_PORT; i++) { + if (ports & BIT_ULL(i)) { + link = rtl839x_get_port_reg_le(RTL839X_MAC_LINK_STS); + if (link & BIT_ULL(i)) + dsa_port_phylink_mac_change(ds, i, true); + else + dsa_port_phylink_mac_change(ds, i, false); + } + } + return IRQ_HANDLED; +} + +// TODO: unused +int rtl8390_sds_power(int mac, int val) +{ + u32 offset = (mac == 48) ? 0x0 : 0x100; + u32 mode = val ? 0 : 1; + + pr_debug("In %s: mac %d, set %d\n", __func__, mac, val); + + if ((mac != 48) && (mac != 49)) { + pr_err("%s: not an SFP port: %d\n", __func__, mac); + return -1; + } + + // Set bit 1003. 1000 starts at 7c + sw_w32_mask(BIT(11), mode << 11, RTL839X_SDS12_13_PWR0 + offset); + + return 0; +} + +int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + u32 v; + + if (port > 63 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + + sw_w32_mask(0xffff0000, port << 16, RTL839X_PHYREG_DATA_CTRL); + v = reg << 5 | page << 10 | ((page == 0x1fff) ? 0x1f : 0) << 23; + sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL); + + sw_w32(0x1ff, RTL839X_PHYREG_CTRL); + + v |= 1; + sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL); + + do { + } while (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x1); + + *val = sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff; + + mutex_unlock(&smi_lock); + return 0; +} + +int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + u32 v; + int err = 0; + + val &= 0xffff; + if (port > 63 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + + // Set PHY to access + rtl839x_set_port_reg_le(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL); + + sw_w32_mask(0xffff0000, val << 16, RTL839X_PHYREG_DATA_CTRL); + + v = reg << 5 | page << 10 | ((page == 0x1fff) ? 0x1f : 0) << 23; + sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL); + + sw_w32(0x1ff, RTL839X_PHYREG_CTRL); + + v |= BIT(3) | 1; /* Write operation and execute */ + sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL); + + do { + } while (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x1); + + if (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x2) + err = -EIO; + + mutex_unlock(&smi_lock); + return err; +} + +/* + * Read an mmd register of the PHY + */ +int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val) +{ + int err = 0; + u32 v; + + mutex_lock(&smi_lock); + + // Set PHY to access + sw_w32_mask(0xffff << 16, port << 16, RTL839X_PHYREG_DATA_CTRL); + + // Set MMD device number and register to write to + sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL); + + v = BIT(2) | BIT(0); // MMD-access | EXEC + sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL); + + do { + v = sw_r32(RTL839X_PHYREG_ACCESS_CTRL); + } while (v & BIT(0)); + // There is no error-checking via BIT 1 of v, as it does not seem to be set correctly + *val = (sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff); + pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err); + + mutex_unlock(&smi_lock); + + return err; +} + +/* + * Write to an mmd register of the PHY + */ +int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val) +{ + int err = 0; + u32 v; + + mutex_lock(&smi_lock); + + // Set PHY to access + rtl839x_set_port_reg_le(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL); + + // Set data to write + sw_w32_mask(0xffff << 16, val << 16, RTL839X_PHYREG_DATA_CTRL); + + // Set MMD device number and register to write to + sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL); + + v = BIT(3) | BIT(2) | BIT(0); // WRITE | MMD-access | EXEC + sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL); + + do { + v = sw_r32(RTL839X_PHYREG_ACCESS_CTRL); + } while (v & BIT(0)); + + pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err); + mutex_unlock(&smi_lock); + return err; +} + +void rtl8390_get_version(struct rtl838x_switch_priv *priv) +{ + u32 info; + + sw_w32_mask(0xf << 28, 0xa << 28, RTL839X_CHIP_INFO); + info = sw_r32(RTL839X_CHIP_INFO); + pr_debug("Chip-Info: %x\n", info); + priv->version = RTL8390_VERSION_A; +} + +void rtl839x_vlan_profile_dump(int profile) +{ + u32 p[2]; + + if (profile < 0 || profile > 7) + return; + + p[0] = sw_r32(RTL839X_VLAN_PROFILE(profile)); + p[1] = sw_r32(RTL839X_VLAN_PROFILE(profile) + 4); + + pr_info("VLAN profile %d: L2 learning: %d, UNKN L2MC FLD PMSK %d, \ + UNKN IPMC FLD PMSK %d, UNKN IPv6MC FLD PMSK: %d", + profile, p[1] & 1, (p[1] >> 1) & 0xfff, (p[1] >> 13) & 0xfff, + (p[0]) & 0xfff); + pr_info("VLAN profile %d: raw %08x, %08x\n", profile, p[0], p[1]); +} + +static void rtl839x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 16 /* Execute cmd */ + | 0 << 15 /* Read */ + | 5 << 12 /* Table type 0b101 */ + | (msti & 0xfff); + priv->r->exec_tbl0_cmd(cmd); + + for (i = 0; i < 4; i++) + port_state[i] = sw_r32(priv->r->tbl_access_data_0(i)); +} + +static void rtl839x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 16 /* Execute cmd */ + | 1 << 15 /* Write */ + | 5 << 12 /* Table type 0b101 */ + | (msti & 0xfff); + for (i = 0; i < 4; i++) + sw_w32(port_state[i], priv->r->tbl_access_data_0(i)); + priv->r->exec_tbl0_cmd(cmd); +} + +/* + * Enables or disables the EEE/EEEP capability of a port + */ +void rtl839x_port_eee_set(struct rtl838x_switch_priv *priv, int port, bool enable) +{ + u32 v; + + // This works only for Ethernet ports, and on the RTL839X, ports above 47 are SFP + if (port >= 48) + return; + + enable = true; + pr_debug("In %s: setting port %d to %d\n", __func__, port, enable); + v = enable ? 0xf : 0x0; + + // Set EEE for 100, 500, 1000MBit and 10GBit + sw_w32_mask(0xf << 8, v << 8, rtl839x_mac_force_mode_ctrl(port)); + + // Set TX/RX EEE state + v = enable ? 0x3 : 0x0; + sw_w32(v, RTL839X_EEE_CTRL(port)); + + priv->ports[port].eee_enabled = enable; +} + +/* + * Get EEE own capabilities and negotiation result + */ +int rtl839x_eee_port_ability(struct rtl838x_switch_priv *priv, struct ethtool_eee *e, int port) +{ + u64 link, a; + + if (port >= 48) + return 0; + + link = rtl839x_get_port_reg_le(RTL839X_MAC_LINK_STS); + if (!(link & BIT_ULL(port))) + return 0; + + if (sw_r32(rtl839x_mac_force_mode_ctrl(port)) & BIT(8)) + e->advertised |= ADVERTISED_100baseT_Full; + + if (sw_r32(rtl839x_mac_force_mode_ctrl(port)) & BIT(10)) + e->advertised |= ADVERTISED_1000baseT_Full; + + a = rtl839x_get_port_reg_le(RTL839X_MAC_EEE_ABLTY); + pr_info("Link partner: %016llx\n", a); + if (rtl839x_get_port_reg_le(RTL839X_MAC_EEE_ABLTY) & BIT_ULL(port)) { + e->lp_advertised = ADVERTISED_100baseT_Full; + e->lp_advertised |= ADVERTISED_1000baseT_Full; + return 1; + } + + return 0; +} + +static void rtl839x_init_eee(struct rtl838x_switch_priv *priv, bool enable) +{ + int i; + + pr_info("Setting up EEE, state: %d\n", enable); + + // Set wake timer for TX and pause timer both to 0x21 + sw_w32_mask(0xff << 20| 0xff, 0x21 << 20| 0x21, RTL839X_EEE_TX_TIMER_GELITE_CTRL); + // Set pause wake timer for GIGA-EEE to 0x11 + sw_w32_mask(0xff << 20, 0x11 << 20, RTL839X_EEE_TX_TIMER_GIGA_CTRL); + // Set pause wake timer for 10GBit ports to 0x11 + sw_w32_mask(0xff << 20, 0x11 << 20, RTL839X_EEE_TX_TIMER_10G_CTRL); + + // Setup EEE on all ports + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) + rtl839x_port_eee_set(priv, i, enable); + } + priv->eee_enabled = enable; +} + +const struct rtl838x_reg rtl839x_reg = { + .mask_port_reg_be = rtl839x_mask_port_reg_be, + .set_port_reg_be = rtl839x_set_port_reg_be, + .get_port_reg_be = rtl839x_get_port_reg_be, + .mask_port_reg_le = rtl839x_mask_port_reg_le, + .set_port_reg_le = rtl839x_set_port_reg_le, + .get_port_reg_le = rtl839x_get_port_reg_le, + .stat_port_rst = RTL839X_STAT_PORT_RST, + .stat_rst = RTL839X_STAT_RST, + .stat_port_std_mib = RTL839X_STAT_PORT_STD_MIB, + .traffic_enable = rtl839x_traffic_enable, + .traffic_disable = rtl839x_traffic_disable, + .traffic_get = rtl839x_traffic_get, + .traffic_set = rtl839x_traffic_set, + .port_iso_ctrl = rtl839x_port_iso_ctrl, + .l2_ctrl_0 = RTL839X_L2_CTRL_0, + .l2_ctrl_1 = RTL839X_L2_CTRL_1, + .l2_port_aging_out = RTL839X_L2_PORT_AGING_OUT, + .smi_poll_ctrl = RTL839X_SMI_PORT_POLLING_CTRL, + .l2_tbl_flush_ctrl = RTL839X_L2_TBL_FLUSH_CTRL, + .exec_tbl0_cmd = rtl839x_exec_tbl0_cmd, + .exec_tbl1_cmd = rtl839x_exec_tbl1_cmd, + .tbl_access_data_0 = rtl839x_tbl_access_data_0, + .isr_glb_src = RTL839X_ISR_GLB_SRC, + .isr_port_link_sts_chg = RTL839X_ISR_PORT_LINK_STS_CHG, + .imr_port_link_sts_chg = RTL839X_IMR_PORT_LINK_STS_CHG, + .imr_glb = RTL839X_IMR_GLB, + .vlan_tables_read = rtl839x_vlan_tables_read, + .vlan_set_tagged = rtl839x_vlan_set_tagged, + .vlan_set_untagged = rtl839x_vlan_set_untagged, + .vlan_profile_dump = rtl839x_vlan_profile_dump, + .vlan_profile_setup = rtl839x_vlan_profile_setup, + .vlan_fwd_on_inner = rtl839x_vlan_fwd_on_inner, + .stp_get = rtl839x_stp_get, + .stp_set = rtl839x_stp_set, + .mac_force_mode_ctrl = rtl839x_mac_force_mode_ctrl, + .mac_port_ctrl = rtl839x_mac_port_ctrl, + .l2_port_new_salrn = rtl839x_l2_port_new_salrn, + .l2_port_new_sa_fwd = rtl839x_l2_port_new_sa_fwd, + .mir_ctrl = RTL839X_MIR_CTRL, + .mir_dpm = RTL839X_MIR_DPM_CTRL, + .mir_spm = RTL839X_MIR_SPM_CTRL, + .mac_link_sts = RTL839X_MAC_LINK_STS, + .mac_link_dup_sts = RTL839X_MAC_LINK_DUP_STS, + .mac_link_spd_sts = rtl839x_mac_link_spd_sts, + .mac_rx_pause_sts = RTL839X_MAC_RX_PAUSE_STS, + .mac_tx_pause_sts = RTL839X_MAC_TX_PAUSE_STS, + .read_l2_entry_using_hash = rtl839x_read_l2_entry_using_hash, + .write_l2_entry_using_hash = rtl839x_write_l2_entry_using_hash, + .read_cam = rtl839x_read_cam, + .write_cam = rtl839x_write_cam, + .vlan_port_egr_filter = RTL839X_VLAN_PORT_EGR_FLTR(0), + .vlan_port_igr_filter = RTL839X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_pb = RTL839X_VLAN_PORT_PB_VLAN, + .vlan_port_tag_sts_ctrl = RTL839X_VLAN_PORT_TAG_STS_CTRL, + .trk_mbr_ctr = rtl839x_trk_mbr_ctr, + .rma_bpdu_fld_pmask = RTL839X_RMA_BPDU_FLD_PMSK, + .spcl_trap_eapol_ctrl = RTL839X_SPCL_TRAP_EAPOL_CTRL, + .init_eee = rtl839x_init_eee, + .port_eee_set = rtl839x_port_eee_set, + .eee_port_ability = rtl839x_eee_port_ability, + .l2_hash_seed = rtl839x_l2_hash_seed, + .l2_hash_key = rtl839x_l2_hash_key, + .read_mcast_pmask = rtl839x_read_mcast_pmask, + .write_mcast_pmask = rtl839x_write_mcast_pmask, +}; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h new file mode 100644 index 0000000000..fd0455a6cd --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _NET_DSA_RTL83XX_H +#define _NET_DSA_RTL83XX_H + +#include +#include "rtl838x.h" + + +#define RTL8380_VERSION_A 'A' +#define RTL8390_VERSION_A 'A' +#define RTL8380_VERSION_B 'B' + +struct fdb_update_work { + struct work_struct work; + struct net_device *ndev; + u64 macs[]; +}; + +#define MIB_DESC(_size, _offset, _name) {.size = _size, .offset = _offset, .name = _name} +struct rtl83xx_mib_desc { + unsigned int size; + unsigned int offset; + const char *name; +}; + +/* API for switch table access */ +struct table_reg { + u16 addr; + u16 data; + u8 max_data; + u8 c_bit; + u8 t_bit; + u8 rmode; + u8 tbl; + struct mutex lock; +}; + +#define TBL_DESC(_addr, _data, _max_data, _c_bit, _t_bit, _rmode) \ + { .addr = _addr, .data = _data, .max_data = _max_data, .c_bit = _c_bit, \ + .t_bit = _t_bit, .rmode = _rmode \ + } + +typedef enum { + RTL8380_TBL_L2 = 0, + RTL8380_TBL_0, + RTL8380_TBL_1, + RTL8390_TBL_L2, + RTL8390_TBL_0, + RTL8390_TBL_1, + RTL8390_TBL_2, + RTL9300_TBL_L2, + RTL9300_TBL_0, + RTL9300_TBL_1, + RTL9300_TBL_2, + RTL9300_TBL_HSB, + RTL9300_TBL_HSA, + RTL9310_TBL_0, + RTL9310_TBL_1, + RTL9310_TBL_2, + RTL9310_TBL_3, + RTL9310_TBL_4, + RTL9310_TBL_5, + RTL_TBL_END +} rtl838x_tbl_reg_t; + +void rtl_table_init(void); +struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t); +void rtl_table_release(struct table_reg *r); +void rtl_table_read(struct table_reg *r, int idx); +void rtl_table_write(struct table_reg *r, int idx); +inline u16 rtl_table_data(struct table_reg *r, int i); +inline u32 rtl_table_data_r(struct table_reg *r, int i); +inline void rtl_table_data_w(struct table_reg *r, u32 v, int i); + +void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv); +int read_phy(u32 port, u32 page, u32 reg, u32 *val); +int write_phy(u32 port, u32 page, u32 reg, u32 val); + +/* Port register accessor functions for the RTL839x and RTL931X SoCs */ +void rtl839x_mask_port_reg_be(u64 clear, u64 set, int reg); +u64 rtl839x_get_port_reg_be(int reg); +void rtl839x_set_port_reg_be(u64 set, int reg); +void rtl839x_mask_port_reg_le(u64 clear, u64 set, int reg); +void rtl839x_set_port_reg_le(u64 set, int reg); +u64 rtl839x_get_port_reg_le(int reg); + +/* Port register accessor functions for the RTL838x and RTL930X SoCs */ +void rtl838x_mask_port_reg(u64 clear, u64 set, int reg); +void rtl838x_set_port_reg(u64 set, int reg); +u64 rtl838x_get_port_reg(int reg); + +/* RTL838x-specific */ +u32 rtl838x_hash(struct rtl838x_switch_priv *priv, u64 seed); +irqreturn_t rtl838x_switch_irq(int irq, void *dev_id); +void rtl8380_get_version(struct rtl838x_switch_priv *priv); +void rtl838x_vlan_profile_dump(int index); +int rtl83xx_dsa_phy_read(struct dsa_switch *ds, int phy_addr, int phy_reg); +void rtl8380_sds_rst(int mac); +int rtl8380_sds_power(int mac, int val); +void rtl838x_print_matrix(void); + +/* RTL839x-specific */ +u32 rtl839x_hash(struct rtl838x_switch_priv *priv, u64 seed); +irqreturn_t rtl839x_switch_irq(int irq, void *dev_id); +void rtl8390_get_version(struct rtl838x_switch_priv *priv); +void rtl839x_vlan_profile_dump(int index); +int rtl83xx_dsa_phy_write(struct dsa_switch *ds, int phy_addr, int phy_reg, u16 val); +void rtl839x_exec_tbl2_cmd(u32 cmd); +void rtl839x_print_matrix(void); + +/* RTL930x-specific */ +u32 rtl930x_hash(struct rtl838x_switch_priv *priv, u64 seed); +irqreturn_t rtl930x_switch_irq(int irq, void *dev_id); +irqreturn_t rtl839x_switch_irq(int irq, void *dev_id); +void rtl930x_vlan_profile_dump(int index); +int rtl9300_sds_power(int mac, int val); +void rtl9300_sds_rst(int sds_num, u32 mode); +void rtl930x_print_matrix(void); + +/* RTL931x-specific */ +irqreturn_t rtl931x_switch_irq(int irq, void *dev_id); + +#endif /* _NET_DSA_RTL83XX_H */ + 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 new file mode 100644 index 0000000000..f1de39f0bc --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c @@ -0,0 +1,1039 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "rtl83xx.h" + +extern struct mutex smi_lock; +extern struct rtl83xx_soc_info soc_info; + +void rtl930x_print_matrix(void) +{ + int i; + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6); + + for (i = 0; i < 29; i++) { + rtl_table_read(r, i); + pr_debug("> %08x\n", sw_r32(rtl_table_data(r, 0))); + } + rtl_table_release(r); +} + +inline void rtl930x_exec_tbl0_cmd(u32 cmd) +{ + sw_w32(cmd, RTL930X_TBL_ACCESS_CTRL_0); + do { } while (sw_r32(RTL930X_TBL_ACCESS_CTRL_0) & (1 << 17)); +} + +inline void rtl930x_exec_tbl1_cmd(u32 cmd) +{ + sw_w32(cmd, RTL930X_TBL_ACCESS_CTRL_1); + do { } while (sw_r32(RTL930X_TBL_ACCESS_CTRL_1) & (1 << 17)); +} + +inline int rtl930x_tbl_access_data_0(int i) +{ + return RTL930X_TBL_ACCESS_DATA_0(i); +} + +static inline int rtl930x_l2_port_new_salrn(int p) +{ + return RTL930X_L2_PORT_SALRN(p); +} + +static inline int rtl930x_l2_port_new_sa_fwd(int p) +{ + // TODO: The definition of the fields changed, because of the master-cpu in a stack + return RTL930X_L2_PORT_NEW_SA_FWD(p); +} + +inline static int rtl930x_trk_mbr_ctr(int group) +{ + return RTL930X_TRK_MBR_CTRL + (group << 2); +} + +static void rtl930x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 v, w; + // Read VLAN table (1) via register 0 + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 1); + + rtl_table_read(r, vlan); + v = sw_r32(rtl_table_data(r, 0)); + w = sw_r32(rtl_table_data(r, 1)); + pr_debug("VLAN_READ %d: %08x %08x\n", vlan, v, w); + rtl_table_release(r); + + info->tagged_ports = v >> 3; + info->profile_id = (w >> 24) & 7; + info->hash_mc_fid = !!(w & BIT(27)); + info->hash_uc_fid = !!(w & BIT(28)); + info->fid = ((v & 0x7) << 3) | ((w >> 29) & 0x7); + + // Read UNTAG table via table register 2 + r = rtl_table_get(RTL9300_TBL_2, 0); + rtl_table_read(r, vlan); + v = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); + + info->untagged_ports = v >> 3; +} + +static void rtl930x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 v, w; + // Access VLAN table (1) via register 0 + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 1); + + v = info->tagged_ports << 3; + v |= ((u32)info->fid) >> 3; + + w = ((u32)info->fid) << 29; + w |= info->hash_mc_fid ? BIT(27) : 0; + w |= info->hash_uc_fid ? BIT(28) : 0; + w |= info->profile_id << 24; + + sw_w32(v, rtl_table_data(r, 0)); + sw_w32(w, rtl_table_data(r, 1)); + + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +void rtl930x_vlan_profile_dump(int profile) +{ + u32 p[5]; + + if (profile < 0 || profile > 7) + return; + + p[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile)); + p[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 4); + p[2] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 8) & 0x1FFFFFFF; + p[3] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 12) & 0x1FFFFFFF; + p[4] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 16) & 0x1FFFFFFF; + + pr_info("VLAN %d: L2 learn: %d; Unknown MC PMasks: L2 %0x, IPv4 %0x, IPv6: %0x", + profile, p[0] & (3 << 21), p[2], p[3], p[4]); + pr_info(" Routing enabled: IPv4 UC %c, IPv6 UC %c, IPv4 MC %c, IPv6 MC %c\n", + p[0] & BIT(17) ? 'y' : 'n', p[0] & BIT(16) ? 'y' : 'n', + p[0] & BIT(13) ? 'y' : 'n', p[0] & BIT(12) ? 'y' : 'n'); + pr_info(" Bridge enabled: IPv4 MC %c, IPv6 MC %c,\n", + p[0] & BIT(15) ? 'y' : 'n', p[0] & BIT(14) ? 'y' : 'n'); + pr_info("VLAN profile %d: raw %08x %08x %08x %08x %08x\n", + profile, p[0], p[1], p[2], p[3], p[4]); +} + +static void rtl930x_vlan_set_untagged(u32 vlan, u64 portmask) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_2, 0); + + sw_w32(portmask << 3, rtl_table_data(r, 0)); + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +/* Sets the L2 forwarding to be based on either the inner VLAN tag or the outer + */ +static void rtl930x_vlan_fwd_on_inner(int port, bool is_set) +{ + // Always set all tag modes to fwd based on either inner or outer tag + if (is_set) + sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0xf, 0, RTL930X_VLAN_PORT_FWD + (port << 2)); +} + +static void rtl930x_vlan_profile_setup(int profile) +{ + u32 p[5]; + + pr_info("In %s\n", __func__); + p[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile)); + p[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 4); + + // Enable routing of Ipv4/6 Unicast and IPv4/6 Multicast traffic + p[0] |= BIT(17) | BIT(16) | BIT(13) | BIT(12); + p[2] = 0x1fffffff; // L2 unknown MC flooding portmask all ports, including the CPU-port + p[3] = 0x1fffffff; // IPv4 unknown MC flooding portmask + p[4] = 0x1fffffff; // IPv6 unknown MC flooding portmask + + sw_w32(p[0], RTL930X_VLAN_PROFILE_SET(profile)); + sw_w32(p[1], RTL930X_VLAN_PROFILE_SET(profile) + 4); + sw_w32(p[2], RTL930X_VLAN_PROFILE_SET(profile) + 8); + sw_w32(p[3], RTL930X_VLAN_PROFILE_SET(profile) + 12); + sw_w32(p[4], RTL930X_VLAN_PROFILE_SET(profile) + 16); + pr_info("Leaving %s\n", __func__); +} + +static void rtl930x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 17 /* Execute cmd */ + | 0 << 16 /* Read */ + | 4 << 12 /* Table type 0b10 */ + | (msti & 0xfff); + priv->r->exec_tbl0_cmd(cmd); + + for (i = 0; i < 2; i++) + port_state[i] = sw_r32(RTL930X_TBL_ACCESS_DATA_0(i)); + pr_debug("MSTI: %d STATE: %08x, %08x\n", msti, port_state[0], port_state[1]); +} + +static void rtl930x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 17 /* Execute cmd */ + | 1 << 16 /* Write */ + | 4 << 12 /* Table type 4 */ + | (msti & 0xfff); + + for (i = 0; i < 2; i++) + sw_w32(port_state[i], RTL930X_TBL_ACCESS_DATA_0(i)); + priv->r->exec_tbl0_cmd(cmd); +} + +static inline int rtl930x_mac_force_mode_ctrl(int p) +{ + return RTL930X_MAC_FORCE_MODE_CTRL + (p << 2); +} + +static inline int rtl930x_mac_port_ctrl(int p) +{ + return RTL930X_MAC_L2_PORT_CTRL(p); +} + +static inline int rtl930x_mac_link_spd_sts(int p) +{ + return RTL930X_MAC_LINK_SPD_STS(p); +} + +static u64 rtl930x_l2_hash_seed(u64 mac, u32 vid) +{ + u64 v = vid; + + v <<= 48; + v |= mac; + + return v; +} + +/* + * Calculate both the block 0 and the block 1 hash by applyingthe same hash + * algorithm as the one used currently by the ASIC to the seed, and return + * both hashes in the lower and higher word of the return value since only 12 bit of + * the hash are significant + */ +static u32 rtl930x_l2_hash_key(struct rtl838x_switch_priv *priv, u64 seed) +{ + u32 k0, k1, h1, h2, h; + + k0 = (u32) (((seed >> 55) & 0x1f) ^ ((seed >> 44) & 0x7ff) + ^ ((seed >> 33) & 0x7ff) ^ ((seed >> 22) & 0x7ff) + ^ ((seed >> 11) & 0x7ff) ^ (seed & 0x7ff)); + + h1 = (seed >> 11) & 0x7ff; + h1 = ((h1 & 0x1f) << 6) | ((h1 >> 5) & 0x3f); + + h2 = (seed >> 33) & 0x7ff; + h2 = ((h2 & 0x3f) << 5)| ((h2 >> 6) & 0x3f); + + k1 = (u32) (((seed << 55) & 0x1f) ^ ((seed >> 44) & 0x7ff) ^ h2 + ^ ((seed >> 22) & 0x7ff) ^ h1 + ^ (seed & 0x7ff)); + + // Algorithm choice for block 0 + if (sw_r32(RTL930X_L2_CTRL) & BIT(0)) + h = k1; + else + h = k0; + + /* Algorithm choice for block 1 + * Since k0 and k1 are < 2048, adding 2048 will offset the hash into the second + * half of hash-space + * 2048 is in fact the hash-table size 16384 divided by 4 hashes per bucket + * divided by 2 to divide the hash space in 2 + */ + if (sw_r32(RTL930X_L2_CTRL) & BIT(1)) + h |= (k1 + 2048) << 16; + else + h |= (k0 + 2048) << 16; + + return h; +} + +/* + * Fills an L2 entry structure from the SoC registers + */ +static void rtl930x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) +{ + pr_debug("In %s valid?\n", __func__); + e->valid = !!(r[2] & BIT(31)); + if (!e->valid) + return; + + pr_debug("In %s is valid\n", __func__); + e->is_ip_mc = false; + e->is_ipv6_mc = false; + + // TODO: Is there not a function to copy directly MAC memory? + e->mac[0] = (r[0] >> 24); + e->mac[1] = (r[0] >> 16); + e->mac[2] = (r[0] >> 8); + e->mac[3] = r[0]; + e->mac[4] = (r[1] >> 24); + e->mac[5] = (r[1] >> 16); + + e->next_hop = !!(r[2] & BIT(12)); + e->rvid = r[1] & 0xfff; + + /* Is it a unicast entry? check multicast bit */ + if (!(e->mac[0] & 1)) { + e->type = L2_UNICAST; + e->is_static = !!(r[2] & BIT(14)); + e->port = (r[2] >> 20) & 0x3ff; + // Check for trunk port + if (r[2] & BIT(30)) { + e->is_trunk = true; + e->stack_dev = (e->port >> 9) & 1; + e->trunk = e->port & 0x3f; + } else { + e->is_trunk = false; + e->stack_dev = (e->port >> 6) & 0xf; + e->port = e->port & 0x3f; + } + + e->block_da = !!(r[2] & BIT(15)); + e->block_sa = !!(r[2] & BIT(16)); + e->suspended = !!(r[2] & BIT(13)); + e->age = (r[2] >> 17) & 3; + e->valid = true; + // the UC_VID field in hardware is used for the VID or for the route id + if (e->next_hop) { + e->nh_route_id = r[2] & 0xfff; + e->vid = 0; + } else { + e->vid = r[2] & 0xfff; + e->nh_route_id = 0; + } + } else { + e->valid = true; + e->type = L2_MULTICAST; + e->mc_portmask_index = (r[2] >> 16) & 0x3ff; + } +} + +/* + * Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry + */ +static void rtl930x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) +{ + u32 port; + + if (!e->valid) { + r[0] = r[1] = r[2] = 0; + return; + } + + r[2] = BIT(31); // Set valid bit + + r[0] = ((u32)e->mac[0]) << 24 | ((u32)e->mac[1]) << 16 + | ((u32)e->mac[2]) << 8 | ((u32)e->mac[3]); + r[1] = ((u32)e->mac[4]) << 24 | ((u32)e->mac[5]) << 16; + + r[2] |= e->next_hop ? BIT(12) : 0; + + if (e->type == L2_UNICAST) { + r[2] |= e->is_static ? BIT(14) : 0; + r[1] |= e->rvid & 0xfff; + r[2] |= (e->port & 0x3ff) << 20; + if (e->is_trunk) { + r[2] |= BIT(30); + port = e->stack_dev << 9 | (e->port & 0x3f); + } else { + port = (e->stack_dev & 0xf) << 6; + port |= e->port & 0x3f; + } + r[2] |= port << 20; + r[2] |= e->block_da ? BIT(15) : 0; + r[2] |= e->block_sa ? BIT(17) : 0; + r[2] |= e->suspended ? BIT(13) : 0; + r[2] |= (e->age & 0x3) << 17; + // the UC_VID field in hardware is used for the VID or for the route id + if (e->next_hop) + r[2] |= e->nh_route_id & 0xfff; + else + r[2] |= e->vid & 0xfff; + } else { // L2_MULTICAST + r[2] |= (e->mc_portmask_index & 0x3ff) << 16; + r[2] |= e->mc_mac_index & 0x7ff; + } +} + +/* + * Read an L2 UC or MC entry out of a hash bucket of the L2 forwarding table + * hash is the id of the bucket and pos is the position of the entry in that bucket + * The data read from the SoC is filled into rtl838x_l2_entry + */ +static u64 rtl930x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 0); + u32 idx; + int i; + u64 mac; + u64 seed; + + pr_debug("%s: hash %08x, pos: %d\n", __func__, hash, pos); + + /* On the RTL93xx, 2 different hash algorithms are used making it a total of + * 8 buckets that need to be searched, 4 for each hash-half + * Use second hash space when bucket is between 4 and 8 */ + if (pos >= 4) { + pos -= 4; + hash >>= 16; + } else { + hash &= 0xffff; + } + + idx = (0 << 14) | (hash << 2) | pos; // Search SRAM, with hash and at pos in bucket + pr_debug("%s: NOW hash %08x, pos: %d\n", __func__, hash, pos); + + rtl_table_read(q, idx); + for (i = 0; i < 3; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl930x_fill_l2_entry(r, e); + + pr_debug("%s: valid: %d, nh: %d\n", __func__, e->valid, e->next_hop); + if (!e->valid) + return 0; + + mac = ((u64)e->mac[0]) << 40 | ((u64)e->mac[1]) << 32 | ((u64)e->mac[2]) << 24 + | ((u64)e->mac[3]) << 16 | ((u64)e->mac[4]) << 8 | ((u64)e->mac[5]); + + seed = rtl930x_l2_hash_seed(mac, e->rvid); + pr_debug("%s: mac %016llx, seed %016llx\n", __func__, mac, seed); + // return vid with concatenated mac as unique id + return seed; +} + +static void rtl930x_write_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 0); + u32 idx = (0 << 14) | (hash << 2) | pos; // Access SRAM, with hash and at pos in bucket + int i; + + pr_info("%s: hash %d, pos %d\n", __func__, hash, pos); + pr_info("%s: index %d -> mac %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, idx, + e->mac[0], e->mac[1], e->mac[2], e->mac[3],e->mac[4],e->mac[5]); + + rtl930x_fill_l2_row(r, e); + + for (i= 0; i < 3; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static u64 rtl930x_read_cam(int idx, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 1); + int i; + + rtl_table_read(q, idx); + for (i= 0; i < 3; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl930x_fill_l2_entry(r, e); + if (!e->valid) + return 0; + + // return mac with concatenated vid as unique id + return ((u64)r[0] << 28) | ((r[1] & 0xffff0000) >> 4) | e->vid; +} + +static void rtl930x_write_cam(int idx, struct rtl838x_l2_entry *e) +{ + u32 r[3]; + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 1); // Access L2 Table 1 + int i; + + rtl930x_fill_l2_row(r, e); + + for (i= 0; i < 3; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); +} + +static void dump_l2_entry(struct rtl838x_l2_entry *e) +{ + pr_info("MAC: %02x:%02x:%02x:%02x:%02x:%02x vid: %d, rvid: %d, port: %d, valid: %d\n", + e->mac[0], e->mac[1], e->mac[2], e->mac[3], e->mac[4], e->mac[5], + e->vid, e->rvid, e->port, e->valid); + pr_info("Type: %d, is_static: %d, is_ip_mc: %d, is_ipv6_mc: %d, block_da: %d\n", + e->type, e->is_static, e->is_ip_mc, e->is_ipv6_mc, e->block_da); + pr_info(" block_sa: %d, suspended: %d, next_hop: %d, age: %d, is_trunk: %d, trunk: %d\n", + e->block_sa, e->suspended, e->next_hop, e->age, e->is_trunk, e->trunk); + if (e->is_ip_mc || e->is_ipv6_mc) + pr_info(" mc_portmask_index: %d, mc_gip: %d, mc_sip: %d\n", + e->mc_portmask_index, e->mc_gip, e->mc_sip); + pr_info(" stac_dev: %d, nh_route_id: %d, port: %d, dev_id\n", + e->stack_dev, e->nh_route_id, e->port); +} + +/* + * Add an L2 nexthop entry for the L3 routing system in the SoC + * Use VID and MAC in rtl838x_l2_entry to identify either a free slot in the L2 hash table + * or mark an existing entry as a nexthop by setting it's nexthop bit + * Called from the L3 layer + * The index in the L2 hash table is filled into nh->l2_id; + */ +static int rtl930x_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl838x_nexthop *nh) +{ + struct rtl838x_l2_entry e; + u64 seed = rtl930x_l2_hash_seed(nh->mac, nh->vid); + u32 key = rtl930x_l2_hash_key(priv, seed); + int i, idx = -1; + u64 entry; + + pr_info("%s searching for %08llx vid %d with key %d, seed: %016llx\n", + __func__, nh->mac, nh->vid, key, seed); + + e.type = L2_UNICAST; + e.rvid = nh->fid; // Verify its the forwarding ID!!! l2_entry.un.unicast.fid + u64_to_ether_addr(nh->mac, &e.mac[0]); + e.port = RTL930X_PORT_IGNORE; + + // Loop over all entries in the hash-bucket and over the second block on 93xx SoCs + for (i = 0; i < priv->l2_bucket_size; i++) { + entry = rtl930x_read_l2_entry_using_hash(key, i, &e); + pr_info("%s i: %d, entry %016llx, seed %016llx\n", __func__, i, entry, seed); + if (e.valid && e.next_hop) + continue; + if (!e.valid || ((entry & 0x0fffffffffffffffULL) == seed)) { + idx = i > 3 ? ((key >> 14) & 0xffff) | i >> 1 + : ((key << 2) | i) & 0xffff; + break; + } + } + + pr_info("%s: found idx %d and i %d\n", __func__, idx, i); + + if (idx < 0) { + pr_err("%s: No more L2 forwarding entries available\n", __func__); + return -1; + } + + // Found an existing or empty entry, make it a nexthop entry + pr_info("%s BEFORE -> key %d, pos: %d, index: %d\n", __func__, key, i, idx); + dump_l2_entry(&e); + nh->l2_id = idx; + + // Found an existing (e->valid is true) or empty entry, make it a nexthop entry + if (e.valid) { + nh->port = e.port; + nh->fid = e.rvid; + nh->vid = e.vid; + nh->dev_id = e.stack_dev; + } else { + e.valid = true; + e.is_static = false; + e.vid = nh->vid; + e.rvid = nh->fid; + e.port = RTL930X_PORT_IGNORE; + u64_to_ether_addr(nh->mac, &e.mac[0]); + } + e.next_hop = true; + // For nexthop entries, the vid field in the table is used to denote the dest mac_id + e.nh_route_id = nh->mac_id; + pr_info("%s AFTER\n", __func__); + dump_l2_entry(&e); + + rtl930x_write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); + + // _dal_longan_l2_nexthop_add + return 0; +} + +static u64 rtl930x_read_mcast_pmask(int idx) +{ + u32 portmask; + // Read MC_PORTMASK (2) via register RTL9300_TBL_L2 + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 2); + + rtl_table_read(q, idx); + portmask = sw_r32(rtl_table_data(q, 0)); + portmask >>= 3; + rtl_table_release(q); + + pr_debug("%s: Index idx %d has portmask %08x\n", __func__, idx, portmask); + return portmask; +} + +static void rtl930x_write_mcast_pmask(int idx, u64 portmask) +{ + u32 pm = portmask; + + // Access MC_PORTMASK (2) via register RTL9300_TBL_L2 + struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 2); + + pr_debug("%s: Index idx %d has portmask %08x\n", __func__, idx, pm); + pm <<= 3; + sw_w32(pm, rtl_table_data(q, 0)); + rtl_table_write(q, idx); + rtl_table_release(q); +} + +u64 rtl930x_traffic_get(int source) +{ + u32 v; + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6); + + rtl_table_read(r, source); + v = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); + return v >> 3; +} + +/* + * Enable traffic between a source port and a destination port matrix + */ +void rtl930x_traffic_set(int source, u64 dest_matrix) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6); + + sw_w32((dest_matrix << 3), rtl_table_data(r, 0)); + rtl_table_write(r, source); + rtl_table_release(r); +} + +void rtl930x_traffic_enable(int source, int dest) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6); + rtl_table_read(r, source); + sw_w32_mask(0, BIT(dest + 3), rtl_table_data(r, 0)); + rtl_table_write(r, source); + rtl_table_release(r); +} + +void rtl930x_traffic_disable(int source, int dest) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6); + rtl_table_read(r, source); + sw_w32_mask(BIT(dest + 3), 0, rtl_table_data(r, 0)); + rtl_table_write(r, source); + rtl_table_release(r); +} + +void rtl9300_dump_debug(void) +{ + int i; + u16 r = RTL930X_STAT_PRVTE_DROP_COUNTER0; + + for (i = 0; i < 10; i ++) { + pr_info("# %d %08x %08x %08x %08x %08x %08x %08x %08x\n", i * 8, + sw_r32(r), sw_r32(r + 4), sw_r32(r + 8), sw_r32(r + 12), + sw_r32(r + 16), sw_r32(r + 20), sw_r32(r + 24), sw_r32(r + 28)); + r += 32; + } + pr_info("# %08x %08x %08x %08x %08x\n", + sw_r32(r), sw_r32(r + 4), sw_r32(r + 8), sw_r32(r + 12), sw_r32(r + 16)); + rtl930x_print_matrix(); + pr_info("RTL930X_L2_PORT_SABLK_CTRL: %08x, RTL930X_L2_PORT_DABLK_CTRL %08x\n", + sw_r32(RTL930X_L2_PORT_SABLK_CTRL), sw_r32(RTL930X_L2_PORT_DABLK_CTRL) + + ); +} + +irqreturn_t rtl930x_switch_irq(int irq, void *dev_id) +{ + struct dsa_switch *ds = dev_id; + u32 status = sw_r32(RTL930X_ISR_GLB); + u32 ports = sw_r32(RTL930X_ISR_PORT_LINK_STS_CHG); + u32 link; + int i; + + /* Clear status */ + sw_w32(ports, RTL930X_ISR_PORT_LINK_STS_CHG); + pr_info("RTL9300 Link change: status: %x, ports %x\n", status, ports); + + rtl9300_dump_debug(); + + for (i = 0; i < 28; i++) { + if (ports & BIT(i)) { + /* Read the register twice because of issues with latency at least + * with the external RTL8226 PHY on the XGS1210 */ + link = sw_r32(RTL930X_MAC_LINK_STS); + link = sw_r32(RTL930X_MAC_LINK_STS); + if (link & BIT(i)) + dsa_port_phylink_mac_change(ds, i, true); + else + dsa_port_phylink_mac_change(ds, i, false); + } + } + + return IRQ_HANDLED; +} + +int rtl9300_sds_power(int mac, int val) +{ + int sds_num; + u32 mode; + + // TODO: these numbers are hard-coded for the Zyxel XGS1210 12 Switch + pr_info("SerDes: %s %d\n", __func__, mac); + switch (mac) { + case 24: + sds_num = 6; + mode = 0x12; // HISGMII + break; + case 25: + sds_num = 7; + mode = 0x12; // HISGMII + break; + case 26: + sds_num = 8; + mode = 0x1b; // 10GR/1000BX auto + break; + case 27: + sds_num = 9; + mode = 0x1b; // 10GR/1000BX auto + break; + default: + return -1; + } + if (!val) + mode = 0x1f; // OFF + + rtl9300_sds_rst(sds_num, mode); + + return 0; +} + +int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + u32 v; + int err = 0; + + pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, val); + + if (port > 63 || page > 4095 || reg > 31) + return -ENOTSUPP; + + val &= 0xffff; + mutex_lock(&smi_lock); + + sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0); + sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2); + v = reg << 20 | page << 3 | 0x1f << 15 | BIT(2) | BIT(0); + sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1); + + do { + v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1); + } while (v & 0x1); + + if (v & 0x2) + err = -EIO; + + mutex_unlock(&smi_lock); + + return err; +} + +int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + u32 v; + int err = 0; + + if (port > 63 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + + sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2); + v = reg << 20 | page << 3 | 0x1f << 15 | 1; + sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1); + + do { + v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1); + } while ( v & 0x1); + + if (v & BIT(25)) { + pr_debug("Error reading phy %d, register %d\n", port, reg); + err = -EIO; + } + *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff); + + pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, *val); + + mutex_unlock(&smi_lock); + + return err; +} + +/* + * Write to an mmd register of the PHY + */ +int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val) +{ + int err = 0; + u32 v; + + mutex_lock(&smi_lock); + + // Set PHY to access + sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0); + + // Set data to write + sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2); + + // Set MMD device number and register to write to + sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3); + + v = BIT(2) | BIT(1) | BIT(0); // WRITE | MMD-access | EXEC + sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1); + + do { + v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1); + } while (v & BIT(0)); + + pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err); + mutex_unlock(&smi_lock); + return err; +} + +/* + * Read an mmd register of the PHY + */ +int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val) +{ + int err = 0; + u32 v; + + mutex_lock(&smi_lock); + + // Set PHY to access + sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2); + + // Set MMD device number and register to write to + sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3); + + v = BIT(1) | BIT(0); // MMD-access | EXEC + sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1); + + do { + v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1); + } while (v & BIT(0)); + // There is no error-checking via BIT 25 of v, as it does not seem to be set correctly + *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff); + pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err); + + mutex_unlock(&smi_lock); + + return err; +} + +/* + * Calculate both the block 0 and the block 1 hash, and return in + * lower and higher word of the return value since only 12 bit of + * the hash are significant + */ +u32 rtl930x_hash(struct rtl838x_switch_priv *priv, u64 seed) +{ + u32 k0, k1, h1, h2, h; + + k0 = (u32) (((seed >> 55) & 0x1f) ^ ((seed >> 44) & 0x7ff) + ^ ((seed >> 33) & 0x7ff) ^ ((seed >> 22) & 0x7ff) + ^ ((seed >> 11) & 0x7ff) ^ (seed & 0x7ff)); + + h1 = (seed >> 11) & 0x7ff; + h1 = ((h1 & 0x1f) << 6) | ((h1 >> 5) & 0x3f); + + h2 = (seed >> 33) & 0x7ff; + h2 = ((h2 & 0x3f) << 5)| ((h2 >> 6) & 0x3f); + + k1 = (u32) (((seed << 55) & 0x1f) ^ ((seed >> 44) & 0x7ff) ^ h2 + ^ ((seed >> 22) & 0x7ff) ^ h1 + ^ (seed & 0x7ff)); + + // Algorithm choice for block 0 + if (sw_r32(RTL930X_L2_CTRL) & BIT(0)) + h = k1; + else + h = k0; + + /* Algorithm choice for block 1 + * Since k0 and k1 are < 2048, adding 2048 will offset the hash into the second + * half of hash-space + * 2048 is in fact the hash-table size 16384 divided by 4 hashes per bucket + * divided by 2 to divide the hash space in 2 + */ + if (sw_r32(RTL930X_L2_CTRL) & BIT(1)) + h |= (k1 + 2048) << 16; + else + h |= (k0 + 2048) << 16; + + return h; +} + +/* + * Enables or disables the EEE/EEEP capability of a port + */ +void rtl930x_port_eee_set(struct rtl838x_switch_priv *priv, int port, bool enable) +{ + u32 v; + + // This works only for Ethernet ports, and on the RTL930X, ports from 26 are SFP + if (port >= 26) + return; + + pr_debug("In %s: setting port %d to %d\n", __func__, port, enable); + v = enable ? 0x3f : 0x0; + + // Set EEE/EEEP state for 100, 500, 1000MBit and 2.5, 5 and 10GBit + sw_w32_mask(0, v << 10, rtl930x_mac_force_mode_ctrl(port)); + + // Set TX/RX EEE state + v = enable ? 0x3 : 0x0; + sw_w32(v, RTL930X_EEE_CTRL(port)); + + priv->ports[port].eee_enabled = enable; +} + +/* + * Get EEE own capabilities and negotiation result + */ +int rtl930x_eee_port_ability(struct rtl838x_switch_priv *priv, struct ethtool_eee *e, int port) +{ + u32 link, a; + + if (port >= 26) + return -ENOTSUPP; + + pr_info("In %s, port %d\n", __func__, port); + link = sw_r32(RTL930X_MAC_LINK_STS); + link = sw_r32(RTL930X_MAC_LINK_STS); + if (!(link & BIT(port))) + return 0; + + pr_info("Setting advertised\n"); + if (sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(10)) + e->advertised |= ADVERTISED_100baseT_Full; + + if (sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(12)) + e->advertised |= ADVERTISED_1000baseT_Full; + + if (priv->ports[port].is2G5 && sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(13)) { + pr_info("ADVERTISING 2.5G EEE\n"); + e->advertised |= ADVERTISED_2500baseX_Full; + } + + if (priv->ports[port].is10G && sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(15)) + e->advertised |= ADVERTISED_10000baseT_Full; + + a = sw_r32(RTL930X_MAC_EEE_ABLTY); + a = sw_r32(RTL930X_MAC_EEE_ABLTY); + pr_info("Link partner: %08x\n", a); + if (a & BIT(port)) { + e->lp_advertised = ADVERTISED_100baseT_Full; + e->lp_advertised |= ADVERTISED_1000baseT_Full; + if (priv->ports[port].is2G5) + e->lp_advertised |= ADVERTISED_2500baseX_Full; + if (priv->ports[port].is10G) + e->lp_advertised |= ADVERTISED_10000baseT_Full; + } + + // Read 2x to clear latched state + a = sw_r32(RTL930X_EEEP_PORT_CTRL(port)); + a = sw_r32(RTL930X_EEEP_PORT_CTRL(port)); + pr_info("%s RTL930X_EEEP_PORT_CTRL: %08x\n", __func__, a); + + return 0; +} + +static void rtl930x_init_eee(struct rtl838x_switch_priv *priv, bool enable) +{ + int i; + + pr_info("Setting up EEE, state: %d\n", enable); + + // Setup EEE on all ports + for (i = 0; i < priv->cpu_port; i++) { + if (priv->ports[i].phy) + rtl930x_port_eee_set(priv, i, enable); + } + + priv->eee_enabled = enable; +} + +const struct rtl838x_reg rtl930x_reg = { + .mask_port_reg_be = rtl838x_mask_port_reg, + .set_port_reg_be = rtl838x_set_port_reg, + .get_port_reg_be = rtl838x_get_port_reg, + .mask_port_reg_le = rtl838x_mask_port_reg, + .set_port_reg_le = rtl838x_set_port_reg, + .get_port_reg_le = rtl838x_get_port_reg, + .stat_port_rst = RTL930X_STAT_PORT_RST, + .stat_rst = RTL930X_STAT_RST, + .stat_port_std_mib = RTL930X_STAT_PORT_MIB_CNTR, + .traffic_enable = rtl930x_traffic_enable, + .traffic_disable = rtl930x_traffic_disable, + .traffic_get = rtl930x_traffic_get, + .traffic_set = rtl930x_traffic_set, + .l2_ctrl_0 = RTL930X_L2_CTRL, + .l2_ctrl_1 = RTL930X_L2_AGE_CTRL, + .l2_port_aging_out = RTL930X_L2_PORT_AGE_CTRL, + .smi_poll_ctrl = RTL930X_SMI_POLL_CTRL, // TODO: Difference to RTL9300_SMI_PRVTE_POLLING_CTRL + .l2_tbl_flush_ctrl = RTL930X_L2_TBL_FLUSH_CTRL, + .exec_tbl0_cmd = rtl930x_exec_tbl0_cmd, + .exec_tbl1_cmd = rtl930x_exec_tbl1_cmd, + .tbl_access_data_0 = rtl930x_tbl_access_data_0, + .isr_glb_src = RTL930X_ISR_GLB, + .isr_port_link_sts_chg = RTL930X_ISR_PORT_LINK_STS_CHG, + .imr_port_link_sts_chg = RTL930X_IMR_PORT_LINK_STS_CHG, + .imr_glb = RTL930X_IMR_GLB, + .vlan_tables_read = rtl930x_vlan_tables_read, + .vlan_set_tagged = rtl930x_vlan_set_tagged, + .vlan_set_untagged = rtl930x_vlan_set_untagged, + .vlan_profile_dump = rtl930x_vlan_profile_dump, + .vlan_profile_setup = rtl930x_vlan_profile_setup, + .vlan_fwd_on_inner = rtl930x_vlan_fwd_on_inner, + .stp_get = rtl930x_stp_get, + .stp_set = rtl930x_stp_set, + .mac_force_mode_ctrl = rtl930x_mac_force_mode_ctrl, + .mac_port_ctrl = rtl930x_mac_port_ctrl, + .l2_port_new_salrn = rtl930x_l2_port_new_salrn, + .l2_port_new_sa_fwd = rtl930x_l2_port_new_sa_fwd, + .mir_ctrl = RTL930X_MIR_CTRL, + .mir_dpm = RTL930X_MIR_DPM_CTRL, + .mir_spm = RTL930X_MIR_SPM_CTRL, + .mac_link_sts = RTL930X_MAC_LINK_STS, + .mac_link_dup_sts = RTL930X_MAC_LINK_DUP_STS, + .mac_link_spd_sts = rtl930x_mac_link_spd_sts, + .mac_rx_pause_sts = RTL930X_MAC_RX_PAUSE_STS, + .mac_tx_pause_sts = RTL930X_MAC_TX_PAUSE_STS, + .read_l2_entry_using_hash = rtl930x_read_l2_entry_using_hash, + .write_l2_entry_using_hash = rtl930x_write_l2_entry_using_hash, + .read_cam = rtl930x_read_cam, + .write_cam = rtl930x_write_cam, + .vlan_port_egr_filter = RTL930X_VLAN_PORT_EGR_FLTR, + .vlan_port_igr_filter = RTL930X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_pb = RTL930X_VLAN_PORT_PB_VLAN, + .vlan_port_tag_sts_ctrl = RTL930X_VLAN_PORT_TAG_STS_CTRL, + .trk_mbr_ctr = rtl930x_trk_mbr_ctr, + .rma_bpdu_fld_pmask = RTL930X_RMA_BPDU_FLD_PMSK, + .init_eee = rtl930x_init_eee, + .port_eee_set = rtl930x_port_eee_set, + .eee_port_ability = rtl930x_eee_port_ability, + .read_mcast_pmask = rtl930x_read_mcast_pmask, + .write_mcast_pmask = rtl930x_write_mcast_pmask, +}; 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 new file mode 100644 index 0000000000..f98bf7df29 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "rtl83xx.h" + +extern struct mutex smi_lock; +extern struct rtl83xx_soc_info soc_info; + +inline void rtl931x_exec_tbl0_cmd(u32 cmd) +{ + sw_w32(cmd, RTL931X_TBL_ACCESS_CTRL_0); + do { } while (sw_r32(RTL931X_TBL_ACCESS_CTRL_0) & (1 << 20)); +} + +inline void rtl931x_exec_tbl1_cmd(u32 cmd) +{ + sw_w32(cmd, RTL931X_TBL_ACCESS_CTRL_1); + do { } while (sw_r32(RTL931X_TBL_ACCESS_CTRL_1) & (1 << 17)); +} + +inline int rtl931x_tbl_access_data_0(int i) +{ + return RTL931X_TBL_ACCESS_DATA_0(i); +} + +void rtl931x_vlan_profile_dump(int index) +{ + u64 profile[4]; + + if (index < 0 || index > 15) + return; + + profile[0] = sw_r32(RTL931X_VLAN_PROFILE_SET(index)); + profile[1] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 4) & 0x1FFFFFFFULL) << 32 + | (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 8) & 0xFFFFFFFF); + profile[2] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 16) & 0xFFFFFFFFULL) << 32 + | (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 12) & 0x1FFFFFFULL); + profile[3] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 20) & 0x1FFFFFFFULL) << 32 + | (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 24) & 0xFFFFFFFF); + + pr_info("VLAN %d: L2 learning: %d, L2 Unknown MultiCast Field %llx, \ + IPv4 Unknown MultiCast Field %llx, IPv6 Unknown MultiCast Field: %llx", + index, (u32) (profile[0] & (3 << 14)), profile[1], profile[2], profile[3]); +} + +static void rtl931x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 20 /* Execute cmd */ + | 0 << 19 /* Read */ + | 2 << 15 /* Table type 0b10 */ + | (msti & 0x3fff); + priv->r->exec_tbl0_cmd(cmd); + + for (i = 0; i < 4; i++) + port_state[i] = sw_r32(priv->r->tbl_access_data_0(i)); +} + +static void rtl931x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +{ + int i; + u32 cmd = 1 << 20 /* Execute cmd */ + | 1 << 19 /* Write */ + | 5 << 15 /* Table type 0b101 */ + | (msti & 0x3fff); + for (i = 0; i < 4; i++) + sw_w32(port_state[i], priv->r->tbl_access_data_0(i)); + priv->r->exec_tbl0_cmd(cmd); +} + +inline static int rtl931x_trk_mbr_ctr(int group) +{ + return RTL931X_TRK_MBR_CTRL + (group << 2); +} + +static void rtl931x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 v, w, x, y; + // Read VLAN table (3) via register 0 + struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 3); + + rtl_table_read(r, vlan); + v = sw_r32(rtl_table_data(r, 0)); + w = sw_r32(rtl_table_data(r, 1)); + x = sw_r32(rtl_table_data(r, 2)); + y = sw_r32(rtl_table_data(r, 3)); + pr_debug("VLAN_READ %d: %08x %08x\n", vlan, v, w); + rtl_table_release(r); + + info->tagged_ports = ((u64) v) << 25 | (w >> 7); + info->profile_id = (x >> 16) & 0xf; + info->hash_mc_fid = !!(x & BIT(30)); + info->hash_uc_fid = !!(x & BIT(31)); + info->fid = w & 0x7f; + // TODO: use also info in 4th register + + // Read UNTAG table via table register 3 + r = rtl_table_get(RTL9310_TBL_3, 0); + rtl_table_read(r, vlan); + v = ((u64)sw_r32(rtl_table_data(r, 0))) << 25; + v |= sw_r32(rtl_table_data(r, 1)) >> 7; + rtl_table_release(r); + + info->untagged_ports = v; +} + +static void rtl931x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info) +{ + u32 v, w, x; + // Access VLAN table (1) via register 0 + struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 3); + + v = info->tagged_ports << 7; + w = (info->tagged_ports & 0x7f000000) << 25; + w |= (u32)info->fid; + x = info->profile_id << 16; + w |= info->hash_mc_fid ? BIT(30) : 0; + w |= info->hash_uc_fid ? BIT(31) : 0; + // TODO: use also info in 4th register + + sw_w32(v, rtl_table_data(r, 0)); + sw_w32(w, rtl_table_data(r, 1)); + sw_w32(x, rtl_table_data(r, 2)); + + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +static void rtl931x_vlan_set_untagged(u32 vlan, u64 portmask) +{ + struct table_reg *r = rtl_table_get(RTL9310_TBL_3, 0); + + rtl839x_set_port_reg_be(portmask << 7, rtl_table_data(r, 0)); + rtl_table_write(r, vlan); + rtl_table_release(r); +} + +static inline int rtl931x_mac_force_mode_ctrl(int p) +{ + return RTL931X_MAC_FORCE_MODE_CTRL + (p << 2); +} + +static inline int rtl931x_mac_link_spd_sts(int p) +{ + return RTL931X_MAC_LINK_SPD_STS(p); +} + +static inline int rtl931x_mac_port_ctrl(int p) +{ + return RTL931X_MAC_PORT_CTRL(p); +} + +static inline int rtl931x_l2_port_new_salrn(int p) +{ + return RTL931X_L2_PORT_NEW_SALRN(p); +} + +static inline int rtl931x_l2_port_new_sa_fwd(int p) +{ + return RTL931X_L2_PORT_NEW_SA_FWD(p); +} + +static u64 rtl931x_read_l2_entry_using_hash(u32 hash, u32 position, struct rtl838x_l2_entry *e) +{ + u64 entry = 0; + + // TODO: Implement + return entry; +} + +static u64 rtl931x_read_cam(int idx, struct rtl838x_l2_entry *e) +{ + u64 entry = 0; + + // TODO: Implement + return entry; +} + +irqreturn_t rtl931x_switch_irq(int irq, void *dev_id) +{ + struct dsa_switch *ds = dev_id; + u32 status = sw_r32(RTL931X_ISR_GLB_SRC); + u64 ports = rtl839x_get_port_reg_le(RTL931X_ISR_PORT_LINK_STS_CHG); + u64 link; + int i; + + /* Clear status */ + rtl839x_set_port_reg_le(ports, RTL931X_ISR_PORT_LINK_STS_CHG); + pr_info("RTL9310 Link change: status: %x, ports %llx\n", status, ports); + + for (i = 0; i < 56; i++) { + if (ports & BIT_ULL(i)) { + link = rtl839x_get_port_reg_le(RTL931X_MAC_LINK_STS); + if (link & BIT_ULL(i)) + dsa_port_phylink_mac_change(ds, i, true); + else + dsa_port_phylink_mac_change(ds, i, false); + } + } + return IRQ_HANDLED; +} + +int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + u32 v; + int err = 0; + + val &= 0xffff; + if (port > 63 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + /* Clear both port registers */ + sw_w32(0, RTL931X_SMI_INDRT_ACCESS_CTRL_2); + sw_w32(0, RTL931X_SMI_INDRT_ACCESS_CTRL_2 + 4); + sw_w32_mask(0, BIT(port), RTL931X_SMI_INDRT_ACCESS_CTRL_2+ (port % 32) * 4); + + sw_w32_mask(0xffff0000, val << 16, RTL931X_SMI_INDRT_ACCESS_CTRL_3); + + v = reg << 6 | page << 11 ; + sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0); + + sw_w32(0x1ff, RTL931X_SMI_INDRT_ACCESS_CTRL_1); + + v |= 1 << 3 | 1; /* Write operation and execute */ + sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0); + + do { + } while (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x1); + + if (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x2) + err = -EIO; + + mutex_unlock(&smi_lock); + return err; +} + +int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + u32 v; + + if (port > 63 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&smi_lock); + + sw_w32_mask(0xffff, port, RTL931X_SMI_INDRT_ACCESS_CTRL_3); + v = reg << 6 | page << 11; // TODO: ACCESS Offset? Park page + sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0); + + sw_w32(0x1ff, RTL931X_SMI_INDRT_ACCESS_CTRL_1); + + v |= 1; + sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0); + + do { + } while (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x1); + + *val = (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_3) & 0xffff0000) >> 16; + + pr_info("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, *val); + + mutex_unlock(&smi_lock); + return 0; +} + +/* + * Read an mmd register of the PHY + */ +int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val) +{ + int err = 0; + u32 v; + int type = 1; // TODO: For C45 PHYs need to set to 2 + + mutex_lock(&smi_lock); + + // Set PHY to access via port-number + sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL); + + // Set MMD device number and register to write to + sw_w32(devnum << 16 | (regnum & 0xffff), RTL931X_SMI_INDRT_ACCESS_MMD_CTRL); + + v = type << 2 | BIT(0); // MMD-access-type | EXEC + sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0); + + do { + v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0); + } while (v & BIT(0)); + + // There is no error-checking via BIT 1 of v, as it does not seem to be set correctly + + *val = (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_3) & 0xffff); + + pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err); + + mutex_unlock(&smi_lock); + + return err; +} + +/* + * Write to an mmd register of the PHY + */ +int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val) +{ + int err = 0; + u32 v; + int type = 1; // TODO: For C45 PHYs need to set to 2 + + mutex_lock(&smi_lock); + + // Set PHY to access via port-number + sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL); + + // Set data to write + sw_w32_mask(0xffff << 16, val << 16, RTL931X_SMI_INDRT_ACCESS_CTRL_3); + + // Set MMD device number and register to write to + sw_w32(devnum << 16 | (regnum & 0xffff), RTL931X_SMI_INDRT_ACCESS_MMD_CTRL); + + v = BIT(4) | type << 2 | BIT(0); // WRITE | MMD-access-type | EXEC + sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0); + + do { + v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0); + } while (v & BIT(0)); + + pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err); + mutex_unlock(&smi_lock); + return err; +} + +void rtl931x_print_matrix(void) +{ + volatile u64 *ptr = RTL838X_SW_BASE + RTL839X_PORT_ISO_CTRL(0); + int i; + + for (i = 0; i < 52; i += 4) + pr_info("> %16llx %16llx %16llx %16llx\n", + ptr[i + 0], ptr[i + 1], ptr[i + 2], ptr[i + 3]); + pr_info("CPU_PORT> %16llx\n", ptr[52]); +} + +const struct rtl838x_reg rtl931x_reg = { + .mask_port_reg_be = rtl839x_mask_port_reg_be, + .set_port_reg_be = rtl839x_set_port_reg_be, + .get_port_reg_be = rtl839x_get_port_reg_be, + .mask_port_reg_le = rtl839x_mask_port_reg_le, + .set_port_reg_le = rtl839x_set_port_reg_le, + .get_port_reg_le = rtl839x_get_port_reg_le, + .stat_port_rst = RTL931X_STAT_PORT_RST, + .stat_rst = RTL931X_STAT_RST, + .stat_port_std_mib = 0, // Not defined + .l2_ctrl_0 = RTL931X_L2_CTRL, + .l2_ctrl_1 = RTL931X_L2_AGE_CTRL, + .l2_port_aging_out = RTL931X_L2_PORT_AGE_CTRL, + // .smi_poll_ctrl does not exist + .l2_tbl_flush_ctrl = RTL931X_L2_TBL_FLUSH_CTRL, + .exec_tbl0_cmd = rtl931x_exec_tbl0_cmd, + .exec_tbl1_cmd = rtl931x_exec_tbl1_cmd, + .tbl_access_data_0 = rtl931x_tbl_access_data_0, + .isr_glb_src = RTL931X_ISR_GLB_SRC, + .isr_port_link_sts_chg = RTL931X_ISR_PORT_LINK_STS_CHG, + .imr_port_link_sts_chg = RTL931X_IMR_PORT_LINK_STS_CHG, + // imr_glb does not exist on RTL931X + .vlan_tables_read = rtl931x_vlan_tables_read, + .vlan_set_tagged = rtl931x_vlan_set_tagged, + .vlan_set_untagged = rtl931x_vlan_set_untagged, + .vlan_profile_dump = rtl931x_vlan_profile_dump, + .stp_get = rtl931x_stp_get, + .stp_set = rtl931x_stp_set, + .mac_force_mode_ctrl = rtl931x_mac_force_mode_ctrl, + .mac_port_ctrl = rtl931x_mac_port_ctrl, + .l2_port_new_salrn = rtl931x_l2_port_new_salrn, + .l2_port_new_sa_fwd = rtl931x_l2_port_new_sa_fwd, + .mir_ctrl = RTL931X_MIR_CTRL, + .mir_dpm = RTL931X_MIR_DPM_CTRL, + .mir_spm = RTL931X_MIR_SPM_CTRL, + .mac_link_sts = RTL931X_MAC_LINK_STS, + .mac_link_dup_sts = RTL931X_MAC_LINK_DUP_STS, + .mac_link_spd_sts = rtl931x_mac_link_spd_sts, + .mac_rx_pause_sts = RTL931X_MAC_RX_PAUSE_STS, + .mac_tx_pause_sts = RTL931X_MAC_TX_PAUSE_STS, + .read_l2_entry_using_hash = rtl931x_read_l2_entry_using_hash, + .read_cam = rtl931x_read_cam, + .vlan_port_egr_filter = RTL931X_VLAN_PORT_EGR_FLTR(0), + .vlan_port_igr_filter = RTL931X_VLAN_PORT_IGR_FLTR(0), +// .vlan_port_pb = does not exist + .vlan_port_tag_sts_ctrl = RTL931X_VLAN_PORT_TAG_CTRL, + .trk_mbr_ctr = rtl931x_trk_mbr_ctr, +}; + diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c new file mode 100644 index 0000000000..3f98e3bf81 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -0,0 +1,2201 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * linux/drivers/net/ethernet/rtl838x_eth.c + * Copyright (C) 2020 B. Koblitz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rtl838x_eth.h" + +extern struct rtl83xx_soc_info soc_info; + +/* + * Maximum number of RX rings is 8 on RTL83XX and 32 on the 93XX + * The ring is assigned by switch based on packet/port priortity + * Maximum number of TX rings is 2, Ring 2 being the high priority + * ring on the RTL93xx SoCs. MAX_RING_SIZE * RING_BUFFER gives + * the memory used for the ring buffer. + */ +#define MAX_RXRINGS 32 +#define MAX_RXLEN 100 +#define MAX_ENTRIES (200 * 8) +#define TXRINGS 2 +// BUG: TXRINGLEN can be 160 +#define TXRINGLEN 16 +#define NOTIFY_EVENTS 10 +#define NOTIFY_BLOCKS 10 +#define TX_EN 0x8 +#define RX_EN 0x4 +#define TX_EN_93XX 0x20 +#define RX_EN_93XX 0x10 +#define TX_DO 0x2 +#define WRAP 0x2 + +#define RING_BUFFER 1600 + +#define RTL838X_STORM_CTRL_PORT_BC_EXCEED (0x470C) +#define RTL838X_STORM_CTRL_PORT_MC_EXCEED (0x4710) +#define RTL838X_STORM_CTRL_PORT_UC_EXCEED (0x4714) +#define RTL838X_ATK_PRVNT_STS (0x5B1C) + +struct p_hdr { + uint8_t *buf; + uint16_t reserved; + uint16_t size; /* buffer size */ + uint16_t offset; + uint16_t len; /* pkt len */ + uint16_t cpu_tag[10]; +} __packed __aligned(1); + +struct n_event { + uint32_t type:2; + uint32_t fidVid:12; + uint64_t mac:48; + uint32_t slp:6; + uint32_t valid:1; + uint32_t reserved:27; +} __packed __aligned(1); + +struct ring_b { + uint32_t rx_r[MAX_RXRINGS][MAX_RXLEN]; + uint32_t tx_r[TXRINGS][TXRINGLEN]; + struct p_hdr rx_header[MAX_RXRINGS][MAX_RXLEN]; + struct p_hdr tx_header[TXRINGS][TXRINGLEN]; + uint32_t c_rx[MAX_RXRINGS]; + uint32_t c_tx[TXRINGS]; + uint8_t tx_space[TXRINGS * TXRINGLEN * RING_BUFFER]; + uint8_t *rx_space; +}; + +struct notify_block { + struct n_event events[NOTIFY_EVENTS]; +}; + +struct notify_b { + struct notify_block blocks[NOTIFY_BLOCKS]; + u32 reserved1[8]; + u32 ring[NOTIFY_BLOCKS]; + u32 reserved2[8]; +}; + +void rtl838x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +{ + prio &= 0x7; + + if (dest_port > 0) { + // cpu_tag[0] is reserved on the RTL83XX SoCs + h->cpu_tag[1] = 0x0400; + h->cpu_tag[2] = 0x0200; + h->cpu_tag[3] = 0x0000; + h->cpu_tag[4] = BIT(dest_port) >> 16; + h->cpu_tag[5] = BIT(dest_port) & 0xffff; + // Set internal priority and AS_PRIO + if (prio >= 0) + h->cpu_tag[2] |= (prio | 0x8) << 12; + } +} + +void rtl839x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +{ + prio &= 0x7; + + if (dest_port > 0) { + // cpu_tag[0] is reserved on the RTL83XX SoCs + h->cpu_tag[1] = 0x0100; + h->cpu_tag[2] = h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0; + if (dest_port >= 32) { + dest_port -= 32; + h->cpu_tag[2] = BIT(dest_port) >> 16; + h->cpu_tag[3] = BIT(dest_port) & 0xffff; + } else { + h->cpu_tag[4] = BIT(dest_port) >> 16; + h->cpu_tag[5] = BIT(dest_port) & 0xffff; + } + h->cpu_tag[6] |= BIT(21); // Enable destination port mask use + // Set internal priority and AS_PRIO + if (prio >= 0) + h->cpu_tag[1] |= prio | BIT(3); + } +} + +void rtl930x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +{ + h->cpu_tag[0] = 0x8000; + h->cpu_tag[1] = 0; // TODO: Fill port and prio + h->cpu_tag[2] = 0; + h->cpu_tag[3] = 0; + h->cpu_tag[4] = 0; + h->cpu_tag[5] = 0; + h->cpu_tag[6] = 0; + h->cpu_tag[7] = 0xffff; +} + +void rtl931x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +{ + h->cpu_tag[0] = 0x8000; + h->cpu_tag[1] = 0; // TODO: Fill port and prio + h->cpu_tag[2] = 0; + h->cpu_tag[3] = 0; + h->cpu_tag[4] = 0; + h->cpu_tag[5] = 0; + h->cpu_tag[6] = 0; + h->cpu_tag[7] = 0xffff; +} + +struct rtl838x_rx_q { + int id; + struct rtl838x_eth_priv *priv; + struct napi_struct napi; +}; + +struct rtl838x_eth_priv { + struct net_device *netdev; + struct platform_device *pdev; + void *membase; + spinlock_t lock; + struct mii_bus *mii_bus; + struct rtl838x_rx_q rx_qs[MAX_RXRINGS]; + struct phylink *phylink; + struct phylink_config phylink_config; + u16 id; + u16 family_id; + const struct rtl838x_reg *r; + u8 cpu_port; + u32 lastEvent; + u16 rxrings; + u16 rxringlen; +}; + +extern int rtl838x_phy_init(struct rtl838x_eth_priv *priv); +extern int rtl838x_read_sds_phy(int phy_addr, int phy_reg); +extern int rtl839x_read_sds_phy(int phy_addr, int phy_reg); +extern int rtl839x_write_sds_phy(int phy_addr, int phy_reg, u16 v); +extern int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg); +extern int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v); +extern int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); +extern int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val); + +/* + * On the RTL93XX, the RTL93XX_DMA_IF_RX_RING_CNTR track the fill level of + * the rings. Writing x into these registers substracts x from its content. + * When the content reaches the ring size, the ASIC no longer adds + * packets to this receive queue. + */ +void rtl838x_update_cntr(int r, int released) +{ + // This feature is not available on RTL838x SoCs +} + +void rtl839x_update_cntr(int r, int released) +{ + // This feature is not available on RTL839x SoCs +} + +void rtl930x_update_cntr(int r, int released) +{ + int pos = (r % 3) * 10; + u32 reg = RTL930X_DMA_IF_RX_RING_CNTR + ((r / 3) << 2); + u32 v = sw_r32(reg); + + v = (v >> pos) & 0x3ff; + pr_debug("RX: Work done %d, old value: %d, pos %d, reg %04x\n", released, v, pos, reg); + sw_w32_mask(0x3ff << pos, released << pos, reg); + sw_w32(v, reg); +} + +void rtl931x_update_cntr(int r, int released) +{ + int pos = (r % 3) * 10; + u32 reg = RTL931X_DMA_IF_RX_RING_CNTR + ((r / 3) << 2); + + sw_w32_mask(0x3ff << pos, released << pos, reg); +} + +struct dsa_tag { + u8 reason; + u8 queue; + u16 port; + u8 l2_offloaded; + u8 prio; + bool crc_error; +}; + +bool rtl838x_decode_tag(struct p_hdr *h, struct dsa_tag *t) +{ + t->reason = h->cpu_tag[3] & 0xf; + t->queue = (h->cpu_tag[0] & 0xe0) >> 5; + t->port = h->cpu_tag[1] & 0x1f; + t->crc_error = t->reason == 13; + + pr_debug("Reason: %d\n", t->reason); + if (t->reason != 4) // NIC_RX_REASON_SPECIAL_TRAP + t->l2_offloaded = 1; + else + t->l2_offloaded = 0; + + return t->l2_offloaded; +} + +bool rtl839x_decode_tag(struct p_hdr *h, struct dsa_tag *t) +{ + t->reason = h->cpu_tag[4] & 0x1f; + t->queue = (h->cpu_tag[3] & 0xe000) >> 13; + t->port = h->cpu_tag[1] & 0x3f; + t->crc_error = h->cpu_tag[3] & BIT(2); + + pr_debug("Reason: %d\n", t->reason); + if ((t->reason != 7) && (t->reason != 8)) // NIC_RX_REASON_RMA_USR + t->l2_offloaded = 1; + else + t->l2_offloaded = 0; + + return t->l2_offloaded; +} + +bool rtl930x_decode_tag(struct p_hdr *h, struct dsa_tag *t) +{ + t->reason = h->cpu_tag[7] & 0x3f; + t->queue = (h->cpu_tag[2] >> 11) & 0x1f; + t->port = (h->cpu_tag[0] >> 8) & 0x1f; + t->crc_error = h->cpu_tag[1] & BIT(6); + + pr_debug("Reason %d, port %d, queue %d\n", t->reason, t->port, t->queue); + if (t->reason >= 19 && t->reason <= 27) + t->l2_offloaded = 0; + else + t->l2_offloaded = 1; + + return t->l2_offloaded; +} + +bool rtl931x_decode_tag(struct p_hdr *h, struct dsa_tag *t) +{ + t->reason = h->cpu_tag[7] & 0x3f; + t->queue = (h->cpu_tag[2] >> 11) & 0x1f; + t->port = (h->cpu_tag[0] >> 8) & 0x3f; + t->crc_error = h->cpu_tag[1] & BIT(6); + + pr_debug("Reason %d, port %d, queue %d\n", t->reason, t->port, t->queue); + if (t->reason >= 19 && t->reason <= 27) + t->l2_offloaded = 0; + else + t->l2_offloaded = 1; + + return t->l2_offloaded; +} + +/* + * Discard the RX ring-buffers, called as part of the net-ISR + * when the buffer runs over + * Caller needs to hold priv->lock + */ +static void rtl838x_rb_cleanup(struct rtl838x_eth_priv *priv, int status) +{ + int r; + u32 *last; + struct p_hdr *h; + struct ring_b *ring = priv->membase; + + for (r = 0; r < priv->rxrings; r++) { + pr_debug("In %s working on r: %d\n", __func__, r); + last = (u32 *)KSEG1ADDR(sw_r32(priv->r->dma_if_rx_cur + r * 4)); + do { + if ((ring->rx_r[r][ring->c_rx[r]] & 0x1)) + break; + pr_debug("Got something: %d\n", ring->c_rx[r]); + h = &ring->rx_header[r][ring->c_rx[r]]; + memset(h, 0, sizeof(struct p_hdr)); + h->buf = (u8 *)KSEG1ADDR(ring->rx_space + + r * priv->rxringlen * RING_BUFFER + + ring->c_rx[r] * RING_BUFFER); + h->size = RING_BUFFER; + /* make sure the header is visible to the ASIC */ + mb(); + + ring->rx_r[r][ring->c_rx[r]] = KSEG1ADDR(h) | 0x1 + | (ring->c_rx[r] == (priv->rxringlen - 1) ? WRAP : 0x1); + ring->c_rx[r] = (ring->c_rx[r] + 1) % priv->rxringlen; + } while (&ring->rx_r[r][ring->c_rx[r]] != last); + } +} + +struct fdb_update_work { + struct work_struct work; + struct net_device *ndev; + u64 macs[NOTIFY_EVENTS + 1]; +}; + +void rtl838x_fdb_sync(struct work_struct *work) +{ + const struct fdb_update_work *uw = + container_of(work, struct fdb_update_work, work); + struct switchdev_notifier_fdb_info info; + u8 addr[ETH_ALEN]; + int i = 0; + int action; + + while (uw->macs[i]) { + action = (uw->macs[i] & (1ULL << 63)) ? SWITCHDEV_FDB_ADD_TO_BRIDGE + : SWITCHDEV_FDB_DEL_TO_BRIDGE; + u64_to_ether_addr(uw->macs[i] & 0xffffffffffffULL, addr); + info.addr = &addr[0]; + info.vid = 0; + info.offloaded = 1; + pr_debug("FDB entry %d: %llx, action %d\n", i, uw->macs[0], action); + call_switchdev_notifiers(action, uw->ndev, &info.info, NULL); + i++; + } + kfree(work); +} + +static void rtl839x_l2_notification_handler(struct rtl838x_eth_priv *priv) +{ + struct notify_b *nb = priv->membase + sizeof(struct ring_b); + u32 e = priv->lastEvent; + struct n_event *event; + int i; + u64 mac; + struct fdb_update_work *w; + + while (!(nb->ring[e] & 1)) { + w = kzalloc(sizeof(*w), GFP_ATOMIC); + if (!w) { + pr_err("Out of memory: %s", __func__); + return; + } + INIT_WORK(&w->work, rtl838x_fdb_sync); + + for (i = 0; i < NOTIFY_EVENTS; i++) { + event = &nb->blocks[e].events[i]; + if (!event->valid) + continue; + mac = event->mac; + if (event->type) + mac |= 1ULL << 63; + w->ndev = priv->netdev; + w->macs[i] = mac; + } + + /* Hand the ring entry back to the switch */ + nb->ring[e] = nb->ring[e] | 1; + e = (e + 1) % NOTIFY_BLOCKS; + + w->macs[i] = 0ULL; + schedule_work(&w->work); + } + priv->lastEvent = e; +} + +static irqreturn_t rtl83xx_net_irq(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct rtl838x_eth_priv *priv = netdev_priv(dev); + u32 status = sw_r32(priv->r->dma_if_intr_sts); + bool triggered = false; + u32 atk = sw_r32(RTL838X_ATK_PRVNT_STS); + int i; + u32 storm_uc = sw_r32(RTL838X_STORM_CTRL_PORT_UC_EXCEED); + u32 storm_mc = sw_r32(RTL838X_STORM_CTRL_PORT_MC_EXCEED); + u32 storm_bc = sw_r32(RTL838X_STORM_CTRL_PORT_BC_EXCEED); + + pr_debug("IRQ: %08x\n", status); + if (storm_uc || storm_mc || storm_bc) { + pr_warn("Storm control UC: %08x, MC: %08x, BC: %08x\n", + storm_uc, storm_mc, storm_bc); + + sw_w32(storm_uc, RTL838X_STORM_CTRL_PORT_UC_EXCEED); + sw_w32(storm_mc, RTL838X_STORM_CTRL_PORT_MC_EXCEED); + sw_w32(storm_bc, RTL838X_STORM_CTRL_PORT_BC_EXCEED); + + triggered = true; + } + + if (atk) { + pr_debug("Attack prevention triggered: %08x\n", atk); + sw_w32(atk, RTL838X_ATK_PRVNT_STS); + } + + spin_lock(&priv->lock); + /* Ignore TX interrupt */ + if ((status & 0xf0000)) { + /* Clear ISR */ + sw_w32(0x000f0000, priv->r->dma_if_intr_sts); + } + + /* RX interrupt */ + if (status & 0x0ff00) { + /* ACK and disable RX interrupt for this ring */ + sw_w32_mask(0xff00 & status, 0, priv->r->dma_if_intr_msk); + sw_w32(0x0000ff00 & status, priv->r->dma_if_intr_sts); + for (i = 0; i < priv->rxrings; i++) { + if (status & BIT(i + 8)) { + pr_debug("Scheduling queue: %d\n", i); + napi_schedule(&priv->rx_qs[i].napi); + } + } + } + + /* RX buffer overrun */ + if (status & 0x000ff) { + pr_info("RX buffer overrun: status %x, mask: %x\n", + status, sw_r32(priv->r->dma_if_intr_msk)); + sw_w32(status, priv->r->dma_if_intr_sts); + rtl838x_rb_cleanup(priv, status & 0xff); + } + + if (priv->family_id == RTL8390_FAMILY_ID && status & 0x00100000) { + sw_w32(0x00100000, priv->r->dma_if_intr_sts); + rtl839x_l2_notification_handler(priv); + } + + if (priv->family_id == RTL8390_FAMILY_ID && status & 0x00200000) { + sw_w32(0x00200000, priv->r->dma_if_intr_sts); + rtl839x_l2_notification_handler(priv); + } + + if (priv->family_id == RTL8390_FAMILY_ID && status & 0x00400000) { + sw_w32(0x00400000, priv->r->dma_if_intr_sts); + rtl839x_l2_notification_handler(priv); + } + + spin_unlock(&priv->lock); + return IRQ_HANDLED; +} + +static irqreturn_t rtl93xx_net_irq(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct rtl838x_eth_priv *priv = netdev_priv(dev); + u32 status_rx_r = sw_r32(priv->r->dma_if_intr_rx_runout_sts); + u32 status_rx = sw_r32(priv->r->dma_if_intr_rx_done_sts); + u32 status_tx = sw_r32(priv->r->dma_if_intr_tx_done_sts); + int i; + + pr_debug("In %s, status_tx: %08x, status_rx: %08x, status_rx_r: %08x\n", + __func__, status_tx, status_rx, status_rx_r); + spin_lock(&priv->lock); + + /* Ignore TX interrupt */ + if (status_tx) { + /* Clear ISR */ + pr_debug("TX done\n"); + sw_w32(status_tx, priv->r->dma_if_intr_tx_done_sts); + } + + /* RX interrupt */ + if (status_rx) { + pr_debug("RX IRQ\n"); + /* ACK and disable RX interrupt for given rings */ + sw_w32(status_rx, priv->r->dma_if_intr_rx_done_sts); + sw_w32_mask(status_rx, 0, priv->r->dma_if_intr_rx_done_msk); + for (i = 0; i < priv->rxrings; i++) { + if (status_rx & BIT(i)) { + pr_debug("Scheduling queue: %d\n", i); + napi_schedule(&priv->rx_qs[i].napi); + } + } + } + + /* RX buffer overrun */ + if (status_rx_r) { + pr_debug("RX buffer overrun: status %x, mask: %x\n", + status_rx_r, sw_r32(priv->r->dma_if_intr_rx_runout_msk)); + sw_w32(status_rx_r, priv->r->dma_if_intr_rx_runout_sts); + rtl838x_rb_cleanup(priv, status_rx_r); + } + + spin_unlock(&priv->lock); + return IRQ_HANDLED; +} + +static const struct rtl838x_reg rtl838x_reg = { + .net_irq = rtl83xx_net_irq, + .mac_port_ctrl = rtl838x_mac_port_ctrl, + .dma_if_intr_sts = RTL838X_DMA_IF_INTR_STS, + .dma_if_intr_msk = RTL838X_DMA_IF_INTR_MSK, + .dma_if_ctrl = RTL838X_DMA_IF_CTRL, + .mac_force_mode_ctrl = RTL838X_MAC_FORCE_MODE_CTRL, + .dma_rx_base = RTL838X_DMA_RX_BASE, + .dma_tx_base = RTL838X_DMA_TX_BASE, + .dma_if_rx_ring_size = rtl838x_dma_if_rx_ring_size, + .dma_if_rx_ring_cntr = rtl838x_dma_if_rx_ring_cntr, + .dma_if_rx_cur = RTL838X_DMA_IF_RX_CUR, + .rst_glb_ctrl = RTL838X_RST_GLB_CTRL_0, + .get_mac_link_sts = rtl838x_get_mac_link_sts, + .get_mac_link_dup_sts = rtl838x_get_mac_link_dup_sts, + .get_mac_link_spd_sts = rtl838x_get_mac_link_spd_sts, + .get_mac_rx_pause_sts = rtl838x_get_mac_rx_pause_sts, + .get_mac_tx_pause_sts = rtl838x_get_mac_tx_pause_sts, + .mac = RTL838X_MAC, + .l2_tbl_flush_ctrl = RTL838X_L2_TBL_FLUSH_CTRL, + .update_cntr = rtl838x_update_cntr, + .create_tx_header = rtl838x_create_tx_header, + .decode_tag = rtl838x_decode_tag, +}; + +static const struct rtl838x_reg rtl839x_reg = { + .net_irq = rtl83xx_net_irq, + .mac_port_ctrl = rtl839x_mac_port_ctrl, + .dma_if_intr_sts = RTL839X_DMA_IF_INTR_STS, + .dma_if_intr_msk = RTL839X_DMA_IF_INTR_MSK, + .dma_if_ctrl = RTL839X_DMA_IF_CTRL, + .mac_force_mode_ctrl = RTL839X_MAC_FORCE_MODE_CTRL, + .dma_rx_base = RTL839X_DMA_RX_BASE, + .dma_tx_base = RTL839X_DMA_TX_BASE, + .dma_if_rx_ring_size = rtl839x_dma_if_rx_ring_size, + .dma_if_rx_ring_cntr = rtl839x_dma_if_rx_ring_cntr, + .dma_if_rx_cur = RTL839X_DMA_IF_RX_CUR, + .rst_glb_ctrl = RTL839X_RST_GLB_CTRL, + .get_mac_link_sts = rtl839x_get_mac_link_sts, + .get_mac_link_dup_sts = rtl839x_get_mac_link_dup_sts, + .get_mac_link_spd_sts = rtl839x_get_mac_link_spd_sts, + .get_mac_rx_pause_sts = rtl839x_get_mac_rx_pause_sts, + .get_mac_tx_pause_sts = rtl839x_get_mac_tx_pause_sts, + .mac = RTL839X_MAC, + .l2_tbl_flush_ctrl = RTL839X_L2_TBL_FLUSH_CTRL, + .update_cntr = rtl839x_update_cntr, + .create_tx_header = rtl839x_create_tx_header, + .decode_tag = rtl839x_decode_tag, +}; + +static const struct rtl838x_reg rtl930x_reg = { + .net_irq = rtl93xx_net_irq, + .mac_port_ctrl = rtl930x_mac_port_ctrl, + .dma_if_intr_rx_runout_sts = RTL930X_DMA_IF_INTR_RX_RUNOUT_STS, + .dma_if_intr_rx_done_sts = RTL930X_DMA_IF_INTR_RX_DONE_STS, + .dma_if_intr_tx_done_sts = RTL930X_DMA_IF_INTR_TX_DONE_STS, + .dma_if_intr_rx_runout_msk = RTL930X_DMA_IF_INTR_RX_RUNOUT_MSK, + .dma_if_intr_rx_done_msk = RTL930X_DMA_IF_INTR_RX_DONE_MSK, + .dma_if_intr_tx_done_msk = RTL930X_DMA_IF_INTR_TX_DONE_MSK, + .l2_ntfy_if_intr_sts = RTL930X_L2_NTFY_IF_INTR_STS, + .l2_ntfy_if_intr_msk = RTL930X_L2_NTFY_IF_INTR_MSK, + .dma_if_ctrl = RTL930X_DMA_IF_CTRL, + .mac_force_mode_ctrl = RTL930X_MAC_FORCE_MODE_CTRL, + .dma_rx_base = RTL930X_DMA_RX_BASE, + .dma_tx_base = RTL930X_DMA_TX_BASE, + .dma_if_rx_ring_size = rtl930x_dma_if_rx_ring_size, + .dma_if_rx_ring_cntr = rtl930x_dma_if_rx_ring_cntr, + .dma_if_rx_cur = RTL930X_DMA_IF_RX_CUR, + .rst_glb_ctrl = RTL930X_RST_GLB_CTRL_0, + .get_mac_link_sts = rtl930x_get_mac_link_sts, + .get_mac_link_dup_sts = rtl930x_get_mac_link_dup_sts, + .get_mac_link_spd_sts = rtl930x_get_mac_link_spd_sts, + .get_mac_rx_pause_sts = rtl930x_get_mac_rx_pause_sts, + .get_mac_tx_pause_sts = rtl930x_get_mac_tx_pause_sts, + .mac = RTL930X_MAC_L2_ADDR_CTRL, + .l2_tbl_flush_ctrl = RTL930X_L2_TBL_FLUSH_CTRL, + .update_cntr = rtl930x_update_cntr, + .create_tx_header = rtl930x_create_tx_header, + .decode_tag = rtl930x_decode_tag, +}; + +static const struct rtl838x_reg rtl931x_reg = { + .net_irq = rtl93xx_net_irq, + .mac_port_ctrl = rtl931x_mac_port_ctrl, + .dma_if_intr_rx_runout_sts = RTL931X_DMA_IF_INTR_RX_RUNOUT_STS, + .dma_if_intr_rx_done_sts = RTL931X_DMA_IF_INTR_RX_DONE_STS, + .dma_if_intr_tx_done_sts = RTL931X_DMA_IF_INTR_TX_DONE_STS, + .dma_if_intr_rx_runout_msk = RTL931X_DMA_IF_INTR_RX_RUNOUT_MSK, + .dma_if_intr_rx_done_msk = RTL931X_DMA_IF_INTR_RX_DONE_MSK, + .dma_if_intr_tx_done_msk = RTL931X_DMA_IF_INTR_TX_DONE_MSK, + .l2_ntfy_if_intr_sts = RTL931X_L2_NTFY_IF_INTR_STS, + .l2_ntfy_if_intr_msk = RTL931X_L2_NTFY_IF_INTR_MSK, + .dma_if_ctrl = RTL931X_DMA_IF_CTRL, + .mac_force_mode_ctrl = RTL931X_MAC_FORCE_MODE_CTRL, + .dma_rx_base = RTL931X_DMA_RX_BASE, + .dma_tx_base = RTL931X_DMA_TX_BASE, + .dma_if_rx_ring_size = rtl931x_dma_if_rx_ring_size, + .dma_if_rx_ring_cntr = rtl931x_dma_if_rx_ring_cntr, + .dma_if_rx_cur = RTL931X_DMA_IF_RX_CUR, + .rst_glb_ctrl = RTL931X_RST_GLB_CTRL, + .get_mac_link_sts = rtl931x_get_mac_link_sts, + .get_mac_link_dup_sts = rtl931x_get_mac_link_dup_sts, + .get_mac_link_spd_sts = rtl931x_get_mac_link_spd_sts, + .get_mac_rx_pause_sts = rtl931x_get_mac_rx_pause_sts, + .get_mac_tx_pause_sts = rtl931x_get_mac_tx_pause_sts, + .mac = RTL931X_MAC_L2_ADDR_CTRL, + .l2_tbl_flush_ctrl = RTL931X_L2_TBL_FLUSH_CTRL, + .update_cntr = rtl931x_update_cntr, + .create_tx_header = rtl931x_create_tx_header, + .decode_tag = rtl931x_decode_tag, +}; + +static void rtl838x_hw_reset(struct rtl838x_eth_priv *priv) +{ + u32 int_saved, nbuf; + int i, pos; + + pr_info("RESETTING %x, CPU_PORT %d\n", priv->family_id, priv->cpu_port); + sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(priv->cpu_port)); + mdelay(100); + + /* Disable and clear interrupts */ + if (priv->family_id == RTL9300_FAMILY_ID || priv->family_id == RTL9310_FAMILY_ID) { + sw_w32(0x00000000, priv->r->dma_if_intr_rx_runout_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_runout_sts); + sw_w32(0x00000000, priv->r->dma_if_intr_rx_done_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_done_sts); + sw_w32(0x00000000, priv->r->dma_if_intr_tx_done_msk); + sw_w32(0x0000000f, priv->r->dma_if_intr_tx_done_sts); + } else { + sw_w32(0x00000000, priv->r->dma_if_intr_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_sts); + } + + if (priv->family_id == RTL8390_FAMILY_ID) { + /* Preserve L2 notification and NBUF settings */ + int_saved = sw_r32(priv->r->dma_if_intr_msk); + nbuf = sw_r32(RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL); + + /* Disable link change interrupt on RTL839x */ + sw_w32(0, RTL839X_IMR_PORT_LINK_STS_CHG); + sw_w32(0, RTL839X_IMR_PORT_LINK_STS_CHG + 4); + + sw_w32(0x00000000, priv->r->dma_if_intr_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_sts); + } + + /* Reset NIC */ + if (priv->family_id == RTL9300_FAMILY_ID || priv->family_id == RTL9310_FAMILY_ID) + sw_w32(0x4, priv->r->rst_glb_ctrl); + else + sw_w32(0x8, priv->r->rst_glb_ctrl); + + do { /* Wait for reset of NIC and Queues done */ + udelay(20); + } while (sw_r32(priv->r->rst_glb_ctrl) & 0xc); + mdelay(100); + + /* Setup Head of Line */ + if (priv->family_id == RTL8380_FAMILY_ID) + sw_w32(0, RTL838X_DMA_IF_RX_RING_SIZE); // Disabled on RTL8380 + if (priv->family_id == RTL8390_FAMILY_ID) + sw_w32(0xffffffff, RTL839X_DMA_IF_RX_RING_CNTR); + if (priv->family_id == RTL9300_FAMILY_ID) { + for (i = 0; i < priv->rxrings; i++) { + pos = (i % 3) * 10; + sw_w32_mask(0x3ff << pos, 0, priv->r->dma_if_rx_ring_size(i)); + sw_w32_mask(0x3ff << pos, priv->rxringlen, + priv->r->dma_if_rx_ring_cntr(i)); + } + } + + /* Re-enable link change interrupt */ + if (priv->family_id == RTL8390_FAMILY_ID) { + sw_w32(0xffffffff, RTL839X_ISR_PORT_LINK_STS_CHG); + sw_w32(0xffffffff, RTL839X_ISR_PORT_LINK_STS_CHG + 4); + sw_w32(0xffffffff, RTL839X_IMR_PORT_LINK_STS_CHG); + sw_w32(0xffffffff, RTL839X_IMR_PORT_LINK_STS_CHG + 4); + + /* Restore notification settings: on RTL838x these bits are null */ + sw_w32_mask(7 << 20, int_saved & (7 << 20), priv->r->dma_if_intr_msk); + sw_w32(nbuf, RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL); + } +} + +static void rtl838x_hw_ring_setup(struct rtl838x_eth_priv *priv) +{ + int i; + struct ring_b *ring = priv->membase; + + for (i = 0; i < priv->rxrings; i++) + sw_w32(KSEG1ADDR(&ring->rx_r[i]), priv->r->dma_rx_base + i * 4); + + for (i = 0; i < TXRINGS; i++) + sw_w32(KSEG1ADDR(&ring->tx_r[i]), priv->r->dma_tx_base + i * 4); +} + +static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) +{ + /* Disable Head of Line features for all RX rings */ + sw_w32(0xffffffff, priv->r->dma_if_rx_ring_size(0)); + + /* Truncate RX buffer to 0x640 (1600) bytes, pad TX */ + sw_w32(0x06400020, priv->r->dma_if_ctrl); + + /* Enable RX done, RX overflow and TX done interrupts */ + sw_w32(0xfffff, priv->r->dma_if_intr_msk); + + /* Enable DMA, engine expects empty FCS field */ + sw_w32_mask(0, RX_EN | TX_EN, priv->r->dma_if_ctrl); + + /* Restart TX/RX to CPU port */ + sw_w32_mask(0x0, 0x3, priv->r->mac_port_ctrl(priv->cpu_port)); + /* Set Speed, duplex, flow control + * FORCE_EN | LINK_EN | NWAY_EN | DUP_SEL + * | SPD_SEL = 0b10 | FORCE_FC_EN | PHY_MASTER_SLV_MANUAL_EN + * | MEDIA_SEL + */ + sw_w32(0x6192F, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); + + /* Enable CRC checks on CPU-port */ + sw_w32_mask(0, BIT(3), priv->r->mac_port_ctrl(priv->cpu_port)); +} + +static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) +{ + /* Setup CPU-Port: RX Buffer */ + sw_w32(0x0000c808, priv->r->dma_if_ctrl); + + /* Enable Notify, RX done, RX overflow and TX done interrupts */ + sw_w32(0x007fffff, priv->r->dma_if_intr_msk); // Notify IRQ! + + /* Enable DMA */ + sw_w32_mask(0, RX_EN | TX_EN, priv->r->dma_if_ctrl); + + /* Restart TX/RX to CPU port, enable CRC checking */ + sw_w32_mask(0x0, 0x3 | BIT(3), priv->r->mac_port_ctrl(priv->cpu_port)); + + /* CPU port joins Lookup Miss Flooding Portmask */ + // TODO: The code below should also work for the RTL838x + sw_w32(0x28000, RTL839X_TBL_ACCESS_L2_CTRL); + sw_w32_mask(0, 0x80000000, RTL839X_TBL_ACCESS_L2_DATA(0)); + sw_w32(0x38000, RTL839X_TBL_ACCESS_L2_CTRL); + + /* Force CPU port link up */ + sw_w32_mask(0, 3, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); +} + +static void rtl93xx_hw_en_rxtx(struct rtl838x_eth_priv *priv) +{ + int i, pos; + u32 v; + + /* Setup CPU-Port: RX Buffer truncated at 1600 Bytes */ + sw_w32(0x06400040, priv->r->dma_if_ctrl); + + for (i = 0; i < priv->rxrings; i++) { + pos = (i % 3) * 10; + sw_w32_mask(0x3ff << pos, priv->rxringlen << pos, priv->r->dma_if_rx_ring_size(i)); + + // Some SoCs have issues with missing underflow protection + v = (sw_r32(priv->r->dma_if_rx_ring_cntr(i)) >> pos) & 0x3ff; + sw_w32_mask(0x3ff << pos, v, priv->r->dma_if_rx_ring_cntr(i)); + } + + /* Enable Notify, RX done, RX overflow and TX done interrupts */ + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_runout_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_done_msk); + sw_w32(0x0000000f, priv->r->dma_if_intr_tx_done_msk); + + /* Enable DMA */ + sw_w32_mask(0, RX_EN_93XX | TX_EN_93XX, priv->r->dma_if_ctrl); + + /* Restart TX/RX to CPU port, enable CRC checking */ + sw_w32_mask(0x0, 0x3 | BIT(4), priv->r->mac_port_ctrl(priv->cpu_port)); + + sw_w32_mask(0, BIT(priv->cpu_port), RTL930X_L2_UNKN_UC_FLD_PMSK); + sw_w32(0x217, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); +} + +static void rtl838x_setup_ring_buffer(struct rtl838x_eth_priv *priv, struct ring_b *ring) +{ + int i, j; + + struct p_hdr *h; + + for (i = 0; i < priv->rxrings; i++) { + for (j = 0; j < priv->rxringlen; j++) { + h = &ring->rx_header[i][j]; + memset(h, 0, sizeof(struct p_hdr)); + h->buf = (u8 *)KSEG1ADDR(ring->rx_space + + i * priv->rxringlen * RING_BUFFER + + j * RING_BUFFER); + h->size = RING_BUFFER; + /* All rings owned by switch, last one wraps */ + ring->rx_r[i][j] = KSEG1ADDR(h) | 1 + | (j == (priv->rxringlen - 1) ? WRAP : 0); + } + ring->c_rx[i] = 0; + } + + for (i = 0; i < TXRINGS; i++) { + for (j = 0; j < TXRINGLEN; j++) { + h = &ring->tx_header[i][j]; + memset(h, 0, sizeof(struct p_hdr)); + h->buf = (u8 *)KSEG1ADDR(ring->tx_space + + i * TXRINGLEN * RING_BUFFER + + j * RING_BUFFER); + h->size = RING_BUFFER; + ring->tx_r[i][j] = KSEG1ADDR(&ring->tx_header[i][j]); + } + /* Last header is wrapping around */ + ring->tx_r[i][j-1] |= WRAP; + ring->c_tx[i] = 0; + } +} + +static void rtl839x_setup_notify_ring_buffer(struct rtl838x_eth_priv *priv) +{ + int i; + struct notify_b *b = priv->membase + sizeof(struct ring_b); + + for (i = 0; i < NOTIFY_BLOCKS; i++) + b->ring[i] = KSEG1ADDR(&b->blocks[i]) | 1 | (i == (NOTIFY_BLOCKS - 1) ? WRAP : 0); + + sw_w32((u32) b->ring, RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL); + sw_w32_mask(0x3ff << 2, 100 << 2, RTL839X_L2_NOTIFICATION_CTRL); + + /* Setup notification events */ + sw_w32_mask(0, 1 << 14, RTL839X_L2_CTRL_0); // RTL8390_L2_CTRL_0_FLUSH_NOTIFY_EN + sw_w32_mask(0, 1 << 12, RTL839X_L2_NOTIFICATION_CTRL); // SUSPEND_NOTIFICATION_EN + + /* Enable Notification */ + sw_w32_mask(0, 1 << 0, RTL839X_L2_NOTIFICATION_CTRL); + priv->lastEvent = 0; +} + +static int rtl838x_eth_open(struct net_device *ndev) +{ + unsigned long flags; + struct rtl838x_eth_priv *priv = netdev_priv(ndev); + struct ring_b *ring = priv->membase; + int i, err; + + pr_debug("%s called: RX rings %d(length %d), TX rings %d(length %d)\n", + __func__, priv->rxrings, priv->rxringlen, TXRINGS, TXRINGLEN); + + spin_lock_irqsave(&priv->lock, flags); + rtl838x_hw_reset(priv); + rtl838x_setup_ring_buffer(priv, ring); + if (priv->family_id == RTL8390_FAMILY_ID) { + rtl839x_setup_notify_ring_buffer(priv); + /* Make sure the ring structure is visible to the ASIC */ + mb(); + flush_cache_all(); + } + + rtl838x_hw_ring_setup(priv); + err = request_irq(ndev->irq, priv->r->net_irq, IRQF_SHARED, ndev->name, ndev); + if (err) { + netdev_err(ndev, "%s: could not acquire interrupt: %d\n", + __func__, err); + return err; + } + phylink_start(priv->phylink); + + for (i = 0; i < priv->rxrings; i++) + napi_enable(&priv->rx_qs[i].napi); + + switch (priv->family_id) { + case RTL8380_FAMILY_ID: + rtl838x_hw_en_rxtx(priv); + /* Trap IGMP/MLD traffic to CPU-Port */ + sw_w32(0x3, RTL838X_SPCL_TRAP_IGMP_CTRL); + /* Flush learned FDB entries on link down of a port */ + sw_w32_mask(0, BIT(7), RTL838X_L2_CTRL_0); + break; + + case RTL8390_FAMILY_ID: + rtl839x_hw_en_rxtx(priv); + // Trap MLD and IGMP messages to CPU_PORT + sw_w32(0x3, RTL839X_SPCL_TRAP_IGMP_CTRL); + /* Flush learned FDB entries on link down of a port */ + sw_w32_mask(0, BIT(7), RTL839X_L2_CTRL_0); + break; + + case RTL9300_FAMILY_ID: + rtl93xx_hw_en_rxtx(priv); + /* Flush learned FDB entries on link down of a port */ + sw_w32_mask(0, BIT(7), RTL930X_L2_CTRL); + // Trap MLD and IGMP messages to CPU_PORT + sw_w32((0x2 << 3) | 0x2, RTL930X_VLAN_APP_PKT_CTRL); + break; + + case RTL9310_FAMILY_ID: + rtl93xx_hw_en_rxtx(priv); + break; + } + + netif_tx_start_all_queues(ndev); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static void rtl838x_hw_stop(struct rtl838x_eth_priv *priv) +{ + u32 force_mac = priv->family_id == RTL8380_FAMILY_ID ? 0x6192C : 0x75; + u32 clear_irq = priv->family_id == RTL8380_FAMILY_ID ? 0x000fffff : 0x007fffff; + int i; + + // Disable RX/TX from/to CPU-port + sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(priv->cpu_port)); + + /* Disable traffic */ + if (priv->family_id == RTL9300_FAMILY_ID || priv->family_id == RTL9310_FAMILY_ID) + sw_w32_mask(RX_EN_93XX | TX_EN_93XX, 0, priv->r->dma_if_ctrl); + else + sw_w32_mask(RX_EN | TX_EN, 0, priv->r->dma_if_ctrl); + mdelay(200); // Test, whether this is needed + + /* Block all ports */ + if (priv->family_id == RTL8380_FAMILY_ID) { + sw_w32(0x03000000, RTL838X_TBL_ACCESS_DATA_0(0)); + sw_w32(0x00000000, RTL838X_TBL_ACCESS_DATA_0(1)); + sw_w32(1 << 15 | 2 << 12, RTL838X_TBL_ACCESS_CTRL_0); + } + + /* Flush L2 address cache */ + if (priv->family_id == RTL8380_FAMILY_ID) { + for (i = 0; i <= priv->cpu_port; i++) { + sw_w32(1 << 26 | 1 << 23 | i << 5, priv->r->l2_tbl_flush_ctrl); + do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 26)); + } + } else if (priv->family_id == RTL8390_FAMILY_ID) { + for (i = 0; i <= priv->cpu_port; i++) { + sw_w32(1 << 28 | 1 << 25 | i << 5, priv->r->l2_tbl_flush_ctrl); + do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 28)); + } + } + // TODO: L2 flush register is 64 bit on RTL931X and 930X + + /* CPU-Port: Link down */ + if (priv->family_id == RTL8380_FAMILY_ID || priv->family_id == RTL8390_FAMILY_ID) + sw_w32(force_mac, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); + else + sw_w32_mask(0x3, 0, priv->r->mac_force_mode_ctrl + priv->cpu_port *4); + mdelay(100); + + /* Disable all TX/RX interrupts */ + if (priv->family_id == RTL9300_FAMILY_ID || priv->family_id == RTL9310_FAMILY_ID) { + sw_w32(0x00000000, priv->r->dma_if_intr_rx_runout_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_runout_sts); + sw_w32(0x00000000, priv->r->dma_if_intr_rx_done_msk); + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_done_sts); + sw_w32(0x00000000, priv->r->dma_if_intr_tx_done_msk); + sw_w32(0x0000000f, priv->r->dma_if_intr_tx_done_sts); + } else { + sw_w32(0x00000000, priv->r->dma_if_intr_msk); + sw_w32(clear_irq, priv->r->dma_if_intr_sts); + } + + /* Disable TX/RX DMA */ + sw_w32(0x00000000, priv->r->dma_if_ctrl); + mdelay(200); +} + +static int rtl838x_eth_stop(struct net_device *ndev) +{ + unsigned long flags; + int i; + struct rtl838x_eth_priv *priv = netdev_priv(ndev); + + pr_info("in %s\n", __func__); + + spin_lock_irqsave(&priv->lock, flags); + phylink_stop(priv->phylink); + rtl838x_hw_stop(priv); + free_irq(ndev->irq, ndev); + + for (i = 0; i < priv->rxrings; i++) + napi_disable(&priv->rx_qs[i].napi); + + netif_tx_stop_all_queues(ndev); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static void rtl839x_eth_set_multicast_list(struct net_device *ndev) +{ + if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { + sw_w32(0x0, RTL839X_RMA_CTRL_0); + sw_w32(0x0, RTL839X_RMA_CTRL_1); + sw_w32(0x0, RTL839X_RMA_CTRL_2); + sw_w32(0x0, RTL839X_RMA_CTRL_3); + } + if (ndev->flags & IFF_ALLMULTI) { + sw_w32(0x7fffffff, RTL839X_RMA_CTRL_0); + sw_w32(0x7fffffff, RTL839X_RMA_CTRL_1); + sw_w32(0x7fffffff, RTL839X_RMA_CTRL_2); + } + if (ndev->flags & IFF_PROMISC) { + sw_w32(0x7fffffff, RTL839X_RMA_CTRL_0); + sw_w32(0x7fffffff, RTL839X_RMA_CTRL_1); + sw_w32(0x7fffffff, RTL839X_RMA_CTRL_2); + sw_w32(0x3ff, RTL839X_RMA_CTRL_3); + } +} + +static void rtl838x_eth_set_multicast_list(struct net_device *ndev) +{ + struct rtl838x_eth_priv *priv = netdev_priv(ndev); + + if (priv->family_id == RTL8390_FAMILY_ID) + return rtl839x_eth_set_multicast_list(ndev); + + if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { + sw_w32(0x0, RTL838X_RMA_CTRL_0); + sw_w32(0x0, RTL838X_RMA_CTRL_1); + } + if (ndev->flags & IFF_ALLMULTI) + sw_w32(0x1fffff, RTL838X_RMA_CTRL_0); + if (ndev->flags & IFF_PROMISC) { + sw_w32(0x1fffff, RTL838X_RMA_CTRL_0); + sw_w32(0x7fff, RTL838X_RMA_CTRL_1); + } +} + +static void rtl930x_eth_set_multicast_list(struct net_device *ndev) +{ + if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { + sw_w32(0x0, RTL930X_RMA_CTRL_0); + sw_w32(0x0, RTL930X_RMA_CTRL_1); + sw_w32(0x0, RTL930X_RMA_CTRL_2); + } + if (ndev->flags & IFF_ALLMULTI) { + sw_w32(0x7fffffff, RTL930X_RMA_CTRL_0); + sw_w32(0x7fffffff, RTL930X_RMA_CTRL_1); + sw_w32(0x7fffffff, RTL930X_RMA_CTRL_2); + } + if (ndev->flags & IFF_PROMISC) { + sw_w32(0x7fffffff, RTL930X_RMA_CTRL_0); + sw_w32(0x7fffffff, RTL930X_RMA_CTRL_1); + sw_w32(0x7fffffff, RTL930X_RMA_CTRL_2); + } +} + +static void rtl931x_eth_set_multicast_list(struct net_device *ndev) +{ + if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { + sw_w32(0x0, RTL931X_RMA_CTRL_0); + sw_w32(0x0, RTL931X_RMA_CTRL_1); + sw_w32(0x0, RTL931X_RMA_CTRL_2); + } + if (ndev->flags & IFF_ALLMULTI) { + sw_w32(0x7fffffff, RTL931X_RMA_CTRL_0); + sw_w32(0x7fffffff, RTL931X_RMA_CTRL_1); + sw_w32(0x7fffffff, RTL931X_RMA_CTRL_2); + } + if (ndev->flags & IFF_PROMISC) { + sw_w32(0x7fffffff, RTL931X_RMA_CTRL_0); + sw_w32(0x7fffffff, RTL931X_RMA_CTRL_1); + sw_w32(0x7fffffff, RTL931X_RMA_CTRL_2); + } +} + +static void rtl838x_eth_tx_timeout(struct net_device *ndev) +{ + unsigned long flags; + struct rtl838x_eth_priv *priv = netdev_priv(ndev); + + pr_warn("%s\n", __func__); + spin_lock_irqsave(&priv->lock, flags); + rtl838x_hw_stop(priv); + rtl838x_hw_ring_setup(priv); + rtl838x_hw_en_rxtx(priv); + netif_trans_update(ndev); + netif_start_queue(ndev); + spin_unlock_irqrestore(&priv->lock, flags); +} + +static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev) +{ + int len, i; + struct rtl838x_eth_priv *priv = netdev_priv(dev); + struct ring_b *ring = priv->membase; + uint32_t val; + int ret; + unsigned long flags; + struct p_hdr *h; + int dest_port = -1; + int q = skb_get_queue_mapping(skb) % TXRINGS; + + if (q) // Check for high prio queue + pr_debug("SKB priority: %d\n", skb->priority); + + spin_lock_irqsave(&priv->lock, flags); + len = skb->len; + + /* Check for DSA tagging at the end of the buffer */ + if (netdev_uses_dsa(dev) && skb->data[len-4] == 0x80 && skb->data[len-3] > 0 + && skb->data[len-3] < priv->cpu_port && skb->data[len-2] == 0x10 + && skb->data[len-1] == 0x00) { + /* Reuse tag space for CRC if possible */ + dest_port = skb->data[len-3]; + skb->data[len-4] = skb->data[len-3] = skb->data[len-2] = skb->data[len-1] = 0x00; + len -= 4; + } + + len += 4; // Add space for CRC + + if (skb_padto(skb, len)) { + ret = NETDEV_TX_OK; + goto txdone; + } + + /* We can send this packet if CPU owns the descriptor */ + if (!(ring->tx_r[q][ring->c_tx[q]] & 0x1)) { + + /* Set descriptor for tx */ + h = &ring->tx_header[q][ring->c_tx[q]]; + h->size = len; + h->len = len; + // On RTL8380 SoCs, small packet lengths being sent need adjustments + if (priv->family_id == RTL8380_FAMILY_ID) { + if (len < ETH_ZLEN - 4) + h->len -= 4; + } + + priv->r->create_tx_header(h, dest_port, skb->priority >> 1); + + /* Copy packet data to tx buffer */ + memcpy((void *)KSEG1ADDR(h->buf), skb->data, len); + /* Make sure packet data is visible to ASIC */ + wmb(); + + /* Hand over to switch */ + ring->tx_r[q][ring->c_tx[q]] |= 1; + + // Before starting TX, prevent a Lextra bus bug on RTL8380 SoCs + if (priv->family_id == RTL8380_FAMILY_ID) { + for (i = 0; i < 10; i++) { + val = sw_r32(priv->r->dma_if_ctrl); + if ((val & 0xc) == 0xc) + break; + } + } + + /* Tell switch to send data */ + if (priv->family_id == RTL9310_FAMILY_ID + || priv->family_id == RTL9300_FAMILY_ID) { + // Ring ID q == 0: Low priority, Ring ID = 1: High prio queue + if (!q) + sw_w32_mask(0, BIT(2), priv->r->dma_if_ctrl); + else + sw_w32_mask(0, BIT(3), priv->r->dma_if_ctrl); + } else { + sw_w32_mask(0, TX_DO, priv->r->dma_if_ctrl); + } + + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; + dev_kfree_skb(skb); + ring->c_tx[q] = (ring->c_tx[q] + 1) % TXRINGLEN; + ret = NETDEV_TX_OK; + } else { + dev_warn(&priv->pdev->dev, "Data is owned by switch\n"); + ret = NETDEV_TX_BUSY; + } +txdone: + spin_unlock_irqrestore(&priv->lock, flags); + return ret; +} + +/* + * Return queue number for TX. On the RTL83XX, these queues have equal priority + * so we do round-robin + */ +u16 rtl83xx_pick_tx_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev) +{ + static u8 last = 0; + + last++; + return last % TXRINGS; +} + +/* + * Return queue number for TX. On the RTL93XX, queue 1 is the high priority queue + */ +u16 rtl93xx_pick_tx_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev) +{ + if (skb->priority >= TC_PRIO_CONTROL) + return 1; + return 0; +} + +static int rtl838x_hw_receive(struct net_device *dev, int r, int budget) +{ + struct rtl838x_eth_priv *priv = netdev_priv(dev); + struct ring_b *ring = priv->membase; + struct sk_buff *skb; + unsigned long flags; + int i, len, work_done = 0; + u8 *data, *skb_data; + unsigned int val; + u32 *last; + struct p_hdr *h; + bool dsa = netdev_uses_dsa(dev); + struct dsa_tag tag; + + spin_lock_irqsave(&priv->lock, flags); + last = (u32 *)KSEG1ADDR(sw_r32(priv->r->dma_if_rx_cur + r * 4)); + pr_debug("---------------------------------------------------------- RX - %d\n", r); + + do { + if ((ring->rx_r[r][ring->c_rx[r]] & 0x1)) { + if (&ring->rx_r[r][ring->c_rx[r]] != last) { + netdev_warn(dev, "Ring contention: r: %x, last %x, cur %x\n", + r, (uint32_t)last, (u32) &ring->rx_r[r][ring->c_rx[r]]); + } + break; + } + + h = &ring->rx_header[r][ring->c_rx[r]]; + data = (u8 *)KSEG1ADDR(h->buf); + len = h->len; + if (!len) + break; + work_done++; + + len -= 4; /* strip the CRC */ + /* Add 4 bytes for cpu_tag */ + if (dsa) + len += 4; + + skb = alloc_skb(len + 4, GFP_KERNEL); + skb_reserve(skb, NET_IP_ALIGN); + + if (likely(skb)) { + /* BUG: Prevent bug on RTL838x SoCs*/ + if (priv->family_id == RTL8380_FAMILY_ID) { + sw_w32(0xffffffff, priv->r->dma_if_rx_ring_size(0)); + for (i = 0; i < priv->rxrings; i++) { + /* Update each ring cnt */ + val = sw_r32(priv->r->dma_if_rx_ring_cntr(i)); + sw_w32(val, priv->r->dma_if_rx_ring_cntr(i)); + } + } + + skb_data = skb_put(skb, len); + /* Make sure data is visible */ + mb(); + memcpy(skb->data, (u8 *)KSEG1ADDR(data), len); + /* Overwrite CRC with cpu_tag */ + if (dsa) { + priv->r->decode_tag(h, &tag); + skb->data[len-4] = 0x80; + skb->data[len-3] = tag.port; + skb->data[len-2] = 0x10; + skb->data[len-1] = 0x00; + if (tag.l2_offloaded) + skb->data[len-3] |= 0x40; + } + + if (tag.queue >= 0) + pr_debug("Queue: %d, len: %d, reason %d port %d\n", + tag.queue, len, tag.reason, tag.port); + + skb->protocol = eth_type_trans(skb, dev); + if (dev->features & NETIF_F_RXCSUM) { + if (tag.crc_error) + skb_checksum_none_assert(skb); + else + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; + + netif_receive_skb(skb); + } else { + if (net_ratelimit()) + dev_warn(&dev->dev, "low on memory - packet dropped\n"); + dev->stats.rx_dropped++; + } + + /* Reset header structure */ + memset(h, 0, sizeof(struct p_hdr)); + h->buf = data; + h->size = RING_BUFFER; + + ring->rx_r[r][ring->c_rx[r]] = KSEG1ADDR(h) | 0x1 + | (ring->c_rx[r] == (priv->rxringlen - 1) ? WRAP : 0x1); + ring->c_rx[r] = (ring->c_rx[r] + 1) % priv->rxringlen; + last = (u32 *)KSEG1ADDR(sw_r32(priv->r->dma_if_rx_cur + r * 4)); + } while (&ring->rx_r[r][ring->c_rx[r]] != last && work_done < budget); + + // Update counters + priv->r->update_cntr(r, 0); + + spin_unlock_irqrestore(&priv->lock, flags); + return work_done; +} + +static int rtl838x_poll_rx(struct napi_struct *napi, int budget) +{ + struct rtl838x_rx_q *rx_q = container_of(napi, struct rtl838x_rx_q, napi); + struct rtl838x_eth_priv *priv = rx_q->priv; + int work_done = 0; + int r = rx_q->id; + int work; + + while (work_done < budget) { + work = rtl838x_hw_receive(priv->netdev, r, budget - work_done); + if (!work) + break; + work_done += work; + } + + if (work_done < budget) { + napi_complete_done(napi, work_done); + + /* Enable RX interrupt */ + if (priv->family_id == RTL9300_FAMILY_ID || priv->family_id == RTL9310_FAMILY_ID) + sw_w32(0xffffffff, priv->r->dma_if_intr_rx_done_msk); + else + sw_w32_mask(0, 0xf00ff | BIT(r + 8), priv->r->dma_if_intr_msk); + } + return work_done; +} + + +static void rtl838x_validate(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + pr_debug("In %s\n", __func__); + + if (!phy_interface_mode_is_rgmii(state->interface) && + state->interface != PHY_INTERFACE_MODE_1000BASEX && + state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII && + state->interface != PHY_INTERFACE_MODE_GMII && + state->interface != PHY_INTERFACE_MODE_QSGMII && + state->interface != PHY_INTERFACE_MODE_INTERNAL && + state->interface != PHY_INTERFACE_MODE_SGMII) { + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + pr_err("Unsupported interface: %d\n", state->interface); + return; + } + + /* Allow all the expected bits */ + phylink_set(mask, Autoneg); + phylink_set_port_modes(mask); + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + + /* With the exclusion of MII and Reverse MII, we support Gigabit, + * including Half duplex + */ + if (state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseT_Half); + } + + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + + bitmap_and(supported, supported, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + + +static void rtl838x_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state) +{ + /* This is only being called for the master device, + * i.e. the CPU-Port. We don't need to do anything. + */ + + pr_info("In %s, mode %x\n", __func__, mode); +} + +static void rtl838x_mac_an_restart(struct phylink_config *config) +{ + struct net_device *dev = container_of(config->dev, struct net_device, dev); + struct rtl838x_eth_priv *priv = netdev_priv(dev); + + /* This works only on RTL838x chips */ + if (priv->family_id != RTL8380_FAMILY_ID) + return; + + pr_debug("In %s\n", __func__); + /* Restart by disabling and re-enabling link */ + sw_w32(0x6192D, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); + mdelay(20); + sw_w32(0x6192F, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); +} + +static int rtl838x_mac_pcs_get_state(struct phylink_config *config, + struct phylink_link_state *state) +{ + u32 speed; + struct net_device *dev = container_of(config->dev, struct net_device, dev); + struct rtl838x_eth_priv *priv = netdev_priv(dev); + int port = priv->cpu_port; + + pr_debug("In %s\n", __func__); + + state->link = priv->r->get_mac_link_sts(port) ? 1 : 0; + state->duplex = priv->r->get_mac_link_dup_sts(port) ? 1 : 0; + + speed = priv->r->get_mac_link_spd_sts(port); + switch (speed) { + case 0: + state->speed = SPEED_10; + break; + case 1: + state->speed = SPEED_100; + break; + case 2: + state->speed = SPEED_1000; + break; + default: + state->speed = SPEED_UNKNOWN; + break; + } + + state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); + if (priv->r->get_mac_rx_pause_sts(port)) + state->pause |= MLO_PAUSE_RX; + if (priv->r->get_mac_tx_pause_sts(port)) + state->pause |= MLO_PAUSE_TX; + + return 1; +} + +static void rtl838x_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) +{ + struct net_device *dev = container_of(config->dev, struct net_device, dev); + struct rtl838x_eth_priv *priv = netdev_priv(dev); + + pr_debug("In %s\n", __func__); + /* Stop TX/RX to port */ + sw_w32_mask(0x03, 0, priv->r->mac_port_ctrl(priv->cpu_port)); +} + +static void rtl838x_mac_link_up(struct phylink_config *config, unsigned int mode, + phy_interface_t interface, + struct phy_device *phy) +{ + struct net_device *dev = container_of(config->dev, struct net_device, dev); + struct rtl838x_eth_priv *priv = netdev_priv(dev); + + pr_debug("In %s\n", __func__); + /* Restart TX/RX to port */ + sw_w32_mask(0, 0x03, priv->r->mac_port_ctrl(priv->cpu_port)); +} + +static void rtl838x_set_mac_hw(struct net_device *dev, u8 *mac) +{ + struct rtl838x_eth_priv *priv = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + pr_debug("In %s\n", __func__); + sw_w32((mac[0] << 8) | mac[1], priv->r->mac); + sw_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], priv->r->mac + 4); + + if (priv->family_id == RTL8380_FAMILY_ID) { + /* 2 more registers, ALE/MAC block */ + sw_w32((mac[0] << 8) | mac[1], RTL838X_MAC_ALE); + sw_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + (RTL838X_MAC_ALE + 4)); + + sw_w32((mac[0] << 8) | mac[1], RTL838X_MAC2); + sw_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + RTL838X_MAC2 + 4); + } + spin_unlock_irqrestore(&priv->lock, flags); +} + +static int rtl838x_set_mac_address(struct net_device *dev, void *p) +{ + struct rtl838x_eth_priv *priv = netdev_priv(dev); + const struct sockaddr *addr = p; + u8 *mac = (u8 *) (addr->sa_data); + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + rtl838x_set_mac_hw(dev, mac); + + pr_info("Using MAC %08x%08x\n", sw_r32(priv->r->mac), sw_r32(priv->r->mac + 4)); + return 0; +} + +static int rtl8390_init_mac(struct rtl838x_eth_priv *priv) +{ + // We will need to set-up EEE and the egress-rate limitation + return 0; +} + +static int rtl8380_init_mac(struct rtl838x_eth_priv *priv) +{ + int i; + + if (priv->family_id == 0x8390) + return rtl8390_init_mac(priv); + + pr_info("%s\n", __func__); + /* fix timer for EEE */ + sw_w32(0x5001411, RTL838X_EEE_TX_TIMER_GIGA_CTRL); + sw_w32(0x5001417, RTL838X_EEE_TX_TIMER_GELITE_CTRL); + + /* Init VLAN */ + if (priv->id == 0x8382) { + for (i = 0; i <= 28; i++) + sw_w32(0, 0xd57c + i * 0x80); + } + if (priv->id == 0x8380) { + for (i = 8; i <= 28; i++) + sw_w32(0, 0xd57c + i * 0x80); + } + return 0; +} + +static int rtl838x_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) +{ + struct rtl838x_eth_priv *priv = netdev_priv(ndev); + + pr_debug("%s called\n", __func__); + return phylink_ethtool_ksettings_get(priv->phylink, cmd); +} + +static int rtl838x_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) +{ + struct rtl838x_eth_priv *priv = netdev_priv(ndev); + + pr_debug("%s called\n", __func__); + return phylink_ethtool_ksettings_set(priv->phylink, cmd); +} + +static int rtl838x_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + u32 val; + int err; + struct rtl838x_eth_priv *priv = bus->priv; + + if (mii_id >= 24 && mii_id <= 27 && priv->id == 0x8380) + return rtl838x_read_sds_phy(mii_id, regnum); + err = rtl838x_read_phy(mii_id, 0, regnum, &val); + if (err) + return err; + return val; +} + +static int rtl839x_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + u32 val; + int err; + struct rtl838x_eth_priv *priv = bus->priv; + + if (mii_id >= 48 && mii_id <= 49 && priv->id == 0x8393) + return rtl839x_read_sds_phy(mii_id, regnum); + + err = rtl839x_read_phy(mii_id, 0, regnum, &val); + if (err) + return err; + return val; +} + +static int rtl930x_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + u32 val; + int err; + + // TODO: These are hard-coded for the 2 Fibre Ports of the XGS1210 + if (mii_id >= 26 && mii_id <= 27) + return rtl930x_read_sds_phy(mii_id - 18, 0, regnum); + + if (regnum & MII_ADDR_C45) { + regnum &= ~MII_ADDR_C45; + err = rtl930x_read_mmd_phy(mii_id, regnum >> 16, regnum & 0xffff, &val); + } else { + err = rtl930x_read_phy(mii_id, 0, regnum, &val); + } + if (err) + return err; + return val; +} + +static int rtl931x_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + u32 val; + int err; +// struct rtl838x_eth_priv *priv = bus->priv; + +// if (mii_id >= 48 && mii_id <= 49 && priv->id == 0x8393) +// return rtl839x_read_sds_phy(mii_id, regnum); + + err = rtl931x_read_phy(mii_id, 0, regnum, &val); + if (err) + return err; + return val; +} + +static int rtl838x_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ + u32 offset = 0; + struct rtl838x_eth_priv *priv = bus->priv; + + if (mii_id >= 24 && mii_id <= 27 && priv->id == 0x8380) { + if (mii_id == 26) + offset = 0x100; + sw_w32(value, RTL838X_SDS4_FIB_REG0 + offset + (regnum << 2)); + return 0; + } + return rtl838x_write_phy(mii_id, 0, regnum, value); +} + +static int rtl839x_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ + struct rtl838x_eth_priv *priv = bus->priv; + + if (mii_id >= 48 && mii_id <= 49 && priv->id == 0x8393) + return rtl839x_write_sds_phy(mii_id, regnum, value); + + return rtl839x_write_phy(mii_id, 0, regnum, value); +} + +static int rtl930x_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ +// struct rtl838x_eth_priv *priv = bus->priv; + +// if (mii_id >= 48 && mii_id <= 49 && priv->id == 0x8393) +// return rtl839x_write_sds_phy(mii_id, regnum, value); + if (regnum & MII_ADDR_C45) { + regnum &= ~MII_ADDR_C45; + return rtl930x_write_mmd_phy(mii_id, regnum >> 16, regnum & 0xffff, value); + } + + return rtl930x_write_phy(mii_id, 0, regnum, value); +} + +static int rtl931x_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ +// struct rtl838x_eth_priv *priv = bus->priv; + +// if (mii_id >= 48 && mii_id <= 49 && priv->id == 0x8393) +// return rtl839x_write_sds_phy(mii_id, regnum, value); + + return rtl931x_write_phy(mii_id, 0, regnum, value); +} + +static int rtl838x_mdio_reset(struct mii_bus *bus) +{ + pr_debug("%s called\n", __func__); + /* Disable MAC polling the PHY so that we can start configuration */ + sw_w32(0x00000000, RTL838X_SMI_POLL_CTRL); + + /* Enable PHY control via SoC */ + sw_w32_mask(0, 1 << 15, RTL838X_SMI_GLB_CTRL); + + // Probably should reset all PHYs here... + return 0; +} + +static int rtl839x_mdio_reset(struct mii_bus *bus) +{ + return 0; + + pr_debug("%s called\n", __func__); + /* BUG: The following does not work, but should! */ + /* Disable MAC polling the PHY so that we can start configuration */ + sw_w32(0x00000000, RTL839X_SMI_PORT_POLLING_CTRL); + sw_w32(0x00000000, RTL839X_SMI_PORT_POLLING_CTRL + 4); + /* Disable PHY polling via SoC */ + sw_w32_mask(1 << 7, 0, RTL839X_SMI_GLB_CTRL); + + // Probably should reset all PHYs here... + return 0; +} + +static int rtl931x_mdio_reset(struct mii_bus *bus) +{ + sw_w32(0x00000000, RTL931X_SMI_PORT_POLLING_CTRL); + sw_w32(0x00000000, RTL931X_SMI_PORT_POLLING_CTRL + 4); + + pr_debug("%s called\n", __func__); + + return 0; +} + +static int rtl930x_mdio_reset(struct mii_bus *bus) +{ + int i; + int pos; + + pr_info("RTL930X_SMI_PORT0_15_POLLING_SEL %08x 16-27: %08x\n", + sw_r32(RTL930X_SMI_PORT0_15_POLLING_SEL), + sw_r32(RTL930X_SMI_PORT16_27_POLLING_SEL)); + + pr_info("%s: Enable SMI polling on SMI bus 0, SMI1, SMI2, disable on SMI3\n", __func__); + sw_w32_mask(BIT(20) | BIT(21) | BIT(22), BIT(23), RTL930X_SMI_GLB_CTRL); + + pr_info("RTL9300 Powering on SerDes ports\n"); + rtl9300_sds_power(24, 1); + rtl9300_sds_power(25, 1); + rtl9300_sds_power(26, 1); + rtl9300_sds_power(27, 1); + mdelay(200); + + // RTL930X_SMI_PORT0_15_POLLING_SEL 55550000 16-27: 00f9aaaa + // i.e SMI=0 for all ports + for (i = 0; i < 5; i++) + pr_info("port phy: %08x\n", sw_r32(RTL930X_SMI_PORT0_5_ADDR + i *4)); + + // 1-to-1 mapping of port to phy-address + for (i = 0; i < 24; i++) { + pos = (i % 6) * 5; + sw_w32_mask(0x1f << pos, i << pos, RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4); + } + + // ports 24 and 25 have PHY addresses 8 and 9, ports 26/27 PHY 26/27 + sw_w32(8 | 9 << 5 | 26 << 10 | 27 << 15, RTL930X_SMI_PORT0_5_ADDR + 4 * 4); + + // Ports 24 and 25 live on SMI bus 1 and 2 + sw_w32_mask(0x3 << 16, 0x1 << 16, RTL930X_SMI_PORT16_27_POLLING_SEL); + sw_w32_mask(0x3 << 18, 0x2 << 18, RTL930X_SMI_PORT16_27_POLLING_SEL); + + // SMI bus 1 and 2 speak Clause 45 TODO: Configure from .dts + sw_w32_mask(0, BIT(17) | BIT(18), RTL930X_SMI_GLB_CTRL); + + // Ports 24 and 25 are 2.5 Gig, set this type (1) + sw_w32_mask(0x7 << 12, 1 << 12, RTL930X_SMI_MAC_TYPE_CTRL); + sw_w32_mask(0x7 << 15, 1 << 15, RTL930X_SMI_MAC_TYPE_CTRL); + + return 0; +} + +static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) +{ + struct device_node *mii_np; + int ret; + + pr_debug("%s called\n", __func__); + mii_np = of_get_child_by_name(priv->pdev->dev.of_node, "mdio-bus"); + + if (!mii_np) { + dev_err(&priv->pdev->dev, "no %s child node found", "mdio-bus"); + return -ENODEV; + } + + if (!of_device_is_available(mii_np)) { + ret = -ENODEV; + goto err_put_node; + } + + priv->mii_bus = devm_mdiobus_alloc(&priv->pdev->dev); + if (!priv->mii_bus) { + ret = -ENOMEM; + goto err_put_node; + } + + switch(priv->family_id) { + case RTL8380_FAMILY_ID: + priv->mii_bus->name = "rtl838x-eth-mdio"; + priv->mii_bus->read = rtl838x_mdio_read; + priv->mii_bus->write = rtl838x_mdio_write; + priv->mii_bus->reset = rtl838x_mdio_reset; + break; + case RTL8390_FAMILY_ID: + priv->mii_bus->name = "rtl839x-eth-mdio"; + priv->mii_bus->read = rtl839x_mdio_read; + priv->mii_bus->write = rtl839x_mdio_write; + priv->mii_bus->reset = rtl839x_mdio_reset; + break; + case RTL9300_FAMILY_ID: + priv->mii_bus->name = "rtl930x-eth-mdio"; + priv->mii_bus->read = rtl930x_mdio_read; + priv->mii_bus->write = rtl930x_mdio_write; + priv->mii_bus->reset = rtl930x_mdio_reset; + // priv->mii_bus->probe_capabilities = MDIOBUS_C22_C45; TODO for linux 5.9 + break; + case RTL9310_FAMILY_ID: + priv->mii_bus->name = "rtl931x-eth-mdio"; + priv->mii_bus->read = rtl931x_mdio_read; + priv->mii_bus->write = rtl931x_mdio_write; + priv->mii_bus->reset = rtl931x_mdio_reset; +// priv->mii_bus->probe_capabilities = MDIOBUS_C22_C45; TODO for linux 5.9 + break; + } + priv->mii_bus->priv = priv; + priv->mii_bus->parent = &priv->pdev->dev; + + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); + ret = of_mdiobus_register(priv->mii_bus, mii_np); + +err_put_node: + of_node_put(mii_np); + return ret; +} + +static int rtl838x_mdio_remove(struct rtl838x_eth_priv *priv) +{ + pr_debug("%s called\n", __func__); + if (!priv->mii_bus) + return 0; + + mdiobus_unregister(priv->mii_bus); + mdiobus_free(priv->mii_bus); + + return 0; +} + +static netdev_features_t rtl838x_fix_features(struct net_device *dev, + netdev_features_t features) +{ + return features; +} + +static int rtl83xx_set_features(struct net_device *dev, netdev_features_t features) +{ + struct rtl838x_eth_priv *priv = netdev_priv(dev); + + if ((features ^ dev->features) & NETIF_F_RXCSUM) { + if (!(features & NETIF_F_RXCSUM)) + sw_w32_mask(BIT(3), 0, priv->r->mac_port_ctrl(priv->cpu_port)); + else + sw_w32_mask(0, BIT(4), priv->r->mac_port_ctrl(priv->cpu_port)); + } + + return 0; +} + +static int rtl93xx_set_features(struct net_device *dev, netdev_features_t features) +{ + struct rtl838x_eth_priv *priv = netdev_priv(dev); + + if ((features ^ dev->features) & NETIF_F_RXCSUM) { + if (!(features & NETIF_F_RXCSUM)) + sw_w32_mask(BIT(4), 0, priv->r->mac_port_ctrl(priv->cpu_port)); + else + sw_w32_mask(0, BIT(4), priv->r->mac_port_ctrl(priv->cpu_port)); + } + + return 0; +} + +static const struct net_device_ops rtl838x_eth_netdev_ops = { + .ndo_open = rtl838x_eth_open, + .ndo_stop = rtl838x_eth_stop, + .ndo_start_xmit = rtl838x_eth_tx, + .ndo_select_queue = rtl83xx_pick_tx_queue, + .ndo_set_mac_address = rtl838x_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = rtl838x_eth_set_multicast_list, + .ndo_tx_timeout = rtl838x_eth_tx_timeout, + .ndo_set_features = rtl83xx_set_features, + .ndo_fix_features = rtl838x_fix_features, +}; + +static const struct net_device_ops rtl839x_eth_netdev_ops = { + .ndo_open = rtl838x_eth_open, + .ndo_stop = rtl838x_eth_stop, + .ndo_start_xmit = rtl838x_eth_tx, + .ndo_select_queue = rtl83xx_pick_tx_queue, + .ndo_set_mac_address = rtl838x_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = rtl839x_eth_set_multicast_list, + .ndo_tx_timeout = rtl838x_eth_tx_timeout, + .ndo_set_features = rtl83xx_set_features, + .ndo_fix_features = rtl838x_fix_features, +}; + +static const struct net_device_ops rtl930x_eth_netdev_ops = { + .ndo_open = rtl838x_eth_open, + .ndo_stop = rtl838x_eth_stop, + .ndo_start_xmit = rtl838x_eth_tx, + .ndo_select_queue = rtl93xx_pick_tx_queue, + .ndo_set_mac_address = rtl838x_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = rtl930x_eth_set_multicast_list, + .ndo_tx_timeout = rtl838x_eth_tx_timeout, + .ndo_set_features = rtl93xx_set_features, + .ndo_fix_features = rtl838x_fix_features, +}; + +static const struct net_device_ops rtl931x_eth_netdev_ops = { + .ndo_open = rtl838x_eth_open, + .ndo_stop = rtl838x_eth_stop, + .ndo_start_xmit = rtl838x_eth_tx, + .ndo_select_queue = rtl93xx_pick_tx_queue, + .ndo_set_mac_address = rtl838x_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = rtl931x_eth_set_multicast_list, + .ndo_tx_timeout = rtl838x_eth_tx_timeout, + .ndo_set_features = rtl93xx_set_features, + .ndo_fix_features = rtl838x_fix_features, +}; + +static const struct phylink_mac_ops rtl838x_phylink_ops = { + .validate = rtl838x_validate, + .mac_link_state = rtl838x_mac_pcs_get_state, + .mac_an_restart = rtl838x_mac_an_restart, + .mac_config = rtl838x_mac_config, + .mac_link_down = rtl838x_mac_link_down, + .mac_link_up = rtl838x_mac_link_up, +}; + +static const struct ethtool_ops rtl838x_ethtool_ops = { + .get_link_ksettings = rtl838x_get_link_ksettings, + .set_link_ksettings = rtl838x_set_link_ksettings, +}; + +static int __init rtl838x_eth_probe(struct platform_device *pdev) +{ + struct net_device *dev; + struct device_node *dn = pdev->dev.of_node; + struct rtl838x_eth_priv *priv; + struct resource *res, *mem; + phy_interface_t phy_mode; + struct phylink *phylink; + int err = 0, i, rxrings, rxringlen; + struct ring_b *ring; + + pr_info("Probing RTL838X eth device pdev: %x, dev: %x\n", + (u32)pdev, (u32)(&(pdev->dev))); + + if (!dn) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + rxrings = (soc_info.family == RTL8380_FAMILY_ID + || soc_info.family == RTL8390_FAMILY_ID) ? 8 : 32; + rxrings = rxrings > MAX_RXRINGS ? MAX_RXRINGS : rxrings; + rxringlen = MAX_ENTRIES / rxrings; + rxringlen = rxringlen > MAX_RXLEN ? MAX_RXLEN : rxringlen; + + dev = alloc_etherdev_mqs(sizeof(struct rtl838x_eth_priv), TXRINGS, rxrings); + if (!dev) { + err = -ENOMEM; + goto err_free; + } + SET_NETDEV_DEV(dev, &pdev->dev); + priv = netdev_priv(dev); + + /* obtain buffer memory space */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + mem = devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), res->name); + if (!mem) { + dev_err(&pdev->dev, "cannot request memory space\n"); + err = -ENXIO; + goto err_free; + } + + dev->mem_start = mem->start; + dev->mem_end = mem->end; + } else { + dev_err(&pdev->dev, "cannot request IO resource\n"); + err = -ENXIO; + goto err_free; + } + + /* Allocate buffer memory */ + priv->membase = dmam_alloc_coherent(&pdev->dev, rxrings * rxringlen * RING_BUFFER + + sizeof(struct ring_b) + sizeof(struct notify_b), + (void *)&dev->mem_start, GFP_KERNEL); + if (!priv->membase) { + dev_err(&pdev->dev, "cannot allocate DMA buffer\n"); + err = -ENOMEM; + goto err_free; + } + + // Allocate ring-buffer space at the end of the allocated memory + ring = priv->membase; + ring->rx_space = priv->membase + sizeof(struct ring_b) + sizeof(struct notify_b); + + spin_lock_init(&priv->lock); + + /* obtain device IRQ number */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "cannot obtain IRQ, using default 24\n"); + dev->irq = 24; + } else { + dev->irq = res->start; + } + dev->ethtool_ops = &rtl838x_ethtool_ops; + dev->min_mtu = ETH_ZLEN; + dev->max_mtu = 1536; + dev->features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM; + dev->hw_features = NETIF_F_RXCSUM; + + priv->id = soc_info.id; + priv->family_id = soc_info.family; + if (priv->id) { + pr_info("Found SoC ID: %4x: %s, family %x\n", + priv->id, soc_info.name, priv->family_id); + } else { + pr_err("Unknown chip id (%04x)\n", priv->id); + return -ENODEV; + } + + switch (priv->family_id) { + case RTL8380_FAMILY_ID: + priv->cpu_port = RTL838X_CPU_PORT; + priv->r = &rtl838x_reg; + dev->netdev_ops = &rtl838x_eth_netdev_ops; + break; + case RTL8390_FAMILY_ID: + priv->cpu_port = RTL839X_CPU_PORT; + priv->r = &rtl839x_reg; + dev->netdev_ops = &rtl839x_eth_netdev_ops; + break; + case RTL9300_FAMILY_ID: + priv->cpu_port = RTL930X_CPU_PORT; + priv->r = &rtl930x_reg; + dev->netdev_ops = &rtl930x_eth_netdev_ops; + break; + case RTL9310_FAMILY_ID: + priv->cpu_port = RTL931X_CPU_PORT; + priv->r = &rtl931x_reg; + dev->netdev_ops = &rtl931x_eth_netdev_ops; + break; + default: + pr_err("Unknown SoC family\n"); + return -ENODEV; + } + priv->rxringlen = rxringlen; + priv->rxrings = rxrings; + + rtl8380_init_mac(priv); + + /* try to get mac address in the following order: + * 1) from device tree data + * 2) from internal registers set by bootloader + */ + of_get_mac_address(pdev->dev.of_node, dev->dev_addr); + if (is_valid_ether_addr(dev->dev_addr)) { + rtl838x_set_mac_hw(dev, (u8 *)dev->dev_addr); + } else { + dev->dev_addr[0] = (sw_r32(priv->r->mac) >> 8) & 0xff; + dev->dev_addr[1] = sw_r32(priv->r->mac) & 0xff; + dev->dev_addr[2] = (sw_r32(priv->r->mac + 4) >> 24) & 0xff; + dev->dev_addr[3] = (sw_r32(priv->r->mac + 4) >> 16) & 0xff; + dev->dev_addr[4] = (sw_r32(priv->r->mac + 4) >> 8) & 0xff; + dev->dev_addr[5] = sw_r32(priv->r->mac + 4) & 0xff; + } + /* if the address is invalid, use a random value */ + if (!is_valid_ether_addr(dev->dev_addr)) { + struct sockaddr sa = { AF_UNSPEC }; + + netdev_warn(dev, "Invalid MAC address, using random\n"); + eth_hw_addr_random(dev); + memcpy(sa.sa_data, dev->dev_addr, ETH_ALEN); + if (rtl838x_set_mac_address(dev, &sa)) + netdev_warn(dev, "Failed to set MAC address.\n"); + } + pr_info("Using MAC %08x%08x\n", sw_r32(priv->r->mac), + sw_r32(priv->r->mac + 4)); + strcpy(dev->name, "eth%d"); + priv->pdev = pdev; + priv->netdev = dev; + + err = rtl838x_mdio_init(priv); + if (err) + goto err_free; + + err = register_netdev(dev); + if (err) + goto err_free; + + for (i = 0; i < priv->rxrings; i++) { + priv->rx_qs[i].id = i; + priv->rx_qs[i].priv = priv; + netif_napi_add(dev, &priv->rx_qs[i].napi, rtl838x_poll_rx, 64); + } + + platform_set_drvdata(pdev, dev); + + phy_mode = of_get_phy_mode(dn); + if (phy_mode < 0) { + dev_err(&pdev->dev, "incorrect phy-mode\n"); + err = -EINVAL; + goto err_free; + } + priv->phylink_config.dev = &dev->dev; + priv->phylink_config.type = PHYLINK_NETDEV; + + phylink = phylink_create(&priv->phylink_config, pdev->dev.fwnode, + phy_mode, &rtl838x_phylink_ops); + if (IS_ERR(phylink)) { + err = PTR_ERR(phylink); + goto err_free; + } + priv->phylink = phylink; + + return 0; + +err_free: + pr_err("Error setting up netdev, freeing it again.\n"); + free_netdev(dev); + return err; +} + +static int rtl838x_eth_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct rtl838x_eth_priv *priv = netdev_priv(dev); + int i; + + if (dev) { + pr_info("Removing platform driver for rtl838x-eth\n"); + rtl838x_mdio_remove(priv); + rtl838x_hw_stop(priv); + + netif_tx_stop_all_queues(dev); + + for (i = 0; i < priv->rxrings; i++) + netif_napi_del(&priv->rx_qs[i].napi); + + unregister_netdev(dev); + free_netdev(dev); + } + return 0; +} + +static const struct of_device_id rtl838x_eth_of_ids[] = { + { .compatible = "realtek,rtl838x-eth"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rtl838x_eth_of_ids); + +static struct platform_driver rtl838x_eth_driver = { + .probe = rtl838x_eth_probe, + .remove = rtl838x_eth_remove, + .driver = { + .name = "rtl838x-eth", + .pm = NULL, + .of_match_table = rtl838x_eth_of_ids, + }, +}; + +module_platform_driver(rtl838x_eth_driver); + +MODULE_AUTHOR("B. Koblitz"); +MODULE_DESCRIPTION("RTL838X SoC Ethernet Driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h new file mode 100644 index 0000000000..c7e97057b3 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h @@ -0,0 +1,429 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _RTL838X_ETH_H +#define _RTL838X_ETH_H + +/* + * Register definition + */ + +/* Per port MAC control */ +#define RTL838X_MAC_PORT_CTRL (0xd560) +#define RTL839X_MAC_PORT_CTRL (0x8004) +#define RTL930X_MAC_L2_PORT_CTRL (0x3268) +#define RTL930X_MAC_PORT_CTRL (0x3260) +#define RTL931X_MAC_L2_PORT_CTRL (0x6000) +#define RTL931X_MAC_PORT_CTRL (0x6004) + +/* DMA interrupt control and status registers */ +#define RTL838X_DMA_IF_CTRL (0x9f58) +#define RTL838X_DMA_IF_INTR_STS (0x9f54) +#define RTL838X_DMA_IF_INTR_MSK (0x9f50) + +#define RTL839X_DMA_IF_CTRL (0x786c) +#define RTL839X_DMA_IF_INTR_STS (0x7868) +#define RTL839X_DMA_IF_INTR_MSK (0x7864) + +#define RTL930X_DMA_IF_CTRL (0xe028) +#define RTL930X_DMA_IF_INTR_RX_RUNOUT_STS (0xe01C) +#define RTL930X_DMA_IF_INTR_RX_DONE_STS (0xe020) +#define RTL930X_DMA_IF_INTR_TX_DONE_STS (0xe024) +#define RTL930X_DMA_IF_INTR_RX_RUNOUT_MSK (0xe010) +#define RTL930X_DMA_IF_INTR_RX_DONE_MSK (0xe014) +#define RTL930X_DMA_IF_INTR_TX_DONE_MSK (0xe018) +#define RTL930X_L2_NTFY_IF_INTR_MSK (0xe04C) +#define RTL930X_L2_NTFY_IF_INTR_STS (0xe050) + +/* TODO: RTL931X_DMA_IF_CTRL has different bits meanings */ +#define RTL931X_DMA_IF_CTRL (0x0928) +#define RTL931X_DMA_IF_INTR_RX_RUNOUT_STS (0x091c) +#define RTL931X_DMA_IF_INTR_RX_DONE_STS (0x0920) +#define RTL931X_DMA_IF_INTR_TX_DONE_STS (0x0924) +#define RTL931X_DMA_IF_INTR_RX_RUNOUT_MSK (0x0910) +#define RTL931X_DMA_IF_INTR_RX_DONE_MSK (0x0914) +#define RTL931X_DMA_IF_INTR_TX_DONE_MSK (0x0918) +#define RTL931X_L2_NTFY_IF_INTR_MSK (0x09E4) +#define RTL931X_L2_NTFY_IF_INTR_STS (0x09E8) + +#define RTL838X_MAC_FORCE_MODE_CTRL (0xa104) +#define RTL839X_MAC_FORCE_MODE_CTRL (0x02bc) +#define RTL930X_MAC_FORCE_MODE_CTRL (0xCA1C) +#define RTL931X_MAC_FORCE_MODE_CTRL (0x0ddc) + +/* MAC address settings */ +#define RTL838X_MAC (0xa9ec) +#define RTL839X_MAC (0x02b4) +#define RTL838X_MAC_ALE (0x6b04) +#define RTL838X_MAC2 (0xa320) +#define RTL930X_MAC_L2_ADDR_CTRL (0xC714) +#define RTL931X_MAC_L2_ADDR_CTRL (0x135c) + +/* Ringbuffer setup */ +#define RTL838X_DMA_RX_BASE (0x9f00) +#define RTL839X_DMA_RX_BASE (0x780c) +#define RTL930X_DMA_RX_BASE (0xdf00) +#define RTL931X_DMA_RX_BASE (0x0800) + +#define RTL838X_DMA_TX_BASE (0x9f40) +#define RTL839X_DMA_TX_BASE (0x784c) +#define RTL930X_DMA_TX_BASE (0xe000) +#define RTL931X_DMA_TX_BASE (0x0900) + +#define RTL838X_DMA_IF_RX_RING_SIZE (0xB7E4) +#define RTL839X_DMA_IF_RX_RING_SIZE (0x6038) +#define RTL930X_DMA_IF_RX_RING_SIZE (0x7C60) +#define RTL931X_DMA_IF_RX_RING_SIZE (0x2080) + +#define RTL838X_DMA_IF_RX_RING_CNTR (0xB7E8) +#define RTL839X_DMA_IF_RX_RING_CNTR (0x603c) +#define RTL930X_DMA_IF_RX_RING_CNTR (0x7C8C) +#define RTL931X_DMA_IF_RX_RING_CNTR (0x20AC) + +#define RTL838X_DMA_IF_RX_CUR (0x9F20) +#define RTL839X_DMA_IF_RX_CUR (0x782c) +#define RTL930X_DMA_IF_RX_CUR (0xdf80) +#define RTL931X_DMA_IF_RX_CUR (0x0880) + +#define RTL838X_DMA_IF_TX_CUR_DESC_ADDR_CTRL (0x9F48) +#define RTL930X_DMA_IF_TX_CUR_DESC_ADDR_CTRL (0xE008) + +#define RTL838X_DMY_REG31 (0x3b28) +#define RTL838X_SDS_MODE_SEL (0x0028) +#define RTL838X_SDS_CFG_REG (0x0034) +#define RTL838X_INT_MODE_CTRL (0x005c) +#define RTL838X_CHIP_INFO (0x00d8) +#define RTL838X_SDS4_REG28 (0xef80) +#define RTL838X_SDS4_DUMMY0 (0xef8c) +#define RTL838X_SDS5_EXT_REG6 (0xf18c) + +/* L2 features */ +#define RTL839X_TBL_ACCESS_L2_CTRL (0x1180) +#define RTL839X_TBL_ACCESS_L2_DATA(idx) (0x1184 + ((idx) << 2)) +#define RTL838X_TBL_ACCESS_CTRL_0 (0x6914) +#define RTL838X_TBL_ACCESS_DATA_0(idx) (0x6918 + ((idx) << 2)) + +/* MAC-side link state handling */ +#define RTL838X_MAC_LINK_STS (0xa188) +#define RTL839X_MAC_LINK_STS (0x0390) +#define RTL930X_MAC_LINK_STS (0xCB10) +#define RTL931X_MAC_LINK_STS (0x0ec0) + +#define RTL838X_MAC_LINK_SPD_STS (0xa190) +#define RTL839X_MAC_LINK_SPD_STS (0x03a0) +#define RTL930X_MAC_LINK_SPD_STS (0xCB18) +#define RTL931X_MAC_LINK_SPD_STS (0x0ed0) + +#define RTL838X_MAC_LINK_DUP_STS (0xa19c) +#define RTL839X_MAC_LINK_DUP_STS (0x03b0) +#define RTL930X_MAC_LINK_DUP_STS (0xCB28) +#define RTL931X_MAC_LINK_DUP_STS (0x0ef0) + +// TODO: RTL8390_MAC_LINK_MEDIA_STS_ADDR ??? + +#define RTL838X_MAC_TX_PAUSE_STS (0xa1a0) +#define RTL839X_MAC_TX_PAUSE_STS (0x03b8) +#define RTL930X_MAC_TX_PAUSE_STS (0xCB2C) +#define RTL931X_MAC_TX_PAUSE_STS (0x0ef8) + +#define RTL838X_MAC_RX_PAUSE_STS (0xa1a4) +#define RTL839X_MAC_RX_PAUSE_STS (0xCB30) +#define RTL930X_MAC_RX_PAUSE_STS (0xC2F8) +#define RTL931X_MAC_RX_PAUSE_STS (0x0f00) + +#define RTL838X_EEE_TX_TIMER_GIGA_CTRL (0xaa04) +#define RTL838X_EEE_TX_TIMER_GELITE_CTRL (0xaa08) + +#define RTL930X_L2_UNKN_UC_FLD_PMSK (0x9064) + +#define RTL839X_MAC_GLB_CTRL (0x02a8) +#define RTL839X_SCHED_LB_TICK_TKN_CTRL (0x60f8) + +#define RTL838X_L2_TBL_FLUSH_CTRL (0x3370) +#define RTL839X_L2_TBL_FLUSH_CTRL (0x3ba0) +#define RTL930X_L2_TBL_FLUSH_CTRL (0x9404) +#define RTL931X_L2_TBL_FLUSH_CTRL (0xCD9C) + +#define RTL930X_L2_PORT_SABLK_CTRL (0x905c) +#define RTL930X_L2_PORT_DABLK_CTRL (0x9060) + +/* MAC link state bits */ +#define FORCE_EN (1 << 0) +#define FORCE_LINK_EN (1 << 1) +#define NWAY_EN (1 << 2) +#define DUPLX_MODE (1 << 3) +#define TX_PAUSE_EN (1 << 6) +#define RX_PAUSE_EN (1 << 7) + +/* L2 Notification DMA interface */ +#define RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL (0x785C) +#define RTL839X_L2_NOTIFICATION_CTRL (0x7808) +#define RTL931X_L2_NTFY_RING_BASE_ADDR (0x09DC) +#define RTL931X_L2_NTFY_RING_CUR_ADDR (0x09E0) +#define RTL839X_L2_NOTIFICATION_CTRL (0x7808) +#define RTL931X_L2_NTFY_CTRL (0xCDC8) +#define RTL838X_L2_CTRL_0 (0x3200) +#define RTL839X_L2_CTRL_0 (0x3800) +#define RTL930X_L2_CTRL (0x8FD8) +#define RTL931X_L2_CTRL (0xC800) + +/* TRAPPING to CPU-PORT */ +#define RTL838X_SPCL_TRAP_IGMP_CTRL (0x6984) +#define RTL838X_RMA_CTRL_0 (0x4300) +#define RTL838X_RMA_CTRL_1 (0x4304) +#define RTL839X_RMA_CTRL_0 (0x1200) + +#define RTL839X_SPCL_TRAP_IGMP_CTRL (0x1058) +#define RTL839X_RMA_CTRL_1 (0x1204) +#define RTL839X_RMA_CTRL_2 (0x1208) +#define RTL839X_RMA_CTRL_3 (0x120C) + +#define RTL930X_VLAN_APP_PKT_CTRL (0xA23C) +#define RTL930X_RMA_CTRL_0 (0x9E60) +#define RTL930X_RMA_CTRL_1 (0x9E64) +#define RTL930X_RMA_CTRL_2 (0x9E68) + +#define RTL931X_RMA_CTRL_0 (0x8800) +#define RTL931X_RMA_CTRL_1 (0x8804) +#define RTL931X_RMA_CTRL_2 (0x8808) + +/* Advanced SMI control for clause 45 PHYs */ +#define RTL930X_SMI_MAC_TYPE_CTRL (0xCA04) +#define RTL930X_SMI_PORT24_27_ADDR_CTRL (0xCB90) +#define RTL930X_SMI_PORT0_15_POLLING_SEL (0xCA08) +#define RTL930X_SMI_PORT16_27_POLLING_SEL (0xCA0C) + +/* Registers of the internal Serdes of the 8390 */ +#define RTL839X_SDS12_13_XSG0 (0xB800) + +/* Registers of the internal Serdes of the 8380 */ +#define RTL838X_SDS4_FIB_REG0 (0xF800) + +inline int rtl838x_mac_port_ctrl(int p) +{ + return RTL838X_MAC_PORT_CTRL + (p << 7); +} + +inline int rtl839x_mac_port_ctrl(int p) +{ + return RTL839X_MAC_PORT_CTRL + (p << 7); +} + +/* On the RTL931XX, the functionality of the MAC port control register is split up + * into RTL931X_MAC_L2_PORT_CTRL and RTL931X_MAC_PORT_CTRL the functionality used + * by the Ethernet driver is in the same bits now in RTL931X_MAC_L2_PORT_CTRL + */ + +inline int rtl930x_mac_port_ctrl(int p) +{ + return RTL930X_MAC_L2_PORT_CTRL + (p << 6); +} + +inline int rtl931x_mac_port_ctrl(int p) +{ + return RTL931X_MAC_L2_PORT_CTRL + (p << 7); +} + +inline int rtl838x_dma_if_rx_ring_size(int i) +{ + return RTL838X_DMA_IF_RX_RING_SIZE + ((i >> 3) << 2); +} + +inline int rtl839x_dma_if_rx_ring_size(int i) +{ + return RTL839X_DMA_IF_RX_RING_SIZE + ((i >> 3) << 2); +} + +inline int rtl930x_dma_if_rx_ring_size(int i) +{ + return RTL930X_DMA_IF_RX_RING_SIZE + ((i / 3) << 2); +} + +inline int rtl931x_dma_if_rx_ring_size(int i) +{ + return RTL931X_DMA_IF_RX_RING_SIZE + ((i / 3) << 2); +} + +inline int rtl838x_dma_if_rx_ring_cntr(int i) +{ + return RTL838X_DMA_IF_RX_RING_CNTR + ((i >> 3) << 2); +} + +inline int rtl839x_dma_if_rx_ring_cntr(int i) +{ + return RTL839X_DMA_IF_RX_RING_CNTR + ((i >> 3) << 2); +} + +inline int rtl930x_dma_if_rx_ring_cntr(int i) +{ + return RTL930X_DMA_IF_RX_RING_CNTR + ((i / 3) << 2); +} + +inline int rtl931x_dma_if_rx_ring_cntr(int i) +{ + return RTL931X_DMA_IF_RX_RING_CNTR + ((i / 3) << 2); +} + +inline u32 rtl838x_get_mac_link_sts(int port) +{ + return (sw_r32(RTL838X_MAC_LINK_STS) & BIT(port)); +} + +inline u32 rtl839x_get_mac_link_sts(int p) +{ + return (sw_r32(RTL839X_MAC_LINK_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl930x_get_mac_link_sts(int port) +{ + return (sw_r32(RTL930X_MAC_LINK_STS) & BIT(port)); +} + +inline u32 rtl931x_get_mac_link_sts(int p) +{ + return (sw_r32(RTL931X_MAC_LINK_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl838x_get_mac_link_dup_sts(int port) +{ + return (sw_r32(RTL838X_MAC_LINK_DUP_STS) & BIT(port)); +} + +inline u32 rtl839x_get_mac_link_dup_sts(int p) +{ + return (sw_r32(RTL839X_MAC_LINK_DUP_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl930x_get_mac_link_dup_sts(int port) +{ + return (sw_r32(RTL930X_MAC_LINK_DUP_STS) & BIT(port)); +} + +inline u32 rtl931x_get_mac_link_dup_sts(int p) +{ + return (sw_r32(RTL931X_MAC_LINK_DUP_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl838x_get_mac_link_spd_sts(int port) +{ + int r = RTL838X_MAC_LINK_SPD_STS + ((port >> 4) << 2); + u32 speed = sw_r32(r); + + speed >>= (port % 16) << 1; + return (speed & 0x3); +} + +inline u32 rtl839x_get_mac_link_spd_sts(int port) +{ + int r = RTL839X_MAC_LINK_SPD_STS + ((port >> 4) << 2); + u32 speed = sw_r32(r); + + speed >>= (port % 16) << 1; + return (speed & 0x3); +} + + +inline u32 rtl930x_get_mac_link_spd_sts(int port) +{ + int r = RTL930X_MAC_LINK_SPD_STS + ((port / 10) << 2); + u32 speed = sw_r32(r); + + speed >>= (port % 10) * 3; + return (speed & 0x7); +} + +inline u32 rtl931x_get_mac_link_spd_sts(int port) +{ + int r = RTL931X_MAC_LINK_SPD_STS + ((port >> 3) << 2); + u32 speed = sw_r32(r); + + speed >>= (port % 8) << 2; + return (speed & 0xf); +} + +inline u32 rtl838x_get_mac_rx_pause_sts(int port) +{ + return (sw_r32(RTL838X_MAC_RX_PAUSE_STS) & (1 << port)); +} + +inline u32 rtl839x_get_mac_rx_pause_sts(int p) +{ + return (sw_r32(RTL839X_MAC_RX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl930x_get_mac_rx_pause_sts(int port) +{ + return (sw_r32(RTL930X_MAC_RX_PAUSE_STS) & (1 << port)); +} + +inline u32 rtl931x_get_mac_rx_pause_sts(int p) +{ + return (sw_r32(RTL931X_MAC_RX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl838x_get_mac_tx_pause_sts(int port) +{ + return (sw_r32(RTL838X_MAC_TX_PAUSE_STS) & (1 << port)); +} + +inline u32 rtl839x_get_mac_tx_pause_sts(int p) +{ + return (sw_r32(RTL839X_MAC_TX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +inline u32 rtl930x_get_mac_tx_pause_sts(int port) +{ + return (sw_r32(RTL930X_MAC_TX_PAUSE_STS) & (1 << port)); +} + +inline u32 rtl931x_get_mac_tx_pause_sts(int p) +{ + return (sw_r32(RTL931X_MAC_TX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32)); +} + +struct p_hdr; +struct dsa_tag; + +struct rtl838x_reg { + irqreturn_t (*net_irq)(int irq, void *dev_id); + int (*mac_port_ctrl)(int port); + int dma_if_intr_sts; + int dma_if_intr_msk; + int dma_if_intr_rx_runout_sts; + int dma_if_intr_rx_done_sts; + int dma_if_intr_tx_done_sts; + int dma_if_intr_rx_runout_msk; + int dma_if_intr_rx_done_msk; + int dma_if_intr_tx_done_msk; + int l2_ntfy_if_intr_sts; + int l2_ntfy_if_intr_msk; + int dma_if_ctrl; + int mac_force_mode_ctrl; + int dma_rx_base; + int dma_tx_base; + int (*dma_if_rx_ring_size)(int ring); + int (*dma_if_rx_ring_cntr)(int ring); + int dma_if_rx_cur; + int rst_glb_ctrl; + u32 (*get_mac_link_sts)(int port); + u32 (*get_mac_link_dup_sts)(int port); + u32 (*get_mac_link_spd_sts)(int port); + u32 (*get_mac_rx_pause_sts)(int port); + u32 (*get_mac_tx_pause_sts)(int port); + int mac; + int l2_tbl_flush_ctrl; + void (*update_cntr)(int r, int work_done); + void (*create_tx_header)(struct p_hdr *h, int dest_port, int prio); + bool (*decode_tag)(struct p_hdr *h, struct dsa_tag *tag); +}; + +int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val); +int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +void rtl9300_sds_power(int sds_num, int val); + +#endif /* _RTL838X_ETH_H */ diff --git a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c new file mode 100644 index 0000000000..3e187228a9 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c @@ -0,0 +1,1983 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Realtek RTL838X Ethernet MDIO interface driver + * + * Copyright (C) 2020 B. Koblitz + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "rtl83xx-phy.h" + + +extern struct rtl83xx_soc_info soc_info; +extern struct mutex smi_lock; + +/* + * This lock protects the state of the SoC automatically polling the PHYs over the SMI + * bus to detect e.g. link and media changes. For operations on the PHYs such as + * patching or other configuration changes such as EEE, polling needs to be disabled + * since otherwise these operations may fails or lead to unpredictable results. + */ +DEFINE_MUTEX(poll_lock); + +static const struct firmware rtl838x_8380_fw; +static const struct firmware rtl838x_8214fc_fw; +static const struct firmware rtl838x_8218b_fw; + +int rtl838x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); +int rtl838x_write_mmd_phy(u32 port, u32 devnum, u32 reg, u32 val); +int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); +int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 reg, u32 val); +int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); +int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 reg, u32 val); +int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); +int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 reg, u32 val); + +static int read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ switch (soc_info.family) { + case RTL8380_FAMILY_ID: + return rtl838x_read_phy(port, page, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_read_phy(port, page, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_read_phy(port, page, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_read_phy(port, page, reg, val); + } + return -1; +} + +static int write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + return rtl838x_write_phy(port, page, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_write_phy(port, page, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_write_phy(port, page, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_write_phy(port, page, reg, val); + } + return -1; +} + +static int read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val) +{ + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + return rtl838x_read_mmd_phy(port, devnum, regnum, val); + case RTL8390_FAMILY_ID: + return rtl839x_read_mmd_phy(port, devnum, regnum, val); + case RTL9300_FAMILY_ID: + return rtl930x_read_mmd_phy(port, devnum, regnum, val); + case RTL9310_FAMILY_ID: + return rtl931x_read_mmd_phy(port, devnum, regnum, val); + } + return -1; +} + +int write_mmd_phy(u32 port, u32 devnum, u32 reg, u32 val) +{ + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + return rtl838x_write_mmd_phy(port, devnum, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_write_mmd_phy(port, devnum, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_write_mmd_phy(port, devnum, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_write_mmd_phy(port, devnum, reg, val); + } + return -1; +} + +static u64 disable_polling(int port) +{ + u64 saved_state; + + mutex_lock(&poll_lock); + + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + saved_state = sw_r32(RTL838X_SMI_POLL_CTRL); + sw_w32_mask(BIT(port), 0, RTL838X_SMI_POLL_CTRL); + break; + case RTL8390_FAMILY_ID: + saved_state = sw_r32(RTL839X_SMI_PORT_POLLING_CTRL + 4); + saved_state <<= 32; + saved_state |= sw_r32(RTL839X_SMI_PORT_POLLING_CTRL); + sw_w32_mask(BIT(port % 32), 0, + RTL839X_SMI_PORT_POLLING_CTRL + ((port >> 5) << 2)); + break; + case RTL9300_FAMILY_ID: + saved_state = sw_r32(RTL930X_SMI_POLL_CTRL); + sw_w32_mask(BIT(port), 0, RTL930X_SMI_POLL_CTRL); + break; + case RTL9310_FAMILY_ID: + pr_warn("%s not implemented for RTL931X\n", __func__); + break; + } + + mutex_unlock(&poll_lock); + + return saved_state; +} + +static int resume_polling(u64 saved_state) +{ + mutex_lock(&poll_lock); + + switch (soc_info.family) { + case RTL8380_FAMILY_ID: + sw_w32(saved_state, RTL838X_SMI_POLL_CTRL); + break; + case RTL8390_FAMILY_ID: + sw_w32(saved_state >> 32, RTL839X_SMI_PORT_POLLING_CTRL + 4); + sw_w32(saved_state, RTL839X_SMI_PORT_POLLING_CTRL); + break; + case RTL9300_FAMILY_ID: + sw_w32(saved_state, RTL930X_SMI_POLL_CTRL); + break; + case RTL9310_FAMILY_ID: + pr_warn("%s not implemented for RTL931X\n", __func__); + break; + } + + mutex_unlock(&poll_lock); + + return 0; +} + +static void rtl8380_int_phy_on_off(int mac, bool on) +{ + u32 val; + + read_phy(mac, 0, 0, &val); + if (on) + write_phy(mac, 0, 0, val & ~BIT(11)); + else + write_phy(mac, 0, 0, val | BIT(11)); +} + +static void rtl8380_rtl8214fc_on_off(int mac, bool on) +{ + u32 val; + + /* fiber ports */ + write_phy(mac, 4095, 30, 3); + read_phy(mac, 0, 16, &val); + if (on) + write_phy(mac, 0, 16, val & ~BIT(11)); + else + write_phy(mac, 0, 16, val | BIT(11)); + + /* copper ports */ + write_phy(mac, 4095, 30, 1); + read_phy(mac, 0, 16, &val); + if (on) + write_phy(mac, 0xa40, 16, val & ~BIT(11)); + else + write_phy(mac, 0xa40, 16, val | BIT(11)); +} + +static void rtl8380_phy_reset(int mac) +{ + u32 val; + + read_phy(mac, 0, 0, &val); + write_phy(mac, 0, 0, val | BIT(15)); +} + +/* + * Reset the SerDes by powering it off and set a new operations mode + * of the SerDes. 0x1f is off. Other modes are + * 0x01: QSGMII 0x04: 1000BX_FIBER 0x05: FIBER100 + * 0x06: QSGMII 0x09: RSGMII 0x0d: USXGMII + * 0x10: XSGMII 0x12: HISGMII 0x16: 2500Base_X + * 0x17: RXAUI_LITE 0x19: RXAUI_PLUS 0x1a: 10G Base-R + * 0x1b: 10GR1000BX_AUTO 0x1f: OFF + */ +void rtl9300_sds_rst(int sds_num, u32 mode) +{ + // The access registers for SDS_MODE_SEL and the LSB for each SDS within + u16 regs[] = { 0x0194, 0x0194, 0x0194, 0x0194, 0x02a0, 0x02a0, 0x02a0, 0x02a0, + 0x02A4, 0x02A4, 0x0198, 0x0198 }; + u8 lsb[] = { 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 0, 6}; + + pr_info("SerDes: %s %d\n", __func__, mode); + if (sds_num < 0 || sds_num > 11) { + pr_err("Wrong SerDes number: %d\n", sds_num); + return; + } + + sw_w32_mask(0x1f << lsb[sds_num], 0x1f << lsb[sds_num], regs[sds_num]); + mdelay(10); + + sw_w32_mask(0x1f << lsb[sds_num], mode << lsb[sds_num], regs[sds_num]); + mdelay(10); + + pr_info("SDS: 194:%08x 198:%08x 2a0:%08x 2a4:%08x\n", + sw_r32(0x194), sw_r32(0x198), sw_r32(0x2a0), sw_r32(0x2a4)); +} + +/* + * On the RTL839x family of SoCs with inbuilt SerDes, these SerDes are accessed through + * a 2048 bit register that holds the contents of the PHY being simulated by the SoC. + */ +int rtl839x_read_sds_phy(int phy_addr, int phy_reg) +{ + int offset = 0; + int reg; + u32 val; + + if (phy_addr == 49) + offset = 0x100; + + /* + * For the RTL8393 internal SerDes, we simulate a PHY ID in registers 2/3 + * which would otherwise read as 0. + */ + if (soc_info.id == 0x8393) { + if (phy_reg == 2) + return 0x1c; + if (phy_reg == 3) + return 0x8393; + } + + /* + * Register RTL839X_SDS12_13_XSG0 is 2048 bit broad, the MSB (bit 15) of the + * 0th PHY register is bit 1023 (in byte 0x80). Because PHY-registers are 16 + * bit broad, we offset by reg << 1. In the SoC 2 registers are stored in + * one 32 bit register. + */ + reg = (phy_reg << 1) & 0xfc; + val = sw_r32(RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg); + + if (phy_reg & 1) + val = (val >> 16) & 0xffff; + else + val &= 0xffff; + return val; +} + +/* + * On the RTL930x family of SoCs, the internal SerDes are accessed through an IO + * register which simulates commands to an internal MDIO bus. + */ +int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg) +{ + int i; + u32 cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 1; + + pr_info("%s: phy_addr %d, phy_reg: %d\n", __func__, phy_addr, phy_reg); + sw_w32(cmd, RTL930X_SDS_INDACS_CMD); + + for (i = 0; i < 100; i++) { + if (!(sw_r32(RTL930X_SDS_INDACS_CMD) & 0x1)) + break; + mdelay(1); + } + + if (i >= 100) + return -EIO; + + pr_info("%s: returning %04x\n", __func__, sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff); + return sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff; +} + +int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v) +{ + int i; + u32 cmd; + + sw_w32(v, RTL930X_SDS_INDACS_DATA); + cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 0x3; + + for (i = 0; i < 100; i++) { + if (!(sw_r32(RTL930X_SDS_INDACS_CMD) & 0x1)) + break; + mdelay(1); + } + + if (i >= 100) + return -EIO; + + return 0; +} + +/* + * On the RTL838x SoCs, the internal SerDes is accessed through direct access to + * standard PHY registers, where a 32 bit register holds a 16 bit word as found + * in a standard page 0 of a PHY + */ +int rtl838x_read_sds_phy(int phy_addr, int phy_reg) +{ + int offset = 0; + u32 val; + + if (phy_addr == 26) + offset = 0x100; + val = sw_r32(RTL838X_SDS4_FIB_REG0 + offset + (phy_reg << 2)) & 0xffff; + + return val; +} + +int rtl839x_write_sds_phy(int phy_addr, int phy_reg, u16 v) +{ + int offset = 0; + int reg; + u32 val; + + if (phy_addr == 49) + offset = 0x100; + + reg = (phy_reg << 1) & 0xfc; + val = v; + if (phy_reg & 1) { + val = val << 16; + sw_w32_mask(0xffff0000, val, + RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg); + } else { + sw_w32_mask(0xffff, val, + RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg); + } + + return 0; +} + +/* Read the link and speed status of the 2 internal SGMII/1000Base-X + * ports of the RTL838x SoCs + */ +static int rtl8380_read_status(struct phy_device *phydev) +{ + int err; + + err = genphy_read_status(phydev); + + if (phydev->link) { + phydev->speed = SPEED_1000; + phydev->duplex = DUPLEX_FULL; + } + + return err; +} + +/* Read the link and speed status of the 2 internal SGMII/1000Base-X + * ports of the RTL8393 SoC + */ +static int rtl8393_read_status(struct phy_device *phydev) +{ + int offset = 0; + int err; + int phy_addr = phydev->mdio.addr; + u32 v; + + err = genphy_read_status(phydev); + if (phy_addr == 49) + offset = 0x100; + + if (phydev->link) { + phydev->speed = SPEED_100; + /* Read SPD_RD_00 (bit 13) and SPD_RD_01 (bit 6) out of the internal + * PHY registers + */ + v = sw_r32(RTL839X_SDS12_13_XSG0 + offset + 0x80); + if (!(v & (1 << 13)) && (v & (1 << 6))) + phydev->speed = SPEED_1000; + phydev->duplex = DUPLEX_FULL; + } + + return err; +} + +static int rtl8226_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, 0x1f); +} + +static int rtl8226_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, 0x1f, page); +} + +static int rtl8226_read_status(struct phy_device *phydev) +{ + int ret = 0, i; + u32 val; + int port = phydev->mdio.addr; + +// TODO: ret = genphy_read_status(phydev); +// if (ret < 0) { +// pr_info("%s: genphy_read_status failed\n", __func__); +// return ret; +// } + + // Link status must be read twice + for (i = 0; i < 2; i++) { + read_mmd_phy(port, MMD_VEND2, 0xA402, &val); + } + phydev->link = val & BIT(2) ? 1 : 0; + if (!phydev->link) + goto out; + + // Read duplex status + ret = read_mmd_phy(port, MMD_VEND2, 0xA434, &val); + if (ret) + goto out; + phydev->duplex = !!(val & BIT(3)); + + // Read speed + ret = read_mmd_phy(port, MMD_VEND2, 0xA434, &val); + switch (val & 0x0630) { + case 0x0000: + phydev->speed = SPEED_10; + break; + case 0x0010: + phydev->speed = SPEED_100; + break; + case 0x0020: + phydev->speed = SPEED_1000; + break; + case 0x0200: + phydev->speed = SPEED_10000; + break; + case 0x0210: + phydev->speed = SPEED_2500; + break; + case 0x0220: + phydev->speed = SPEED_5000; + break; + default: + break; + } +out: + return ret; +} + +static int rtl8226_advertise_aneg(struct phy_device *phydev) +{ + int ret = 0; + u32 v; + int port = phydev->mdio.addr; + + pr_info("In %s\n", __func__); + + ret = read_mmd_phy(port, MMD_AN, 16, &v); + if (ret) + goto out; + + v |= BIT(5); // HD 10M + v |= BIT(6); // FD 10M + v |= BIT(7); // HD 100M + v |= BIT(8); // FD 100M + + ret = write_mmd_phy(port, MMD_AN, 16, v); + + // Allow 1GBit + ret = read_mmd_phy(port, MMD_VEND2, 0xA412, &v); + if (ret) + goto out; + v |= BIT(9); // FD 1000M + + ret = write_mmd_phy(port, MMD_VEND2, 0xA412, v); + if (ret) + goto out; + + // Allow 2.5G + ret = read_mmd_phy(port, MMD_AN, 32, &v); + if (ret) + goto out; + + v |= BIT(7); + ret = write_mmd_phy(port, MMD_AN, 32, v); + +out: + return ret; +} + +static int rtl8226_config_aneg(struct phy_device *phydev) +{ + int ret = 0; + u32 v; + int port = phydev->mdio.addr; + + pr_info("In %s\n", __func__); + if (phydev->autoneg == AUTONEG_ENABLE) { + ret = rtl8226_advertise_aneg(phydev); + if (ret) + goto out; + // AutoNegotiationEnable + ret = read_mmd_phy(port, MMD_AN, 0, &v); + if (ret) + goto out; + + v |= BIT(12); // Enable AN + ret = write_mmd_phy(port, MMD_AN, 0, v); + if (ret) + goto out; + + // RestartAutoNegotiation + ret = read_mmd_phy(port, MMD_VEND2, 0xA400, &v); + if (ret) + goto out; + v |= BIT(9); + + ret = write_mmd_phy(port, MMD_VEND2, 0xA400, v); + } + + pr_info("%s: Ret is already: %d\n", __func__, ret); +// TODO: ret = __genphy_config_aneg(phydev, ret); + +out: + pr_info("%s: And ret is now: %d\n", __func__, ret); + return ret; +} + +static int rtl8226_get_eee(struct phy_device *phydev, + struct ethtool_eee *e) +{ + u32 val; + int addr = phydev->mdio.addr; + + pr_debug("In %s, port %d, was enabled: %d\n", __func__, addr, e->eee_enabled); + + read_mmd_phy(addr, MMD_AN, 60, &val); + if (e->eee_enabled) { + e->eee_enabled = !!(val & BIT(1)); + if (!e->eee_enabled) { + read_mmd_phy(addr, MMD_AN, 62, &val); + e->eee_enabled = !!(val & BIT(0)); + } + } + pr_debug("%s: enabled: %d\n", __func__, e->eee_enabled); + + return 0; +} + +static int rtl8226_set_eee(struct phy_device *phydev, struct ethtool_eee *e) +{ + int port = phydev->mdio.addr; + u64 poll_state; + bool an_enabled; + u32 val; + + pr_info("In %s, port %d, enabled %d\n", __func__, port, e->eee_enabled); + + poll_state = disable_polling(port); + + // Remember aneg state + read_mmd_phy(port, MMD_AN, 0, &val); + an_enabled = !!(val & BIT(12)); + + // Setup 100/1000MBit + read_mmd_phy(port, MMD_AN, 60, &val); + if (e->eee_enabled) + val |= 0x6; + else + val &= 0x6; + write_mmd_phy(port, MMD_AN, 60, val); + + // Setup 2.5GBit + read_mmd_phy(port, MMD_AN, 62, &val); + if (e->eee_enabled) + val |= 0x1; + else + val &= 0x1; + write_mmd_phy(port, MMD_AN, 62, val); + + // RestartAutoNegotiation + read_mmd_phy(port, MMD_VEND2, 0xA400, &val); + val |= BIT(9); + write_mmd_phy(port, MMD_VEND2, 0xA400, val); + + resume_polling(poll_state); + + return 0; +} + +static struct fw_header *rtl838x_request_fw(struct phy_device *phydev, + const struct firmware *fw, + const char *name) +{ + struct device *dev = &phydev->mdio.dev; + int err; + struct fw_header *h; + uint32_t checksum, my_checksum; + + err = request_firmware(&fw, name, dev); + if (err < 0) + goto out; + + if (fw->size < sizeof(struct fw_header)) { + pr_err("Firmware size too small.\n"); + err = -EINVAL; + goto out; + } + + h = (struct fw_header *) fw->data; + pr_info("Firmware loaded. Size %d, magic: %08x\n", fw->size, h->magic); + + if (h->magic != 0x83808380) { + pr_err("Wrong firmware file: MAGIC mismatch.\n"); + goto out; + } + + checksum = h->checksum; + h->checksum = 0; + my_checksum = ~crc32(0xFFFFFFFFU, fw->data, fw->size); + if (checksum != my_checksum) { + pr_err("Firmware checksum mismatch.\n"); + err = -EINVAL; + goto out; + } + h->checksum = checksum; + + return h; +out: + dev_err(dev, "Unable to load firmware %s (%d)\n", name, err); + return NULL; +} + +static int rtl8390_configure_generic(struct phy_device *phydev) +{ + u32 val, phy_id; + int mac = phydev->mdio.addr; + + read_phy(mac, 0, 2, &val); + phy_id = val << 16; + read_phy(mac, 0, 3, &val); + phy_id |= val; + pr_debug("Phy on MAC %d: %x\n", mac, phy_id); + + /* Read internal PHY ID */ + write_phy(mac, 31, 27, 0x0002); + read_phy(mac, 31, 28, &val); + + /* Internal RTL8218B, version 2 */ + phydev_info(phydev, "Detected unknown %x\n", val); + return 0; +} + +static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev) +{ + u32 val, phy_id; + int i, p, ipd_flag; + int mac = phydev->mdio.addr; + struct fw_header *h; + u32 *rtl838x_6275B_intPhy_perport; + u32 *rtl8218b_6276B_hwEsd_perport; + + + read_phy(mac, 0, 2, &val); + phy_id = val << 16; + read_phy(mac, 0, 3, &val); + phy_id |= val; + pr_debug("Phy on MAC %d: %x\n", mac, phy_id); + + /* Read internal PHY ID */ + write_phy(mac, 31, 27, 0x0002); + read_phy(mac, 31, 28, &val); + if (val != 0x6275) { + phydev_err(phydev, "Expected internal RTL8218B, found PHY-ID %x\n", val); + return -1; + } + + /* Internal RTL8218B, version 2 */ + phydev_info(phydev, "Detected internal RTL8218B\n"); + + h = rtl838x_request_fw(phydev, &rtl838x_8380_fw, FIRMWARE_838X_8380_1); + if (!h) + return -1; + + if (h->phy != 0x83800000) { + phydev_err(phydev, "Wrong firmware file: PHY mismatch.\n"); + return -1; + } + + rtl838x_6275B_intPhy_perport = (void *)h + sizeof(struct fw_header) + + h->parts[8].start; + + rtl8218b_6276B_hwEsd_perport = (void *)h + sizeof(struct fw_header) + + h->parts[9].start; + + if (sw_r32(RTL838X_DMY_REG31) == 0x1) + ipd_flag = 1; + + read_phy(mac, 0, 0, &val); + if (val & (1 << 11)) + rtl8380_int_phy_on_off(mac, true); + else + rtl8380_phy_reset(mac); + msleep(100); + + /* Ready PHY for patch */ + for (p = 0; p < 8; p++) { + write_phy(mac + p, 0xfff, 0x1f, 0x0b82); + write_phy(mac + p, 0xfff, 0x10, 0x0010); + } + msleep(500); + for (p = 0; p < 8; p++) { + for (i = 0; i < 100 ; i++) { + read_phy(mac + p, 0x0b80, 0x10, &val); + if (val & 0x40) + break; + } + if (i >= 100) { + phydev_err(phydev, + "ERROR: Port %d not ready for patch.\n", + mac + p); + return -1; + } + } + for (p = 0; p < 8; p++) { + i = 0; + while (rtl838x_6275B_intPhy_perport[i * 2]) { + write_phy(mac + p, 0xfff, + rtl838x_6275B_intPhy_perport[i * 2], + rtl838x_6275B_intPhy_perport[i * 2 + 1]); + i++; + } + i = 0; + while (rtl8218b_6276B_hwEsd_perport[i * 2]) { + write_phy(mac + p, 0xfff, + rtl8218b_6276B_hwEsd_perport[i * 2], + rtl8218b_6276B_hwEsd_perport[i * 2 + 1]); + i++; + } + } + return 0; +} + +static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev) +{ + u32 val, ipd, phy_id; + int i, l; + int mac = phydev->mdio.addr; + struct fw_header *h; + u32 *rtl8380_rtl8218b_perchip; + u32 *rtl8218B_6276B_rtl8380_perport; + u32 *rtl8380_rtl8218b_perport; + + if (soc_info.family == RTL8380_FAMILY_ID && mac != 0 && mac != 16) { + phydev_err(phydev, "External RTL8218B must have PHY-IDs 0 or 16!\n"); + return -1; + } + read_phy(mac, 0, 2, &val); + phy_id = val << 16; + read_phy(mac, 0, 3, &val); + phy_id |= val; + pr_info("Phy on MAC %d: %x\n", mac, phy_id); + + /* Read internal PHY ID */ + write_phy(mac, 31, 27, 0x0002); + read_phy(mac, 31, 28, &val); + if (val != 0x6276) { + phydev_err(phydev, "Expected external RTL8218B, found PHY-ID %x\n", val); + return -1; + } + phydev_info(phydev, "Detected external RTL8218B\n"); + + h = rtl838x_request_fw(phydev, &rtl838x_8218b_fw, FIRMWARE_838X_8218b_1); + if (!h) + return -1; + + if (h->phy != 0x8218b000) { + phydev_err(phydev, "Wrong firmware file: PHY mismatch.\n"); + return -1; + } + + rtl8380_rtl8218b_perchip = (void *)h + sizeof(struct fw_header) + + h->parts[0].start; + + rtl8218B_6276B_rtl8380_perport = (void *)h + sizeof(struct fw_header) + + h->parts[1].start; + + rtl8380_rtl8218b_perport = (void *)h + sizeof(struct fw_header) + + h->parts[2].start; + + read_phy(mac, 0, 0, &val); + if (val & (1 << 11)) + rtl8380_int_phy_on_off(mac, true); + else + rtl8380_phy_reset(mac); + msleep(100); + + /* Get Chip revision */ + write_phy(mac, 0xfff, 0x1f, 0x0); + write_phy(mac, 0xfff, 0x1b, 0x4); + read_phy(mac, 0xfff, 0x1c, &val); + + i = 0; + while (rtl8380_rtl8218b_perchip[i * 3] + && rtl8380_rtl8218b_perchip[i * 3 + 1]) { + write_phy(mac + rtl8380_rtl8218b_perchip[i * 3], + 0xfff, rtl8380_rtl8218b_perchip[i * 3 + 1], + rtl8380_rtl8218b_perchip[i * 3 + 2]); + i++; + } + + /* Enable PHY */ + for (i = 0; i < 8; i++) { + write_phy(mac + i, 0xfff, 0x1f, 0x0000); + write_phy(mac + i, 0xfff, 0x00, 0x1140); + } + mdelay(100); + + /* Request patch */ + for (i = 0; i < 8; i++) { + write_phy(mac + i, 0xfff, 0x1f, 0x0b82); + write_phy(mac + i, 0xfff, 0x10, 0x0010); + } + mdelay(300); + + /* Verify patch readiness */ + for (i = 0; i < 8; i++) { + for (l = 0; l < 100; l++) { + read_phy(mac + i, 0xb80, 0x10, &val); + if (val & 0x40) + break; + } + if (l >= 100) { + phydev_err(phydev, "Could not patch PHY\n"); + return -1; + } + } + + /* Use Broadcast ID method for patching */ + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0008); + write_phy(mac, 0xfff, 0x1f, 0x0266); + write_phy(mac, 0xfff, 0x16, 0xff00 + mac); + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0000); + mdelay(1); + + write_phy(mac, 0xfff, 30, 8); + write_phy(mac, 0x26e, 17, 0xb); + write_phy(mac, 0x26e, 16, 0x2); + mdelay(1); + read_phy(mac, 0x26e, 19, &ipd); + write_phy(mac, 0, 30, 0); + ipd = (ipd >> 4) & 0xf; + + i = 0; + while (rtl8218B_6276B_rtl8380_perport[i * 2]) { + write_phy(mac, 0xfff, rtl8218B_6276B_rtl8380_perport[i * 2], + rtl8218B_6276B_rtl8380_perport[i * 2 + 1]); + i++; + } + + /*Disable broadcast ID*/ + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0008); + write_phy(mac, 0xfff, 0x1f, 0x0266); + write_phy(mac, 0xfff, 0x16, 0x00 + mac); + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0000); + mdelay(1); + + return 0; +} + +static int rtl8218b_ext_match_phy_device(struct phy_device *phydev) +{ + int addr = phydev->mdio.addr; + + /* Both the RTL8214FC and the external RTL8218B have the same + * PHY ID. On the RTL838x, the RTL8218B can only be attached_dev + * at PHY IDs 0-7, while the RTL8214FC must be attached via + * the pair of SGMII/1000Base-X with higher PHY-IDs + */ + if (soc_info.family == RTL8380_FAMILY_ID) + return phydev->phy_id == PHY_ID_RTL8218B_E && addr < 8; + else + return phydev->phy_id == PHY_ID_RTL8218B_E; +} + +static int rtl8218b_read_mmd(struct phy_device *phydev, + int devnum, u16 regnum) +{ + int ret; + u32 val; + int addr = phydev->mdio.addr; + + ret = read_mmd_phy(addr, devnum, regnum, &val); + if (ret) + return ret; + return val; +} + +static int rtl8218b_write_mmd(struct phy_device *phydev, + int devnum, u16 regnum, u16 val) +{ + int addr = phydev->mdio.addr; + + return rtl838x_write_mmd_phy(addr, devnum, regnum, val); +} + +static int rtl8226_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) +{ + int port = phydev->mdio.addr; // the SoC translates port addresses to PHY addr + int err; + u32 val; + + err = read_mmd_phy(port, devnum, regnum, &val); + if (err) + return err; + return val; +} + +static int rtl8226_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, u16 val) +{ + int port = phydev->mdio.addr; // the SoC translates port addresses to PHY addr + + return write_mmd_phy(port, devnum, regnum, val); +} + +static void rtl8380_rtl8214fc_media_set(int mac, bool set_fibre) +{ + int base = mac - (mac % 4); + static int reg[] = {16, 19, 20, 21}; + int val, media, power; + + pr_info("%s: port %d, set_fibre: %d\n", __func__, mac, set_fibre); + write_phy(base, 0xfff, 29, 8); + read_phy(base, 0x266, reg[mac % 4], &val); + + media = (val >> 10) & 0x3; + pr_info("Current media %x\n", media); + if (media & 0x2) { + pr_info("Powering off COPPER\n"); + write_phy(base, 0xfff, 29, 1); + /* Ensure power is off */ + read_phy(base, 0xa40, 16, &power); + if (!(power & (1 << 11))) + write_phy(base, 0xa40, 16, power | (1 << 11)); + } else { + pr_info("Powering off FIBRE"); + write_phy(base, 0xfff, 29, 3); + /* Ensure power is off */ + read_phy(base, 0xa40, 16, &power); + if (!(power & (1 << 11))) + write_phy(base, 0xa40, 16, power | (1 << 11)); + } + + if (set_fibre) { + val |= 1 << 10; + val &= ~(1 << 11); + } else { + val |= 1 << 10; + val |= 1 << 11; + } + write_phy(base, 0xfff, 29, 8); + write_phy(base, 0x266, reg[mac % 4], val); + write_phy(base, 0xfff, 29, 0); + + if (set_fibre) { + pr_info("Powering on FIBRE"); + write_phy(base, 0xfff, 29, 3); + /* Ensure power is off */ + read_phy(base, 0xa40, 16, &power); + if (power & (1 << 11)) + write_phy(base, 0xa40, 16, power & ~(1 << 11)); + } else { + pr_info("Powering on COPPER\n"); + write_phy(base, 0xfff, 29, 1); + /* Ensure power is off */ + read_phy(base, 0xa40, 16, &power); + if (power & (1 << 11)) + write_phy(base, 0xa40, 16, power & ~(1 << 11)); + } + + write_phy(base, 0xfff, 29, 0); +} + +static bool rtl8380_rtl8214fc_media_is_fibre(int mac) +{ + int base = mac - (mac % 4); + static int reg[] = {16, 19, 20, 21}; + u32 val; + + write_phy(base, 0xfff, 29, 8); + read_phy(base, 0x266, reg[mac % 4], &val); + write_phy(base, 0xfff, 29, 0); + if (val & (1 << 11)) + return false; + return true; +} + +static int rtl8214fc_set_port(struct phy_device *phydev, int port) +{ + bool is_fibre = (port == PORT_FIBRE ? true : false); + int addr = phydev->mdio.addr; + + pr_debug("%s port %d to %d\n", __func__, addr, port); + + rtl8380_rtl8214fc_media_set(addr, is_fibre); + return 0; +} + +static int rtl8214fc_get_port(struct phy_device *phydev) +{ + int addr = phydev->mdio.addr; + + pr_debug("%s: port %d\n", __func__, addr); + if (rtl8380_rtl8214fc_media_is_fibre(addr)) + return PORT_FIBRE; + return PORT_MII; +} + +/* + * Enable EEE on the RTL8218B PHYs + * The method used is not the preferred way (which would be based on the MAC-EEE state, + * but the only way that works since the kernel first enables EEE in the MAC + * and then sets up the PHY. The MAC-based approach would require the oppsite. + */ +void rtl8218d_eee_set(int port, bool enable) +{ + u32 val; + bool an_enabled; + + pr_debug("In %s %d, enable %d\n", __func__, port, enable); + /* Set GPHY page to copper */ + write_phy(port, 0xa42, 30, 0x0001); + + read_phy(port, 0, 0, &val); + an_enabled = val & BIT(12); + + /* Enable 100M (bit 1) / 1000M (bit 2) EEE */ + read_mmd_phy(port, 7, 60, &val); + val |= BIT(2) | BIT(1); + write_mmd_phy(port, 7, 60, enable ? 0x6 : 0); + + /* 500M EEE ability */ + read_phy(port, 0xa42, 20, &val); + if (enable) + val |= BIT(7); + else + val &= ~BIT(7); + write_phy(port, 0xa42, 20, val); + + /* Restart AN if enabled */ + if (an_enabled) { + read_phy(port, 0, 0, &val); + val |= BIT(9); + write_phy(port, 0, 0, val); + } + + /* GPHY page back to auto*/ + write_phy(port, 0xa42, 30, 0); +} + +static int rtl8218b_get_eee(struct phy_device *phydev, + struct ethtool_eee *e) +{ + u32 val; + int addr = phydev->mdio.addr; + + pr_debug("In %s, port %d, was enabled: %d\n", __func__, addr, e->eee_enabled); + + /* Set GPHY page to copper */ + write_phy(addr, 0xa42, 29, 0x0001); + + read_phy(addr, 7, 60, &val); + if (e->eee_enabled) { + // Verify vs MAC-based EEE + e->eee_enabled = !!(val & BIT(7)); + if (!e->eee_enabled) { + read_phy(addr, 0x0A43, 25, &val); + e->eee_enabled = !!(val & BIT(4)); + } + } + pr_debug("%s: enabled: %d\n", __func__, e->eee_enabled); + + /* GPHY page to auto */ + write_phy(addr, 0xa42, 29, 0x0000); + + return 0; +} + +static int rtl8218d_get_eee(struct phy_device *phydev, + struct ethtool_eee *e) +{ + u32 val; + int addr = phydev->mdio.addr; + + pr_debug("In %s, port %d, was enabled: %d\n", __func__, addr, e->eee_enabled); + + /* Set GPHY page to copper */ + write_phy(addr, 0xa42, 30, 0x0001); + + read_phy(addr, 7, 60, &val); + if (e->eee_enabled) + e->eee_enabled = !!(val & BIT(7)); + pr_debug("%s: enabled: %d\n", __func__, e->eee_enabled); + + /* GPHY page to auto */ + write_phy(addr, 0xa42, 30, 0x0000); + + return 0; +} + +static int rtl8214fc_set_eee(struct phy_device *phydev, + struct ethtool_eee *e) +{ + u32 poll_state; + int port = phydev->mdio.addr; + bool an_enabled; + u32 val; + + pr_debug("In %s port %d, enabled %d\n", __func__, port, e->eee_enabled); + + if (rtl8380_rtl8214fc_media_is_fibre(port)) { + netdev_err(phydev->attached_dev, "Port %d configured for FIBRE", port); + return -ENOTSUPP; + } + + poll_state = disable_polling(port); + + /* Set GPHY page to copper */ + write_phy(port, 0xa42, 29, 0x0001); + + // Get auto-negotiation status + read_phy(port, 0, 0, &val); + an_enabled = val & BIT(12); + + pr_info("%s: aneg: %d\n", __func__, an_enabled); + read_phy(port, 0x0A43, 25, &val); + val &= ~BIT(5); // Use MAC-based EEE + write_phy(port, 0x0A43, 25, val); + + /* Enable 100M (bit 1) / 1000M (bit 2) EEE */ + write_phy(port, 7, 60, e->eee_enabled ? 0x6 : 0); + + /* 500M EEE ability */ + read_phy(port, 0xa42, 20, &val); + if (e->eee_enabled) + val |= BIT(7); + else + val &= ~BIT(7); + write_phy(port, 0xa42, 20, val); + + /* Restart AN if enabled */ + if (an_enabled) { + pr_info("%s: doing aneg\n", __func__); + read_phy(port, 0, 0, &val); + val |= BIT(9); + write_phy(port, 0, 0, val); + } + + /* GPHY page back to auto*/ + write_phy(port, 0xa42, 29, 0); + + resume_polling(poll_state); + + return 0; +} + +static int rtl8214fc_get_eee(struct phy_device *phydev, + struct ethtool_eee *e) +{ + int addr = phydev->mdio.addr; + + pr_debug("In %s port %d, enabled %d\n", __func__, addr, e->eee_enabled); + if (rtl8380_rtl8214fc_media_is_fibre(addr)) { + netdev_err(phydev->attached_dev, "Port %d configured for FIBRE", addr); + return -ENOTSUPP; + } + + return rtl8218b_get_eee(phydev, e); +} + +static int rtl8218b_set_eee(struct phy_device *phydev, struct ethtool_eee *e) +{ + int port = phydev->mdio.addr; + u64 poll_state; + u32 val; + bool an_enabled; + + pr_info("In %s, port %d, enabled %d\n", __func__, port, e->eee_enabled); + + poll_state = disable_polling(port); + + /* Set GPHY page to copper */ + write_phy(port, 0, 30, 0x0001); + read_phy(port, 0, 0, &val); + an_enabled = val & BIT(12); + + if (e->eee_enabled) { + /* 100/1000M EEE Capability */ + write_phy(port, 0, 13, 0x0007); + write_phy(port, 0, 14, 0x003C); + write_phy(port, 0, 13, 0x4007); + write_phy(port, 0, 14, 0x0006); + + read_phy(port, 0x0A43, 25, &val); + val |= BIT(4); + write_phy(port, 0x0A43, 25, val); + } else { + /* 100/1000M EEE Capability */ + write_phy(port, 0, 13, 0x0007); + write_phy(port, 0, 14, 0x003C); + write_phy(port, 0, 13, 0x0007); + write_phy(port, 0, 14, 0x0000); + + read_phy(port, 0x0A43, 25, &val); + val &= ~BIT(4); + write_phy(port, 0x0A43, 25, val); + } + + /* Restart AN if enabled */ + if (an_enabled) { + read_phy(port, 0, 0, &val); + val |= BIT(9); + write_phy(port, 0, 0, val); + } + + /* GPHY page back to auto*/ + write_phy(port, 0xa42, 30, 0); + + pr_info("%s done\n", __func__); + resume_polling(poll_state); + + return 0; +} + +static int rtl8218d_set_eee(struct phy_device *phydev, struct ethtool_eee *e) +{ + int addr = phydev->mdio.addr; + u64 poll_state; + + pr_info("In %s, port %d, enabled %d\n", __func__, addr, e->eee_enabled); + + poll_state = disable_polling(addr); + + rtl8218d_eee_set(addr, (bool) e->eee_enabled); + + resume_polling(poll_state); + + return 0; +} + +static int rtl8214c_match_phy_device(struct phy_device *phydev) +{ + return phydev->phy_id == PHY_ID_RTL8214C; +} + +static int rtl8380_configure_rtl8214c(struct phy_device *phydev) +{ + u32 phy_id, val; + int mac = phydev->mdio.addr; + + read_phy(mac, 0, 2, &val); + phy_id = val << 16; + read_phy(mac, 0, 3, &val); + phy_id |= val; + pr_debug("Phy on MAC %d: %x\n", mac, phy_id); + + phydev_info(phydev, "Detected external RTL8214C\n"); + + /* GPHY auto conf */ + write_phy(mac, 0xa42, 29, 0); + return 0; +} + +static int rtl8380_configure_rtl8214fc(struct phy_device *phydev) +{ + u32 phy_id, val, page = 0; + int i, l; + int mac = phydev->mdio.addr; + struct fw_header *h; + u32 *rtl8380_rtl8214fc_perchip; + u32 *rtl8380_rtl8214fc_perport; + + read_phy(mac, 0, 2, &val); + phy_id = val << 16; + read_phy(mac, 0, 3, &val); + phy_id |= val; + pr_debug("Phy on MAC %d: %x\n", mac, phy_id); + + /* Read internal PHY id */ + write_phy(mac, 0, 30, 0x0001); + write_phy(mac, 0, 31, 0x0a42); + write_phy(mac, 31, 27, 0x0002); + read_phy(mac, 31, 28, &val); + if (val != 0x6276) { + phydev_err(phydev, "Expected external RTL8214FC, found PHY-ID %x\n", val); + return -1; + } + phydev_info(phydev, "Detected external RTL8214FC\n"); + + h = rtl838x_request_fw(phydev, &rtl838x_8214fc_fw, FIRMWARE_838X_8214FC_1); + if (!h) + return -1; + + if (h->phy != 0x8214fc00) { + phydev_err(phydev, "Wrong firmware file: PHY mismatch.\n"); + return -1; + } + + rtl8380_rtl8214fc_perchip = (void *)h + sizeof(struct fw_header) + + h->parts[0].start; + + rtl8380_rtl8214fc_perport = (void *)h + sizeof(struct fw_header) + + h->parts[1].start; + + /* detect phy version */ + write_phy(mac, 0xfff, 27, 0x0004); + read_phy(mac, 0xfff, 28, &val); + + read_phy(mac, 0, 16, &val); + if (val & (1 << 11)) + rtl8380_rtl8214fc_on_off(mac, true); + else + rtl8380_phy_reset(mac); + + msleep(100); + write_phy(mac, 0, 30, 0x0001); + + i = 0; + while (rtl8380_rtl8214fc_perchip[i * 3] + && rtl8380_rtl8214fc_perchip[i * 3 + 1]) { + if (rtl8380_rtl8214fc_perchip[i * 3 + 1] == 0x1f) + page = rtl8380_rtl8214fc_perchip[i * 3 + 2]; + if (rtl8380_rtl8214fc_perchip[i * 3 + 1] == 0x13 && page == 0x260) { + read_phy(mac + rtl8380_rtl8214fc_perchip[i * 3], 0x260, 13, &val); + val = (val & 0x1f00) | (rtl8380_rtl8214fc_perchip[i * 3 + 2] + & 0xe0ff); + write_phy(mac + rtl8380_rtl8214fc_perchip[i * 3], + 0xfff, rtl8380_rtl8214fc_perchip[i * 3 + 1], val); + } else { + write_phy(mac + rtl8380_rtl8214fc_perchip[i * 3], + 0xfff, rtl8380_rtl8214fc_perchip[i * 3 + 1], + rtl8380_rtl8214fc_perchip[i * 3 + 2]); + } + i++; + } + + /* Force copper medium */ + for (i = 0; i < 4; i++) { + write_phy(mac + i, 0xfff, 0x1f, 0x0000); + write_phy(mac + i, 0xfff, 0x1e, 0x0001); + } + + /* Enable PHY */ + for (i = 0; i < 4; i++) { + write_phy(mac + i, 0xfff, 0x1f, 0x0000); + write_phy(mac + i, 0xfff, 0x00, 0x1140); + } + mdelay(100); + + /* Disable Autosensing */ + for (i = 0; i < 4; i++) { + for (l = 0; l < 100; l++) { + read_phy(mac + i, 0x0a42, 0x10, &val); + if ((val & 0x7) >= 3) + break; + } + if (l >= 100) { + phydev_err(phydev, "Could not disable autosensing\n"); + return -1; + } + } + + /* Request patch */ + for (i = 0; i < 4; i++) { + write_phy(mac + i, 0xfff, 0x1f, 0x0b82); + write_phy(mac + i, 0xfff, 0x10, 0x0010); + } + mdelay(300); + + /* Verify patch readiness */ + for (i = 0; i < 4; i++) { + for (l = 0; l < 100; l++) { + read_phy(mac + i, 0xb80, 0x10, &val); + if (val & 0x40) + break; + } + if (l >= 100) { + phydev_err(phydev, "Could not patch PHY\n"); + return -1; + } + } + + /* Use Broadcast ID method for patching */ + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0008); + write_phy(mac, 0xfff, 0x1f, 0x0266); + write_phy(mac, 0xfff, 0x16, 0xff00 + mac); + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0000); + mdelay(1); + + i = 0; + while (rtl8380_rtl8214fc_perport[i * 2]) { + write_phy(mac, 0xfff, rtl8380_rtl8214fc_perport[i * 2], + rtl8380_rtl8214fc_perport[i * 2 + 1]); + i++; + } + + /*Disable broadcast ID*/ + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0008); + write_phy(mac, 0xfff, 0x1f, 0x0266); + write_phy(mac, 0xfff, 0x16, 0x00 + mac); + write_phy(mac, 0xfff, 0x1f, 0x0000); + write_phy(mac, 0xfff, 0x1d, 0x0000); + mdelay(1); + + /* Auto medium selection */ + for (i = 0; i < 4; i++) { + write_phy(mac + i, 0xfff, 0x1f, 0x0000); + write_phy(mac + i, 0xfff, 0x1e, 0x0000); + } + + return 0; +} + +static int rtl8214fc_match_phy_device(struct phy_device *phydev) +{ + int addr = phydev->mdio.addr; + + return phydev->phy_id == PHY_ID_RTL8214FC && addr >= 24; +} + +static int rtl8380_configure_serdes(struct phy_device *phydev) +{ + u32 v; + u32 sds_conf_value; + int i; + struct fw_header *h; + u32 *rtl8380_sds_take_reset; + u32 *rtl8380_sds_common; + u32 *rtl8380_sds01_qsgmii_6275b; + u32 *rtl8380_sds23_qsgmii_6275b; + u32 *rtl8380_sds4_fiber_6275b; + u32 *rtl8380_sds5_fiber_6275b; + u32 *rtl8380_sds_reset; + u32 *rtl8380_sds_release_reset; + + phydev_info(phydev, "Detected internal RTL8380 SERDES\n"); + + h = rtl838x_request_fw(phydev, &rtl838x_8218b_fw, FIRMWARE_838X_8380_1); + if (!h) + return -1; + + if (h->magic != 0x83808380) { + phydev_err(phydev, "Wrong firmware file: magic number mismatch.\n"); + return -1; + } + + rtl8380_sds_take_reset = (void *)h + sizeof(struct fw_header) + + h->parts[0].start; + + rtl8380_sds_common = (void *)h + sizeof(struct fw_header) + + h->parts[1].start; + + rtl8380_sds01_qsgmii_6275b = (void *)h + sizeof(struct fw_header) + + h->parts[2].start; + + rtl8380_sds23_qsgmii_6275b = (void *)h + sizeof(struct fw_header) + + h->parts[3].start; + + rtl8380_sds4_fiber_6275b = (void *)h + sizeof(struct fw_header) + + h->parts[4].start; + + rtl8380_sds5_fiber_6275b = (void *)h + sizeof(struct fw_header) + + h->parts[5].start; + + rtl8380_sds_reset = (void *)h + sizeof(struct fw_header) + + h->parts[6].start; + + rtl8380_sds_release_reset = (void *)h + sizeof(struct fw_header) + + h->parts[7].start; + + /* Back up serdes power off value */ + sds_conf_value = sw_r32(RTL838X_SDS_CFG_REG); + pr_info("SDS power down value: %x\n", sds_conf_value); + + /* take serdes into reset */ + i = 0; + while (rtl8380_sds_take_reset[2 * i]) { + sw_w32(rtl8380_sds_take_reset[2 * i + 1], rtl8380_sds_take_reset[2 * i]); + i++; + udelay(1000); + } + + /* apply common serdes patch */ + i = 0; + while (rtl8380_sds_common[2 * i]) { + sw_w32(rtl8380_sds_common[2 * i + 1], rtl8380_sds_common[2 * i]); + i++; + udelay(1000); + } + + /* internal R/W enable */ + sw_w32(3, RTL838X_INT_RW_CTRL); + + /* SerDes ports 4 and 5 are FIBRE ports */ + sw_w32_mask(0x7 | 0x38, 1 | (1 << 3), RTL838X_INT_MODE_CTRL); + + /* SerDes module settings, SerDes 0-3 are QSGMII */ + v = 0x6 << 25 | 0x6 << 20 | 0x6 << 15 | 0x6 << 10; + /* SerDes 4 and 5 are 1000BX FIBRE */ + v |= 0x4 << 5 | 0x4; + sw_w32(v, RTL838X_SDS_MODE_SEL); + + pr_info("PLL control register: %x\n", sw_r32(RTL838X_PLL_CML_CTRL)); + sw_w32_mask(0xfffffff0, 0xaaaaaaaf & 0xf, RTL838X_PLL_CML_CTRL); + i = 0; + while (rtl8380_sds01_qsgmii_6275b[2 * i]) { + sw_w32(rtl8380_sds01_qsgmii_6275b[2 * i + 1], + rtl8380_sds01_qsgmii_6275b[2 * i]); + i++; + } + + i = 0; + while (rtl8380_sds23_qsgmii_6275b[2 * i]) { + sw_w32(rtl8380_sds23_qsgmii_6275b[2 * i + 1], rtl8380_sds23_qsgmii_6275b[2 * i]); + i++; + } + + i = 0; + while (rtl8380_sds4_fiber_6275b[2 * i]) { + sw_w32(rtl8380_sds4_fiber_6275b[2 * i + 1], rtl8380_sds4_fiber_6275b[2 * i]); + i++; + } + + i = 0; + while (rtl8380_sds5_fiber_6275b[2 * i]) { + sw_w32(rtl8380_sds5_fiber_6275b[2 * i + 1], rtl8380_sds5_fiber_6275b[2 * i]); + i++; + } + + i = 0; + while (rtl8380_sds_reset[2 * i]) { + sw_w32(rtl8380_sds_reset[2 * i + 1], rtl8380_sds_reset[2 * i]); + i++; + } + + i = 0; + while (rtl8380_sds_release_reset[2 * i]) { + sw_w32(rtl8380_sds_release_reset[2 * i + 1], rtl8380_sds_release_reset[2 * i]); + i++; + } + + pr_info("SDS power down value now: %x\n", sw_r32(RTL838X_SDS_CFG_REG)); + sw_w32(sds_conf_value, RTL838X_SDS_CFG_REG); + + pr_info("Configuration of SERDES done\n"); + return 0; +} + +static int rtl8390_configure_serdes(struct phy_device *phydev) +{ + phydev_info(phydev, "Detected internal RTL8390 SERDES\n"); + + /* In autoneg state, force link, set SR4_CFG_EN_LINK_FIB1G */ + sw_w32_mask(0, 1 << 18, RTL839X_SDS12_13_XSG0 + 0x0a); + + /* Disable EEE: Clear FRE16_EEE_RSG_FIB1G, FRE16_EEE_STD_FIB1G, + * FRE16_C1_PWRSAV_EN_FIB1G, FRE16_C2_PWRSAV_EN_FIB1G + * and FRE16_EEE_QUIET_FIB1G + */ + sw_w32_mask(0x1f << 10, 0, RTL839X_SDS12_13_XSG0 + 0xe0); + + return 0; +} + +int rtl9300_configure_serdes(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + int phy_addr = phydev->mdio.addr; + int sds_num = 0; + int v; + + phydev_info(phydev, "Configuring internal RTL9300 SERDES\n"); + + switch (phy_addr) { + case 26: + sds_num = 8; + break; + case 27: + sds_num = 9; + break; + default: + dev_err(dev, "Not a SerDes PHY\n"); + return -EINVAL; + } + + /* Set default Medium to fibre */ + v = rtl930x_read_sds_phy(sds_num, 0x1f, 11); + if (v < 0) { + dev_err(dev, "Cannot access SerDes PHY %d\n", phy_addr); + return -EINVAL; + } + v |= BIT(2); + rtl930x_write_sds_phy(sds_num, 0x1f, 11, v); + + // TODO: this needs to be configurable via ethtool/.dts + pr_info("Setting 10G/1000BX auto fibre medium\n"); + rtl9300_sds_rst(sds_num, 0x1b); + + // TODO: Apply patch set for fibre type + + return 0; +} + +static int rtl8214fc_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + /* 839x has internal SerDes */ + if (soc_info.id == 0x8393) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8214FC"; + + /* All base addresses of the PHYs start at multiples of 8 */ + if (!(addr % 8)) { + /* Configuration must be done whil patching still possible */ + return rtl8380_configure_rtl8214fc(phydev); + } + return 0; +} + +static int rtl8214c_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8214C"; + + /* All base addresses of the PHYs start at multiples of 8 */ + if (!(addr % 8)) { + /* Configuration must be done whil patching still possible */ + return rtl8380_configure_rtl8214c(phydev); + } + return 0; +} + +static int rtl8218b_ext_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8218B (external)"; + + /* All base addresses of the PHYs start at multiples of 8 */ + if (!(addr % 8) && soc_info.family == RTL8380_FAMILY_ID) { + /* Configuration must be done while patching still possible */ + return rtl8380_configure_ext_rtl8218b(phydev); + } + return 0; +} + +static int rtl8218b_int_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + if (soc_info.family != RTL8380_FAMILY_ID) + return -ENODEV; + if (addr >= 24) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8218B (internal)"; + + /* All base addresses of the PHYs start at multiples of 8 */ + if (!(addr % 8)) { + /* Configuration must be done while patching still possible */ + return rtl8380_configure_int_rtl8218b(phydev); + } + return 0; +} + +static int rtl8218d_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + pr_info("%s: id: %d\n", __func__, addr); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8218D"; + + /* All base addresses of the PHYs start at multiples of 8 */ + if (!(addr % 8)) { + /* Configuration must be done while patching still possible */ +// TODO: return configure_rtl8218d(phydev); + } + return 0; +} + +static int rtl8226_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + pr_info("%s: id: %d\n", __func__, addr); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8226"; + + return 0; +} + +static int rtl838x_serdes_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + if (soc_info.family != RTL8380_FAMILY_ID) + return -ENODEV; + if (addr < 24) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8380 Serdes"; + + /* On the RTL8380M, PHYs 24-27 connect to the internal SerDes */ + if (soc_info.id == 0x8380) { + if (addr == 24) + return rtl8380_configure_serdes(phydev); + return 0; + } + return -ENODEV; +} + +static int rtl8393_serdes_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + pr_info("%s: id: %d\n", __func__, addr); + if (soc_info.family != RTL8390_FAMILY_ID) + return -ENODEV; + + if (addr < 24) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8393 Serdes"; + return rtl8390_configure_serdes(phydev); +} + +static int rtl8390_serdes_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + if (soc_info.family != RTL8390_FAMILY_ID) + return -ENODEV; + + if (addr < 24) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8390 Serdes"; + return rtl8390_configure_generic(phydev); +} + +static int rtl9300_serdes_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + if (soc_info.family != RTL9300_FAMILY_ID) + return -ENODEV; + + if (addr < 24) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL9300 Serdes"; + return rtl9300_configure_serdes(phydev); +} + +static struct phy_driver rtl83xx_phy_driver[] = { + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8214C), + .name = "Realtek RTL8214C", + .features = PHY_GBIT_FEATURES, + .match_phy_device = rtl8214c_match_phy_device, + .probe = rtl8214c_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC), + .name = "Realtek RTL8214FC", + .features = PHY_GBIT_FIBRE_FEATURES, + .match_phy_device = rtl8214fc_match_phy_device, + .probe = rtl8214fc_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_mmd = rtl8218b_read_mmd, + .write_mmd = rtl8218b_write_mmd, + .set_port = rtl8214fc_set_port, + .get_port = rtl8214fc_get_port, + .set_eee = rtl8214fc_set_eee, + .get_eee = rtl8214fc_get_eee, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_E), + .name = "Realtek RTL8218B (external)", + .features = PHY_GBIT_FEATURES, + .match_phy_device = rtl8218b_ext_match_phy_device, + .probe = rtl8218b_ext_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_mmd = rtl8218b_read_mmd, + .write_mmd = rtl8218b_write_mmd, + .set_eee = rtl8218b_set_eee, + .get_eee = rtl8218b_get_eee, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8218D), + .name = "REALTEK RTL8218D", + .features = PHY_GBIT_FEATURES, + .probe = rtl8218d_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .set_eee = rtl8218d_set_eee, + .get_eee = rtl8218d_get_eee, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8226), + .name = "REALTEK RTL8226", + .features = PHY_GBIT_FEATURES, + .probe = rtl8226_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_mmd = rtl8226_read_mmd, + .write_mmd = rtl8226_write_mmd, + .read_page = rtl8226_read_page, + .write_page = rtl8226_write_page, + .read_status = rtl8226_read_status, + .config_aneg = rtl8226_config_aneg, + .set_eee = rtl8226_set_eee, + .get_eee = rtl8226_get_eee, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_I), + .name = "Realtek RTL8218B (internal)", + .features = PHY_GBIT_FEATURES, + .probe = rtl8218b_int_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_mmd = rtl8218b_read_mmd, + .write_mmd = rtl8218b_write_mmd, + .set_eee = rtl8218b_set_eee, + .get_eee = rtl8218b_get_eee, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_I), + .name = "Realtek RTL8380 SERDES", + .features = PHY_GBIT_FIBRE_FEATURES, + .probe = rtl838x_serdes_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_mmd = rtl8218b_read_mmd, + .write_mmd = rtl8218b_write_mmd, + .read_status = rtl8380_read_status, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8393_I), + .name = "Realtek RTL8393 SERDES", + .features = PHY_GBIT_FIBRE_FEATURES, + .probe = rtl8393_serdes_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_status = rtl8393_read_status, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8390_GENERIC), + .name = "Realtek RTL8390 Generic", + .features = PHY_GBIT_FIBRE_FEATURES, + .probe = rtl8390_serdes_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL9300_I), + .name = "REALTEK RTL9300 SERDES", + .features = PHY_GBIT_FIBRE_FEATURES, + .probe = rtl9300_serdes_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + }, +}; + +module_phy_driver(rtl83xx_phy_driver); + +static struct mdio_device_id __maybe_unused rtl83xx_tbl[] = { + { PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC) }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, rtl83xx_tbl); + +MODULE_AUTHOR("B. Koblitz"); +MODULE_DESCRIPTION("RTL83xx PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h new file mode 100644 index 0000000000..031ec8a0e9 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-only + +// TODO: not really used +struct rtl838x_phy_priv { + char *name; +}; + +struct __attribute__ ((__packed__)) part { + uint16_t start; + uint8_t wordsize; + uint8_t words; +}; + +struct __attribute__ ((__packed__)) fw_header { + uint32_t magic; + uint32_t phy; + uint32_t checksum; + uint32_t version; + struct part parts[10]; +}; + +// TODO: fixed path? +#define FIRMWARE_838X_8380_1 "rtl838x_phy/rtl838x_8380.fw" +#define FIRMWARE_838X_8214FC_1 "rtl838x_phy/rtl838x_8214fc.fw" +#define FIRMWARE_838X_8218b_1 "rtl838x_phy/rtl838x_8218b.fw" + +/* External RTL8218B and RTL8214FC IDs are identical */ +#define PHY_ID_RTL8214C 0x001cc942 +#define PHY_ID_RTL8214FC 0x001cc981 +#define PHY_ID_RTL8218B_E 0x001cc981 +#define PHY_ID_RTL8218D 0x001cc983 +#define PHY_ID_RTL8218B_I 0x001cca40 +#define PHY_ID_RTL8226 0x001cc838 +#define PHY_ID_RTL8390_GENERIC 0x001ccab0 +#define PHY_ID_RTL8393_I 0x001c8393 +#define PHY_ID_RTL9300_I 0x70d03106 + +// PHY MMD devices +#define MMD_AN 7 +#define MMD_VEND2 31 + +/* Registers of the internal Serdes of the 8380 */ +#define RTL838X_SDS_MODE_SEL (0x0028) +#define RTL838X_SDS_CFG_REG (0x0034) +#define RTL838X_INT_MODE_CTRL (0x005c) +#define RTL838X_DMY_REG31 (0x3b28) + +#define RTL8380_SDS4_FIB_REG0 (0xF800) +#define RTL838X_SDS4_REG28 (0xef80) +#define RTL838X_SDS4_DUMMY0 (0xef8c) +#define RTL838X_SDS5_EXT_REG6 (0xf18c) +#define RTL838X_SDS4_FIB_REG0 (RTL838X_SDS4_REG28 + 0x880) +#define RTL838X_SDS5_FIB_REG0 (RTL838X_SDS4_REG28 + 0x980) + +/* Registers of the internal SerDes of the RTL8390 */ +#define RTL839X_SDS12_13_XSG0 (0xB800) + +/* Registers of the internal Serdes of the 9300 */ +#define RTL930X_SDS_INDACS_CMD (0x03B0) +#define RTL930X_SDS_INDACS_DATA (0x03B4) diff --git a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch new file mode 100644 index 0000000000..ecc77b2a73 --- /dev/null +++ b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch @@ -0,0 +1,39 @@ +--- a/arch/mips/Kbuild.platforms ++++ b/arch/mips/Kbuild.platforms +@@ -27,6 +27,7 @@ platforms += pistachio + platforms += pmcs-msp71xx + platforms += pnx833x + platforms += ralink ++platforms += rtl838x + platforms += rb532 + platforms += sgi-ip22 + platforms += sgi-ip27 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -631,6 +631,26 @@ config RALINK + select ARCH_HAS_RESET_CONTROLLER + select RESET_CONTROLLER + ++config RTL838X ++ bool "Realtek based platforms" ++ select DMA_NONCOHERENT ++ select IRQ_MIPS_CPU ++ select CSRC_R4K ++ select CEVT_R4K ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_CPU_MIPS32_R2 ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_MIPS16 ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_HAS_EARLY_PRINTK_8250 ++ select USE_GENERIC_EARLY_PRINTK_8250 ++ select BOOT_RAW ++ select PINCTRL ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select USE_OF ++ + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" + select FW_ARC diff --git a/target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch b/target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch new file mode 100644 index 0000000000..4f5901d87f --- /dev/null +++ b/target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch @@ -0,0 +1,32 @@ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -441,6 +441,18 @@ config GPIO_REG + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + ++config GPIO_RTL8231 ++ tristate "RTL8231 GPIO" ++ depends on GPIO_RTL838X ++ help ++ Say yes here to support Realtek RTL8231 GPIO expansion chips. ++ ++config GPIO_RTL838X ++ tristate "RTL838X GPIO" ++ depends on RTL838X ++ help ++ Say yes here to support RTL838X GPIO devices. ++ + config GPIO_SAMA5D2_PIOBU + tristate "SAMA5D2 PIOBU GPIO support" + depends on MFD_SYSCON +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -117,6 +117,8 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_GPIO_REG) += gpio-reg.o ++obj-$(CONFIG_GPIO_RTL8231) += gpio-rtl8231.o ++obj-$(CONFIG_GPIO_RTL838X) += gpio-rtl838x.o + obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o + obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o + obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch b/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch new file mode 100644 index 0000000000..1c41db75b2 --- /dev/null +++ b/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch @@ -0,0 +1,34 @@ +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -127,6 +127,15 @@ config RDA_TIMER + help + Enables the support for the RDA Micro timer driver. + ++config RTL9300_TIMER ++ bool "Clocksource/timer for the Realtek RTL9300 family of SoCs" ++ depends on MIPS ++ select COMMON_CLK ++ select TIMER_OF ++ select CLKSRC_MMIO ++ help ++ Enables support for the Realtek RTL9300 timer driver. ++ + config SUN4I_TIMER + bool "Sun4i timer driver" if COMPILE_TEST + depends on HAS_IOMEM +@@ -696,5 +705,4 @@ config INGENIC_TIMER + select IRQ_DOMAIN + help + Support for the timer/counter unit of the Ingenic JZ SoCs. +- + endmenu +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -61,6 +61,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) += timer-mi + obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o + obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o + obj-$(CONFIG_RDA_TIMER) += timer-rda.o ++obj-$(CONFIG_RTL9300_TIMER) += timer-rtl9300.o + + obj-$(CONFIG_ARC_TIMERS) += arc_timer.o + obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o diff --git a/target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch b/target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch new file mode 100644 index 0000000000..16cff75308 --- /dev/null +++ b/target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch @@ -0,0 +1,23 @@ +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -118,4 +118,13 @@ config SPI_INTEL_SPI_PLATFORM + To compile this driver as a module, choose M here: the module + will be called intel-spi-platform. + ++config SPI_RTL838X ++ tristate "Realtek RTl838X SPI flash platform driver" ++ depends on RTL838X ++ help ++ This driver provides support for accessing SPI flash ++ in the RTL838X SoC. ++ ++ Say N here unless you know what you are doing. ++ + endif # MTD_SPI_NOR +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi + obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o + obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o + obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o ++obj-$(CONFIG_SPI_RTL838X) += rtl838x-nor.o diff --git a/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch b/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch new file mode 100644 index 0000000000..bb6f83e55d --- /dev/null +++ b/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -63,6 +63,8 @@ config NET_DSA_QCA8K + This enables support for the Qualcomm Atheros QCA8K Ethernet + switch chips. + ++source "drivers/net/dsa/rtl83xx/Kconfig" ++ + config NET_DSA_REALTEK_SMI + tristate "Realtek SMI Ethernet switch family support" + depends on NET_DSA +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -21,3 +21,4 @@ obj-y += b53/ + obj-y += microchip/ + obj-y += mv88e6xxx/ + obj-y += sja1105/ ++obj-y += rtl83xx/ diff --git a/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch b/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch new file mode 100644 index 0000000000..803614e7c0 --- /dev/null +++ b/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch @@ -0,0 +1,40 @@ +--- a/net/dsa/tag_trailer.c ++++ b/net/dsa/tag_trailer.c +@@ -44,7 +44,12 @@ static struct sk_buff *trailer_xmit(stru + + trailer = skb_put(nskb, 4); + trailer[0] = 0x80; ++ ++#ifdef CONFIG_NET_DSA_RTL83XX ++ trailer[1] = dp->index; ++#else + trailer[1] = 1 << dp->index; ++#endif /* CONFIG_NET_DSA_RTL838X */ + trailer[2] = 0x10; + trailer[3] = 0x00; + +@@ -61,12 +66,23 @@ static struct sk_buff *trailer_rcv(struc + return NULL; + + trailer = skb_tail_pointer(skb) - 4; ++ ++#ifdef CONFIG_NET_DSA_RTL83XX ++ if (trailer[0] != 0x80 || (trailer[1] & 0x80) != 0x00 || ++ (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00) ++ return NULL; ++ ++ if (trailer[1] & 0x40) ++ skb->offload_fwd_mark = 1; ++ ++ source_port = trailer[1] & 0x3f; ++#else + if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 || + (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00) + return NULL; + + source_port = trailer[1] & 7; +- ++#endif + skb->dev = dsa_master_find_slave(dev, 0, source_port); + if (!skb->dev) + return NULL; diff --git a/target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch b/target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch new file mode 100644 index 0000000000..929f2b9444 --- /dev/null +++ b/target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch @@ -0,0 +1,11 @@ +--- a/include/linux/platform_data/dsa.h ++++ b/include/linux/platform_data/dsa.h +@@ -6,7 +6,7 @@ struct device; + struct net_device; + + #define DSA_MAX_SWITCHES 4 +-#define DSA_MAX_PORTS 12 ++#define DSA_MAX_PORTS 54 + #define DSA_RTABLE_NONE -1 + + struct dsa_chip_data { diff --git a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch new file mode 100644 index 0000000000..11e62450d5 --- /dev/null +++ b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/ethernet/Kconfig ++++ b/drivers/net/ethernet/Kconfig +@@ -163,6 +163,13 @@ source "drivers/net/ethernet/rdc/Kconfig + source "drivers/net/ethernet/realtek/Kconfig" + source "drivers/net/ethernet/renesas/Kconfig" + source "drivers/net/ethernet/rocker/Kconfig" ++ ++config NET_RTL838X ++ tristate "Realtek rtl838x Ethernet MAC support" ++ depends on RTL838X ++ ---help--- ++ Say Y here if you want to use the Realtek rtl838x Gbps Ethernet MAC. ++ + source "drivers/net/ethernet/samsung/Kconfig" + source "drivers/net/ethernet/seeq/Kconfig" + source "drivers/net/ethernet/sfc/Kconfig" +--- a/drivers/net/ethernet/Makefile ++++ b/drivers/net/ethernet/Makefile +@@ -76,6 +76,7 @@ obj-$(CONFIG_NET_VENDOR_REALTEK) += real + obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/ + obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ + obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/ ++obj-$(CONFIG_NET_RTL838X) += rtl838x_eth.o + obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/ + obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/ + obj-$(CONFIG_NET_VENDOR_SILAN) += silan/ diff --git a/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch b/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch new file mode 100644 index 0000000000..3682eb30a3 --- /dev/null +++ b/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch @@ -0,0 +1,13 @@ +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -645,6 +645,10 @@ struct phy_driver { + struct ethtool_tunable *tuna, + const void *data); + int (*set_loopback)(struct phy_device *dev, bool enable); ++ int (*get_port)(struct phy_device *dev); ++ int (*set_port)(struct phy_device *dev, int port); ++ int (*get_eee)(struct phy_device *dev, struct ethtool_eee *e); ++ int (*set_eee)(struct phy_device *dev, struct ethtool_eee *e); + }; + #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ + struct phy_driver, mdiodrv) diff --git a/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch b/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch new file mode 100644 index 0000000000..7743147ea3 --- /dev/null +++ b/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch @@ -0,0 +1,41 @@ +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1242,6 +1242,11 @@ int phylink_ethtool_ksettings_set(struct + + /* If we have a PHY, configure the phy */ + if (pl->phydev) { ++ if (pl->phydev->drv->get_port && pl->phydev->drv->set_port) { ++ if(pl->phydev->drv->get_port(pl->phydev) != kset->base.port) { ++ pl->phydev->drv->set_port(pl->phydev, kset->base.port); ++ } ++ } + ret = phy_ethtool_ksettings_set(pl->phydev, &our_kset); + if (ret) + return ret; +@@ -1420,8 +1425,11 @@ int phylink_ethtool_get_eee(struct phyli + + ASSERT_RTNL(); + +- if (pl->phydev) ++ if (pl->phydev) { ++ if (pl->phydev->drv->get_eee) ++ return pl->phydev->drv->get_eee(pl->phydev, eee); + ret = phy_ethtool_get_eee(pl->phydev, eee); ++ } + + return ret; + } +@@ -1438,9 +1446,11 @@ int phylink_ethtool_set_eee(struct phyli + + ASSERT_RTNL(); + +- if (pl->phydev) ++ if (pl->phydev) { ++ if (pl->phydev->drv->set_eee) ++ return pl->phydev->drv->set_eee(pl->phydev, eee); + ret = phy_ethtool_set_eee(pl->phydev, eee); +- ++ } + return ret; + } + EXPORT_SYMBOL_GPL(phylink_ethtool_set_eee); diff --git a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch new file mode 100644 index 0000000000..f4cd8f2d6d --- /dev/null +++ b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -540,6 +540,12 @@ config REALTEK_PHY + ---help--- + Supports the Realtek 821x PHY. + ++config REALTEK_SOC_PHY ++ tristate "Realtek SoC PHYs" ++ depends on RTL838X ++ ---help--- ++ Supports the PHYs found in combination with Realtek Switch SoCs ++ + config RENESAS_PHY + tristate "Driver for Renesas PHYs" + ---help--- +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -102,6 +102,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o ++obj-$(CONFIG_REALTEK_SOC_PHY) += rtl83xx-phy.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o + obj-$(CONFIG_SMSC_PHY) += smsc.o diff --git a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch new file mode 100644 index 0000000000..ca6deb74d8 --- /dev/null +++ b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch @@ -0,0 +1,11 @@ +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -188,7 +188,7 @@ static inline const char *phy_modes(phy_ + #define PHY_INIT_TIMEOUT 100000 + #define PHY_FORCE_TIMEOUT 10 + +-#define PHY_MAX_ADDR 32 ++#define PHY_MAX_ADDR 64 + + /* Used when trying to connect to a specific phy (mii bus id:phy device id) */ + #define PHY_ID_FMT "%s:%02x" From 1651bd9bc61550a7f3b2d25a8ef6c54dc0b61ce3 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 24 Jun 2021 20:22:51 +0900 Subject: [PATCH 59/82] realtek: drop rtl838x spi-nor driver from 5.10 To backport the upstreamed driver (spi-realtek-rtl) from 5.12, drop the old driver from realtek target. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/config-5.10 | 1 - .../drivers/mtd/spi-nor/rtl838x-nor.c | 603 ------------------ .../drivers/mtd/spi-nor/rtl838x-spi.h | 111 ---- ...400-mtd-add-rtl838x-spi-flash-driver.patch | 23 - 4 files changed, 738 deletions(-) delete mode 100644 target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c delete mode 100644 target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h delete mode 100644 target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 index 5e29879798..3c953f3f56 100644 --- a/target/linux/realtek/config-5.10 +++ b/target/linux/realtek/config-5.10 @@ -171,7 +171,6 @@ CONFIG_SFP=y CONFIG_SPI=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y -CONFIG_SPI_RTL838X=y CONFIG_SRCU=y CONFIG_SWAP_IO_SPACE=y CONFIG_SWPHY=y diff --git a/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c b/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c deleted file mode 100644 index 35bf53ea5a..0000000000 --- a/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-nor.c +++ /dev/null @@ -1,603 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtl838x-spi.h" -#include - -extern struct rtl83xx_soc_info soc_info; - -struct rtl838x_nor { - struct spi_nor nor; - struct device *dev; - volatile void __iomem *base; - bool fourByteMode; - u32 chipSize; - uint32_t flags; - uint32_t io_status; -}; - -static uint32_t spi_prep(struct rtl838x_nor *rtl838x_nor) -{ - /* Needed because of MMU constraints */ - SPI_WAIT_READY; - spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1 - spi_w32w(0, SFCSR); //activate CS0,CS1 - spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1 - - return (CS0 & rtl838x_nor->flags) ? (SPI_eCS0 & SPI_LEN_INIT) - : ((SPI_eCS1 & SPI_LEN_INIT) | SFCSR_CHIP_SEL); -} - -static uint32_t rtl838x_nor_get_SR(struct rtl838x_nor *rtl838x_nor) -{ - uint32_t sfcsr, sfdr; - - sfcsr = spi_prep(rtl838x_nor); - sfdr = (SPINOR_OP_RDSR)<<24; - - pr_debug("%s: rdid,sfcsr_val = %.8x,SFDR = %.8x\n", __func__, sfcsr, sfdr); - pr_debug("rdid,sfcsr = %.8x\n", sfcsr | SPI_LEN4); - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - spi_w32_mask(0, SPI_LEN4, SFCSR); - SPI_WAIT_READY; - - return spi_r32(SFDR); -} - -static void spi_write_disable(struct rtl838x_nor *rtl838x_nor) -{ - uint32_t sfcsr, sfdr; - - sfcsr = spi_prep(rtl838x_nor); - sfdr = (SPINOR_OP_WRDI) << 24; - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr); - - spi_prep(rtl838x_nor); -} - -static void spi_write_enable(struct rtl838x_nor *rtl838x_nor) -{ - uint32_t sfcsr, sfdr; - - sfcsr = spi_prep(rtl838x_nor); - sfdr = (SPINOR_OP_WREN) << 24; - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr); - - spi_prep(rtl838x_nor); -} - -static void spi_4b_set(struct rtl838x_nor *rtl838x_nor, bool enable) -{ - uint32_t sfcsr, sfdr; - - sfcsr = spi_prep(rtl838x_nor); - if (enable) - sfdr = (SPINOR_OP_EN4B) << 24; - else - sfdr = (SPINOR_OP_EX4B) << 24; - - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr); - - spi_prep(rtl838x_nor); -} - -static int rtl838x_get_addr_mode(struct rtl838x_nor *rtl838x_nor) -{ - int res = 3; - u32 reg; - - sw_w32(0x3, RTL838X_INT_RW_CTRL); - if (!sw_r32(RTL838X_EXT_VERSION)) { - if (sw_r32(RTL838X_STRAP_DBG) & (1 << 29)) - res = 4; - } else { - reg = sw_r32(RTL838X_PLL_CML_CTRL); - if ((reg & (1 << 30)) && (reg & (1 << 31))) - res = 4; - if ((!(reg & (1 << 30))) - && sw_r32(RTL838X_STRAP_DBG) & (1 << 29)) - res = 4; - } - sw_w32(0x0, RTL838X_INT_RW_CTRL); - return res; -} - -static int rtl8390_get_addr_mode(struct rtl838x_nor *rtl838x_nor) -{ - if (spi_r32(RTL8390_SOC_SPI_MMIO_CONF) & (1 << 9)) - return 4; - return 3; -} - -ssize_t rtl838x_do_read(struct rtl838x_nor *rtl838x_nor, loff_t from, - size_t length, u_char *buffer, uint8_t command) -{ - uint32_t sfcsr, sfdr; - uint32_t len = length; - - sfcsr = spi_prep(rtl838x_nor); - sfdr = command << 24; - - /* Perform SPINOR_OP_READ: 1 byte command & 3 byte addr*/ - sfcsr |= SPI_LEN4; - sfdr |= from; - - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - - /* Read Data, 4 bytes at a time */ - while (length >= 4) { - SPI_WAIT_READY; - *((uint32_t *) buffer) = spi_r32(SFDR); - buffer += 4; - length -= 4; - } - - /* The rest needs to be read 1 byte a time */ - sfcsr &= SPI_LEN_INIT|SPI_LEN1; - SPI_WAIT_READY; - spi_w32w(sfcsr, SFCSR); - while (length > 0) { - SPI_WAIT_READY; - *(buffer) = spi_r32(SFDR) >> 24; - buffer++; - length--; - } - return len; -} - -/* - * Do fast read in 3 or 4 Byte addressing mode - */ -static ssize_t rtl838x_do_4bf_read(struct rtl838x_nor *rtl838x_nor, loff_t from, - size_t length, u_char *buffer, uint8_t command) -{ - int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2; - int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8; - uint32_t sfcsr; - uint32_t len = length; - - pr_debug("Fast read from %llx, len %x, shift %d\n", - from, sfcsr_addr_len, sfdr_addr_shift); - sfcsr = spi_prep(rtl838x_nor); - - /* Send read command */ - spi_w32w(sfcsr | SPI_LEN1, SFCSR); - spi_w32w(command << 24, SFDR); - - /* Send address */ - spi_w32w(sfcsr | (sfcsr_addr_len << 28), SFCSR); - spi_w32w(from << sfdr_addr_shift, SFDR); - - /* Dummy cycles */ - spi_w32w(sfcsr | SPI_LEN1, SFCSR); - spi_w32w(0, SFDR); - - /* Start reading */ - spi_w32w(sfcsr | SPI_LEN4, SFCSR); - - /* Read Data, 4 bytes at a time */ - while (length >= 4) { - SPI_WAIT_READY; - *((uint32_t *) buffer) = spi_r32(SFDR); - buffer += 4; - length -= 4; - } - - /* The rest needs to be read 1 byte a time */ - sfcsr &= SPI_LEN_INIT|SPI_LEN1; - SPI_WAIT_READY; - spi_w32w(sfcsr, SFCSR); - while (length > 0) { - SPI_WAIT_READY; - *(buffer) = spi_r32(SFDR) >> 24; - buffer++; - length--; - } - return len; - -} - -/* - * Do write (Page Programming) in 3 or 4 Byte addressing mode - */ -static ssize_t rtl838x_do_4b_write(struct rtl838x_nor *rtl838x_nor, loff_t to, - size_t length, const u_char *buffer, - uint8_t command) -{ - int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2; - int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8; - uint32_t sfcsr; - uint32_t len = length; - - pr_debug("Write to %llx, len %x, shift %d\n", - to, sfcsr_addr_len, sfdr_addr_shift); - sfcsr = spi_prep(rtl838x_nor); - - /* Send write command, command IO-width is 1 (bit 25/26) */ - spi_w32w(sfcsr | SPI_LEN1 | (0 << 25), SFCSR); - spi_w32w(command << 24, SFDR); - - /* Send address */ - spi_w32w(sfcsr | (sfcsr_addr_len << 28) | (0 << 25), SFCSR); - spi_w32w(to << sfdr_addr_shift, SFDR); - - /* Write Data, 1 byte at a time, if we are not 4-byte aligned */ - if (((long)buffer) % 4) { - spi_w32w(sfcsr | SPI_LEN1, SFCSR); - while (length > 0 && (((long)buffer) % 4)) { - SPI_WAIT_READY; - spi_w32(*(buffer) << 24, SFDR); - buffer += 1; - length -= 1; - } - } - - /* Now we can write 4 bytes at a time */ - SPI_WAIT_READY; - spi_w32w(sfcsr | SPI_LEN4, SFCSR); - while (length >= 4) { - SPI_WAIT_READY; - spi_w32(*((uint32_t *)buffer), SFDR); - buffer += 4; - length -= 4; - } - - /* Final bytes might need to be written 1 byte at a time, again */ - SPI_WAIT_READY; - spi_w32w(sfcsr | SPI_LEN1, SFCSR); - while (length > 0) { - SPI_WAIT_READY; - spi_w32(*(buffer) << 24, SFDR); - buffer++; - length--; - } - return len; -} - -static ssize_t rtl838x_nor_write(struct spi_nor *nor, loff_t to, size_t len, - const u_char *buffer) -{ - int ret = 0; - uint32_t offset = 0; - struct rtl838x_nor *rtl838x_nor = nor->priv; - size_t l = len; - uint8_t cmd = SPINOR_OP_PP; - - /* Do write in 4-byte mode on large Macronix chips */ - if (rtl838x_nor->fourByteMode) { - cmd = SPINOR_OP_PP_4B; - spi_4b_set(rtl838x_nor, true); - } - - pr_debug("In %s %8x to: %llx\n", __func__, - (unsigned int) rtl838x_nor, to); - - while (l >= SPI_MAX_TRANSFER_SIZE) { - while - (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); - do { - spi_write_enable(rtl838x_nor); - } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); - ret = rtl838x_do_4b_write(rtl838x_nor, to + offset, - SPI_MAX_TRANSFER_SIZE, buffer+offset, cmd); - l -= SPI_MAX_TRANSFER_SIZE; - offset += SPI_MAX_TRANSFER_SIZE; - } - - if (l > 0) { - while - (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); - do { - spi_write_enable(rtl838x_nor); - } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); - ret = rtl838x_do_4b_write(rtl838x_nor, to+offset, - len, buffer+offset, cmd); - } - - return len; -} - -static ssize_t rtl838x_nor_read(struct spi_nor *nor, loff_t from, - size_t length, u_char *buffer) -{ - uint32_t offset = 0; - uint8_t cmd = SPINOR_OP_READ_FAST; - size_t l = length; - struct rtl838x_nor *rtl838x_nor = nor->priv; - - /* Do fast read in 3, or 4-byte mode on large Macronix chips */ - if (rtl838x_nor->fourByteMode) { - cmd = SPINOR_OP_READ_FAST_4B; - spi_4b_set(rtl838x_nor, true); - } - - /* TODO: do timeout and return error */ - pr_debug("Waiting for pending writes\n"); - while - (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); - do { - spi_write_enable(rtl838x_nor); - } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); - - pr_debug("cmd is %d\n", cmd); - pr_debug("%s: addr %.8llx to addr %.8x, cmd %.8x, size %d\n", __func__, - from, (u32)buffer, (u32)cmd, length); - - while (l >= SPI_MAX_TRANSFER_SIZE) { - rtl838x_do_4bf_read(rtl838x_nor, from + offset, - SPI_MAX_TRANSFER_SIZE, buffer+offset, cmd); - l -= SPI_MAX_TRANSFER_SIZE; - offset += SPI_MAX_TRANSFER_SIZE; - } - - if (l > 0) - rtl838x_do_4bf_read(rtl838x_nor, from + offset, l, buffer+offset, cmd); - - return length; -} - -static int rtl838x_erase(struct spi_nor *nor, loff_t offs) -{ - struct rtl838x_nor *rtl838x_nor = nor->priv; - int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2; - int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8; - uint32_t sfcsr; - uint8_t cmd = SPINOR_OP_SE; - - pr_debug("Erasing sector at %llx\n", offs); - - /* Do erase in 4-byte mode on large Macronix chips */ - if (rtl838x_nor->fourByteMode) { - cmd = SPINOR_OP_SE_4B; - spi_4b_set(rtl838x_nor, true); - } - /* TODO: do timeout and return error */ - while - (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP); - do { - spi_write_enable(rtl838x_nor); - } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL)); - - sfcsr = spi_prep(rtl838x_nor); - - /* Send erase command, command IO-width is 1 (bit 25/26) */ - spi_w32w(sfcsr | SPI_LEN1 | (0 << 25), SFCSR); - spi_w32w(cmd << 24, SFDR); - - /* Send address */ - spi_w32w(sfcsr | (sfcsr_addr_len << 28) | (0 << 25), SFCSR); - spi_w32w(offs << sfdr_addr_shift, SFDR); - - return 0; -} - -static int rtl838x_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -{ - int length = len; - u8 *buffer = buf; - uint32_t sfcsr, sfdr; - struct rtl838x_nor *rtl838x_nor = nor->priv; - - pr_debug("In %s: opcode %x, len %x\n", __func__, opcode, len); - - sfcsr = spi_prep(rtl838x_nor); - sfdr = opcode << 24; - - sfcsr |= SPI_LEN1; - - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - - while (length > 0) { - SPI_WAIT_READY; - *(buffer) = spi_r32(SFDR) >> 24; - buffer++; - length--; - } - - return len; -} - -static int rtl838x_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -{ - uint32_t sfcsr, sfdr; - struct rtl838x_nor *rtl838x_nor = nor->priv; - - pr_debug("In %s, opcode %x, len %x\n", __func__, opcode, len); - sfcsr = spi_prep(rtl838x_nor); - sfdr = opcode << 24; - - if (len == 1) { /* SPINOR_OP_WRSR */ - sfdr |= buf[0]; - sfcsr |= SPI_LEN2; - } - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - return 0; -} - -static int spi_enter_sio(struct spi_nor *nor) -{ - uint32_t sfcsr, sfcr2, sfdr; - uint32_t ret = 0, reg = 0, size_bits; - struct rtl838x_nor *rtl838x_nor = nor->priv; - - pr_debug("In %s\n", __func__); - rtl838x_nor->io_status = 0; - sfdr = SPI_C_RSTQIO << 24; - sfcsr = spi_prep(rtl838x_nor); - - reg = spi_r32(SFCR2); - pr_debug("SFCR2: %x, size %x, rdopt: %x\n", reg, SFCR2_GETSIZE(reg), - (reg & SFCR2_RDOPT)); - size_bits = rtl838x_nor->fourByteMode ? SFCR2_SIZE(0x6) : SFCR2_SIZE(0x7); - - sfcr2 = SFCR2_HOLD_TILL_SFDR2 | size_bits - | (reg & SFCR2_RDOPT) | SFCR2_CMDIO(0) - | SFCR2_ADDRIO(0) | SFCR2_DUMMYCYCLE(4) - | SFCR2_DATAIO(0) | SFCR2_SFCMD(SPINOR_OP_READ_FAST); - pr_debug("SFCR2: %x, size %x\n", reg, SFCR2_GETSIZE(reg)); - - SPI_WAIT_READY; - spi_w32w(sfcr2, SFCR2); - spi_w32w(sfcsr, SFCSR); - spi_w32w(sfdr, SFDR); - - spi_w32_mask(SFCR2_HOLD_TILL_SFDR2, 0, SFCR2); - rtl838x_nor->io_status &= ~IOSTATUS_CIO_MASK; - rtl838x_nor->io_status |= CIO1; - - spi_prep(rtl838x_nor); - - return ret; -} - -int rtl838x_spi_nor_scan(struct spi_nor *nor, const char *name) -{ - static const struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ | SNOR_HWCAPS_PP - | SNOR_HWCAPS_READ_FAST - }; - - struct rtl838x_nor *rtl838x_nor = nor->priv; - - pr_debug("In %s\n", __func__); - - spi_w32_mask(0, SFCR_EnableWBO, SFCR); - spi_w32_mask(0, SFCR_EnableRBO, SFCR); - - rtl838x_nor->flags = CS0 | R_MODE; - - spi_nor_scan(nor, NULL, &hwcaps); - pr_debug("------------- Got size: %llx\n", nor->mtd.size); - - return 0; -} - -int rtl838x_nor_init(struct rtl838x_nor *rtl838x_nor, - struct device_node *flash_node) -{ - int ret; - struct spi_nor *nor; - - pr_info("%s called\n", __func__); - nor = &rtl838x_nor->nor; - nor->dev = rtl838x_nor->dev; - nor->priv = rtl838x_nor; - spi_nor_set_flash_node(nor, flash_node); - - nor->read_reg = rtl838x_nor_read_reg; - nor->write_reg = rtl838x_nor_write_reg; - nor->read = rtl838x_nor_read; - nor->write = rtl838x_nor_write; - nor->erase = rtl838x_erase; - nor->mtd.name = "rtl838x_nor"; - nor->erase_opcode = rtl838x_nor->fourByteMode ? SPINOR_OP_SE_4B - : SPINOR_OP_SE; - /* initialized with NULL */ - ret = rtl838x_spi_nor_scan(nor, NULL); - if (ret) - return ret; - - spi_enter_sio(nor); - spi_write_disable(rtl838x_nor); - - ret = mtd_device_parse_register(&nor->mtd, NULL, NULL, NULL, 0); - return ret; -} - -static int rtl838x_nor_drv_probe(struct platform_device *pdev) -{ - struct device_node *flash_np; - struct resource *res; - int ret; - struct rtl838x_nor *rtl838x_nor; - int addrMode; - - pr_info("Initializing rtl838x_nor_driver\n"); - if (!pdev->dev.of_node) { - dev_err(&pdev->dev, "No DT found\n"); - return -EINVAL; - } - - rtl838x_nor = devm_kzalloc(&pdev->dev, sizeof(*rtl838x_nor), GFP_KERNEL); - if (!rtl838x_nor) - return -ENOMEM; - platform_set_drvdata(pdev, rtl838x_nor); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rtl838x_nor->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR((void *)rtl838x_nor->base)) - return PTR_ERR((void *)rtl838x_nor->base); - - pr_info("SPI resource base is %08x\n", (u32)rtl838x_nor->base); - rtl838x_nor->dev = &pdev->dev; - - /* only support one attached flash */ - flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); - if (!flash_np) { - dev_err(&pdev->dev, "no SPI flash device to configure\n"); - ret = -ENODEV; - goto nor_free; - } - - /* Get the 3/4 byte address mode as configure by bootloader */ - if (soc_info.family == RTL8390_FAMILY_ID) - addrMode = rtl8390_get_addr_mode(rtl838x_nor); - else - addrMode = rtl838x_get_addr_mode(rtl838x_nor); - pr_info("Address mode is %d bytes\n", addrMode); - if (addrMode == 4) - rtl838x_nor->fourByteMode = true; - - ret = rtl838x_nor_init(rtl838x_nor, flash_np); - -nor_free: - return ret; -} - -static int rtl838x_nor_drv_remove(struct platform_device *pdev) -{ -/* struct rtl8xx_nor *rtl838x_nor = platform_get_drvdata(pdev); */ - return 0; -} - -static const struct of_device_id rtl838x_nor_of_ids[] = { - { .compatible = "realtek,rtl838x-nor"}, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, rtl838x_nor_of_ids); - -static struct platform_driver rtl838x_nor_driver = { - .probe = rtl838x_nor_drv_probe, - .remove = rtl838x_nor_drv_remove, - .driver = { - .name = "rtl838x-nor", - .pm = NULL, - .of_match_table = rtl838x_nor_of_ids, - }, -}; - -module_platform_driver(rtl838x_nor_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("RTL838x SPI NOR Flash Driver"); diff --git a/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h b/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h deleted file mode 100644 index de424c647a..0000000000 --- a/target/linux/realtek/files-5.10/drivers/mtd/spi-nor/rtl838x-spi.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2009 Realtek Semiconductor Corp. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _RTL838X_SPI_H -#define _RTL838X_SPI_H - - -/* - * Register access macros - */ - -#define spi_r32(reg) readl(rtl838x_nor->base + reg) -#define spi_w32(val, reg) writel(val, rtl838x_nor->base + reg) -#define spi_w32_mask(clear, set, reg) \ - spi_w32((spi_r32(reg) & ~(clear)) | (set), reg) - -#define SPI_WAIT_READY do { \ - } while (!(spi_r32(SFCSR) & SFCSR_SPI_RDY)) - -#define spi_w32w(val, reg) do { \ - writel(val, rtl838x_nor->base + reg); \ - SPI_WAIT_READY; \ - } while (0) - -#define SFCR (0x00) /*SPI Flash Configuration Register*/ - #define SFCR_CLK_DIV(val) ((val)<<29) - #define SFCR_EnableRBO (1<<28) - #define SFCR_EnableWBO (1<<27) - #define SFCR_SPI_TCS(val) ((val)<<23) /*4 bit, 1111 */ - -#define SFCR2 (0x04) /*For memory mapped I/O */ - #define SFCR2_SFCMD(val) ((val)<<24) /*8 bit, 1111_1111 */ - #define SFCR2_SIZE(val) ((val)<<21) /*3 bit, 111 */ - #define SFCR2_RDOPT (1<<20) - #define SFCR2_CMDIO(val) ((val)<<18) /*2 bit, 11 */ - #define SFCR2_ADDRIO(val) ((val)<<16) /*2 bit, 11 */ - #define SFCR2_DUMMYCYCLE(val) ((val)<<13) /*3 bit, 111 */ - #define SFCR2_DATAIO(val) ((val)<<11) /*2 bit, 11 */ - #define SFCR2_HOLD_TILL_SFDR2 (1<<10) - #define SFCR2_GETSIZE(x) (((x)&0x00E00000)>>21) - -#define SFCSR (0x08) /*SPI Flash Control&Status Register*/ - #define SFCSR_SPI_CSB0 (1<<31) - #define SFCSR_SPI_CSB1 (1<<30) - #define SFCSR_LEN(val) ((val)<<28) /*2 bits*/ - #define SFCSR_SPI_RDY (1<<27) - #define SFCSR_IO_WIDTH(val) ((val)<<25) /*2 bits*/ - #define SFCSR_CHIP_SEL (1<<24) - #define SFCSR_CMD_BYTE(val) ((val)<<16) /*8 bit, 1111_1111 */ - -#define SFDR (0x0C) /*SPI Flash Data Register*/ -#define SFDR2 (0x10) /*SPI Flash Data Register - for post SPI bootup setting*/ - #define SPI_CS_INIT (SFCSR_SPI_CSB0 | SFCSR_SPI_CSB1 | SPI_LEN1) - #define SPI_CS0 SFCSR_SPI_CSB0 - #define SPI_CS1 SFCSR_SPI_CSB1 - #define SPI_eCS0 ((SFCSR_SPI_CSB1)) /*and SFCSR to active CS0*/ - #define SPI_eCS1 ((SFCSR_SPI_CSB0)) /*and SFCSR to active CS1*/ - - #define SPI_WIP (1) /* Write In Progress */ - #define SPI_WEL (1<<1) /* Write Enable Latch*/ - #define SPI_SST_QIO_WIP (1<<7) /* SST QIO Flash Write In Progress */ - #define SPI_LEN_INIT 0xCFFFFFFF /* and SFCSR to init */ - #define SPI_LEN4 0x30000000 /* or SFCSR to set */ - #define SPI_LEN3 0x20000000 /* or SFCSR to set */ - #define SPI_LEN2 0x10000000 /* or SFCSR to set */ - #define SPI_LEN1 0x00000000 /* or SFCSR to set */ - #define SPI_SETLEN(val) do { \ - SPI_REG(SFCSR) &= 0xCFFFFFFF; \ - SPI_REG(SFCSR) |= (val-1)<<28; \ - } while (0) -/* - * SPI interface control - */ -#define RTL8390_SOC_SPI_MMIO_CONF (0x04) - -#define IOSTATUS_CIO_MASK (0x00000038) - -/* Chip select: bits 4-7*/ -#define CS0 (1<<4) -#define R_MODE 0x04 - -/* io_status */ -#define IO1 (1<<0) -#define IO2 (1<<1) -#define CIO1 (1<<3) -#define CIO2 (1<<4) -#define CMD_IO1 (1<<6) -#define W_ADDR_IO1 ((1)<<12) -#define R_ADDR_IO2 ((2)<<9) -#define R_DATA_IO2 ((2)<<15) -#define W_DATA_IO1 ((1)<<18) - -/* Commands */ -#define SPI_C_RSTQIO 0xFF - -#define SPI_MAX_TRANSFER_SIZE 256 - -#endif /* _RTL838X_SPI_H */ diff --git a/target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch b/target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch deleted file mode 100644 index 16cff75308..0000000000 --- a/target/linux/realtek/patches-5.10/400-mtd-add-rtl838x-spi-flash-driver.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/mtd/spi-nor/Kconfig -+++ b/drivers/mtd/spi-nor/Kconfig -@@ -118,4 +118,13 @@ config SPI_INTEL_SPI_PLATFORM - To compile this driver as a module, choose M here: the module - will be called intel-spi-platform. - -+config SPI_RTL838X -+ tristate "Realtek RTl838X SPI flash platform driver" -+ depends on RTL838X -+ help -+ This driver provides support for accessing SPI flash -+ in the RTL838X SoC. -+ -+ Say N here unless you know what you are doing. -+ - endif # MTD_SPI_NOR ---- a/drivers/mtd/spi-nor/Makefile -+++ b/drivers/mtd/spi-nor/Makefile -@@ -8,3 +8,4 @@ obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi - obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o - obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o - obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o -+obj-$(CONFIG_SPI_RTL838X) += rtl838x-nor.o From 0b000cbfe0aa0323bffa855ef8449c0687a4c071 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 6 May 2021 19:30:58 +0900 Subject: [PATCH 60/82] realtek: backport spi-realtek-rtl driver from 5.12 to 5.10 This patch backports "spi-realtek-rtl" driver to Kernel 5.10 from 5.12. "MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X" is used in OpenWrt, so update the dependency by the additional patch. Signed-off-by: INAGAKI Hiroshi --- ...altek-rtl838x-rtl839x-spi-controller.patch | 63 +++++ ...ltek-rtl838x-rtl839x-spi-controllers.patch | 248 ++++++++++++++++++ ...pdate-dependency-for-spi-realtek-rtl.patch | 11 + 3 files changed, 322 insertions(+) create mode 100644 target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch create mode 100644 target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch create mode 100644 target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch diff --git a/target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch b/target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch new file mode 100644 index 0000000000..035b0e655f --- /dev/null +++ b/target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch @@ -0,0 +1,63 @@ +From 6acbd614c2c8d3b8de5fb7605d6e24b9b3a8a17b Mon Sep 17 00:00:00 2001 +From: Bert Vermeulen +Date: Wed, 20 Jan 2021 14:59:27 +0100 +Subject: spi: Realtek RTL838x/RTL839x SPI controller + +Signed-off-by: Bert Vermeulen +Link: https://lore.kernel.org/r/20210120135928.246054-2-bert@biot.com +Signed-off-by: Mark Brown +--- + .../devicetree/bindings/spi/realtek,rtl-spi.yaml | 41 ++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml + +diff --git a/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml b/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml +new file mode 100644 +index 0000000000000..30a62a211984f +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml +@@ -0,0 +1,41 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/spi/realtek,rtl-spi.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Realtek RTL838x/RTL839x SPI controller ++ ++maintainers: ++ - Bert Vermeulen ++ - Birger Koblitz ++ ++allOf: ++ - $ref: "spi-controller.yaml#" ++ ++properties: ++ compatible: ++ oneOf: ++ - const: realtek,rtl8380-spi ++ - const: realtek,rtl8382-spi ++ - const: realtek,rtl8391-spi ++ - const: realtek,rtl8392-spi ++ - const: realtek,rtl8393-spi ++ ++ reg: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ spi: spi@1200 { ++ compatible = "realtek,rtl8382-spi"; ++ reg = <0x1200 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch b/target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch new file mode 100644 index 0000000000..090847baad --- /dev/null +++ b/target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch @@ -0,0 +1,248 @@ +From a8af5cc2ff1e804694629a8ef320935629dd15ba Mon Sep 17 00:00:00 2001 +From: Bert Vermeulen +Date: Wed, 20 Jan 2021 14:59:28 +0100 +Subject: spi: realtek-rtl: Add support for Realtek RTL838x/RTL839x SPI + controllers + +This driver likely also supports earlier (RTL8196) and later (RTL93xx) +SoCs. + +The SPI hardware in these SoCs is specifically intended for connecting NOR +bootflash chips, and only used for that in dozens of examined devices. +However boiled down to basics, it's really just a half-duplex SPI +controller. + +The hardware appears to have a vestigial second chip-select control, but +it hasn't been seen in the wild and is thus not supported. + +Signed-off-by: Bert Vermeulen +Link: https://lore.kernel.org/r/20210120135928.246054-3-bert@biot.com +Signed-off-by: Mark Brown +--- + drivers/spi/Makefile | 1 + + drivers/spi/spi-realtek-rtl.c | 209 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 210 insertions(+) + create mode 100644 drivers/spi/spi-realtek-rtl.c + +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -94,6 +94,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom + obj-$(CONFIG_SPI_QUP) += spi-qup.o + obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o + obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o ++obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o + obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o + obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o +--- /dev/null ++++ b/drivers/spi/spi-realtek-rtl.c +@@ -0,0 +1,209 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#include ++#include ++#include ++#include ++ ++struct rtspi { ++ void __iomem *base; ++}; ++ ++/* SPI Flash Configuration Register */ ++#define RTL_SPI_SFCR 0x00 ++#define RTL_SPI_SFCR_RBO BIT(28) ++#define RTL_SPI_SFCR_WBO BIT(27) ++ ++/* SPI Flash Control and Status Register */ ++#define RTL_SPI_SFCSR 0x08 ++#define RTL_SPI_SFCSR_CSB0 BIT(31) ++#define RTL_SPI_SFCSR_CSB1 BIT(30) ++#define RTL_SPI_SFCSR_RDY BIT(27) ++#define RTL_SPI_SFCSR_CS BIT(24) ++#define RTL_SPI_SFCSR_LEN_MASK ~(0x03 << 28) ++#define RTL_SPI_SFCSR_LEN1 (0x00 << 28) ++#define RTL_SPI_SFCSR_LEN4 (0x03 << 28) ++ ++/* SPI Flash Data Register */ ++#define RTL_SPI_SFDR 0x0c ++ ++#define REG(x) (rtspi->base + x) ++ ++ ++static void rt_set_cs(struct spi_device *spi, bool active) ++{ ++ struct rtspi *rtspi = spi_controller_get_devdata(spi->controller); ++ u32 value; ++ ++ /* CS0 bit is active low */ ++ value = readl(REG(RTL_SPI_SFCSR)); ++ if (active) ++ value |= RTL_SPI_SFCSR_CSB0; ++ else ++ value &= ~RTL_SPI_SFCSR_CSB0; ++ writel(value, REG(RTL_SPI_SFCSR)); ++} ++ ++static void set_size(struct rtspi *rtspi, int size) ++{ ++ u32 value; ++ ++ value = readl(REG(RTL_SPI_SFCSR)); ++ value &= RTL_SPI_SFCSR_LEN_MASK; ++ if (size == 4) ++ value |= RTL_SPI_SFCSR_LEN4; ++ else if (size == 1) ++ value |= RTL_SPI_SFCSR_LEN1; ++ writel(value, REG(RTL_SPI_SFCSR)); ++} ++ ++static inline void wait_ready(struct rtspi *rtspi) ++{ ++ while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY)) ++ cpu_relax(); ++} ++static void send4(struct rtspi *rtspi, const u32 *buf) ++{ ++ wait_ready(rtspi); ++ set_size(rtspi, 4); ++ writel(*buf, REG(RTL_SPI_SFDR)); ++} ++ ++static void send1(struct rtspi *rtspi, const u8 *buf) ++{ ++ wait_ready(rtspi); ++ set_size(rtspi, 1); ++ writel(buf[0] << 24, REG(RTL_SPI_SFDR)); ++} ++ ++static void rcv4(struct rtspi *rtspi, u32 *buf) ++{ ++ wait_ready(rtspi); ++ set_size(rtspi, 4); ++ *buf = readl(REG(RTL_SPI_SFDR)); ++} ++ ++static void rcv1(struct rtspi *rtspi, u8 *buf) ++{ ++ wait_ready(rtspi); ++ set_size(rtspi, 1); ++ *buf = readl(REG(RTL_SPI_SFDR)) >> 24; ++} ++ ++static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi, ++ struct spi_transfer *xfer) ++{ ++ struct rtspi *rtspi = spi_controller_get_devdata(ctrl); ++ void *rx_buf; ++ const void *tx_buf; ++ int cnt; ++ ++ tx_buf = xfer->tx_buf; ++ rx_buf = xfer->rx_buf; ++ cnt = xfer->len; ++ if (tx_buf) { ++ while (cnt >= 4) { ++ send4(rtspi, tx_buf); ++ tx_buf += 4; ++ cnt -= 4; ++ } ++ while (cnt) { ++ send1(rtspi, tx_buf); ++ tx_buf++; ++ cnt--; ++ } ++ } else if (rx_buf) { ++ while (cnt >= 4) { ++ rcv4(rtspi, rx_buf); ++ rx_buf += 4; ++ cnt -= 4; ++ } ++ while (cnt) { ++ rcv1(rtspi, rx_buf); ++ rx_buf++; ++ cnt--; ++ } ++ } ++ ++ spi_finalize_current_transfer(ctrl); ++ ++ return 0; ++} ++ ++static void init_hw(struct rtspi *rtspi) ++{ ++ u32 value; ++ ++ /* Turn on big-endian byte ordering */ ++ value = readl(REG(RTL_SPI_SFCR)); ++ value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO; ++ writel(value, REG(RTL_SPI_SFCR)); ++ ++ value = readl(REG(RTL_SPI_SFCSR)); ++ /* Permanently disable CS1, since it's never used */ ++ value |= RTL_SPI_SFCSR_CSB1; ++ /* Select CS0 for use */ ++ value &= RTL_SPI_SFCSR_CS; ++ writel(value, REG(RTL_SPI_SFCSR)); ++} ++ ++static int realtek_rtl_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_controller *ctrl; ++ struct rtspi *rtspi; ++ int err; ++ ++ ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi)); ++ if (!ctrl) { ++ dev_err(&pdev->dev, "Error allocating SPI controller\n"); ++ return -ENOMEM; ++ } ++ platform_set_drvdata(pdev, ctrl); ++ rtspi = spi_controller_get_devdata(ctrl); ++ ++ rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); ++ if (IS_ERR(rtspi->base)) { ++ dev_err(&pdev->dev, "Could not map SPI register address"); ++ return -ENOMEM; ++ } ++ ++ init_hw(rtspi); ++ ++ ctrl->dev.of_node = pdev->dev.of_node; ++ ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX; ++ ctrl->set_cs = rt_set_cs; ++ ctrl->transfer_one = transfer_one; ++ ++ err = devm_spi_register_controller(&pdev->dev, ctrl); ++ if (err) { ++ dev_err(&pdev->dev, "Could not register SPI controller\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++ ++static const struct of_device_id realtek_rtl_spi_of_ids[] = { ++ { .compatible = "realtek,rtl8380-spi" }, ++ { .compatible = "realtek,rtl8382-spi" }, ++ { .compatible = "realtek,rtl8391-spi" }, ++ { .compatible = "realtek,rtl8392-spi" }, ++ { .compatible = "realtek,rtl8393-spi" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids); ++ ++static struct platform_driver realtek_rtl_spi_driver = { ++ .probe = realtek_rtl_spi_probe, ++ .driver = { ++ .name = "realtek-rtl-spi", ++ .of_match_table = realtek_rtl_spi_of_ids, ++ }, ++}; ++ ++module_platform_driver(realtek_rtl_spi_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Bert Vermeulen "); ++MODULE_DESCRIPTION("Realtek RTL SPI driver"); diff --git a/target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch b/target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch new file mode 100644 index 0000000000..6975bfd228 --- /dev/null +++ b/target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch @@ -0,0 +1,11 @@ +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -94,7 +94,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom + obj-$(CONFIG_SPI_QUP) += spi-qup.o + obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o + obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o +-obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o ++obj-$(CONFIG_RTL838X) += spi-realtek-rtl.o + obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o + obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o From fbd675c668e1e6be4e5a8a8107902282e668a3a0 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 24 Jun 2021 20:32:31 +0900 Subject: [PATCH 61/82] realtek: drop rtl838x gpio driver from 5.10 To backport the upstreamed driver (gpio-realtek-otto) from 5.13, drop the old driver from realtek target. And, modify 301-gpio-add-rtl838x-driver.patch to remove rtl838x GPIO support and rename it only for rtl8231 GPIO support. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/config-5.10 | 1 - .../files-5.10/drivers/gpio/gpio-rtl838x.c | 425 ------------------ ...atch => 301-gpio-add-rtl8231-driver.patch} | 13 +- 3 files changed, 3 insertions(+), 436 deletions(-) delete mode 100644 target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c rename target/linux/realtek/patches-5.10/{301-gpio-add-rtl838x-driver.patch => 301-gpio-add-rtl8231-driver.patch} (74%) diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 index 3c953f3f56..b9ed86b426 100644 --- a/target/linux/realtek/config-5.10 +++ b/target/linux/realtek/config-5.10 @@ -73,7 +73,6 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y CONFIG_GPIO_RTL8231=y -CONFIG_GPIO_RTL838X=y CONFIG_REALTEK_SOC_PHY=y CONFIG_GRO_CELLS=y CONFIG_HANDLE_DOMAIN_IRQ=y diff --git a/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c deleted file mode 100644 index 8207e4bb73..0000000000 --- a/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c +++ /dev/null @@ -1,425 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include -#include -#include -#include -#include - -/* RTL8231 registers for LED control */ -#define RTL8231_LED_FUNC0 0x0000 -#define RTL8231_GPIO_PIN_SEL(gpio) ((0x0002) + ((gpio) >> 4)) -#define RTL8231_GPIO_DIR(gpio) ((0x0005) + ((gpio) >> 4)) -#define RTL8231_GPIO_DATA(gpio) ((0x001C) + ((gpio) >> 4)) - -struct rtl838x_gpios { - struct gpio_chip gc; - u32 id; - struct device *dev; - int irq; - int num_leds; - int min_led; - int leds_per_port; - u32 led_mode; - int led_glb_ctrl; - int led_sw_ctrl; - int (*led_sw_p_ctrl)(int port); - int (*led_sw_p_en_ctrl)(int port); - int (*ext_gpio_dir)(int i); - int (*ext_gpio_data)(int i); -}; - -inline int rtl838x_ext_gpio_dir(int i) -{ - return RTL838X_EXT_GPIO_DIR + ((i >>5) << 2); -} - -inline int rtl839x_ext_gpio_dir(int i) -{ - return RTL839X_EXT_GPIO_DIR + ((i >>5) << 2); -} - -inline int rtl838x_ext_gpio_data(int i) -{ - return RTL838X_EXT_GPIO_DATA + ((i >>5) << 2); -} - -inline int rtl839x_ext_gpio_data(int i) -{ - return RTL839X_EXT_GPIO_DATA + ((i >>5) << 2); -} - -inline int rtl838x_led_sw_p_ctrl(int p) -{ - return RTL838X_LED_SW_P_CTRL + (p << 2); -} - -inline int rtl839x_led_sw_p_ctrl(int p) -{ - return RTL839X_LED_SW_P_CTRL + (p << 2); -} - -inline int rtl838x_led_sw_p_en_ctrl(int p) -{ - return RTL838X_LED_SW_P_EN_CTRL + ((p / 10) << 2); -} - -inline int rtl839x_led_sw_p_en_ctrl(int p) -{ - return RTL839X_LED_SW_P_EN_CTRL + ((p / 10) << 2); -} - -extern struct mutex smi_lock; -extern struct rtl83xx_soc_info soc_info; - - -void rtl838x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) -{ - int bit; - struct rtl838x_gpios *gpios = gpiochip_get_data(gc); - - pr_debug("rtl838x_set: %d, value: %d\n", offset, value); - /* Internal GPIO of the RTL8380 */ - if (offset < 32) { - if (value) - rtl83xx_w32_mask(0, BIT(offset), RTL838X_GPIO_PABC_DATA); - else - rtl83xx_w32_mask(BIT(offset), 0, RTL838X_GPIO_PABC_DATA); - } - - /* LED driver for PWR and SYS */ - if (offset >= 32 && offset < 64) { - bit = offset - 32; - if (value) - sw_w32_mask(0, BIT(bit), gpios->led_glb_ctrl); - else - sw_w32_mask(BIT(bit), 0, gpios->led_glb_ctrl); - return; - } - - bit = (offset - 64) % 32; - /* First Port-LED */ - if (offset >= 64 && offset < 96 - && offset >= (64 + gpios->min_led) - && offset < (64 + gpios->min_led + gpios->num_leds)) { - if (value) - sw_w32_mask(7, 5, gpios->led_sw_p_ctrl(bit)); - else - sw_w32_mask(7, 0, gpios->led_sw_p_ctrl(bit)); - } - if (offset >= 96 && offset < 128 - && offset >= (96 + gpios->min_led) - && offset < (96 + gpios->min_led + gpios->num_leds)) { - if (value) - sw_w32_mask(7 << 3, 5 << 3, gpios->led_sw_p_ctrl(bit)); - else - sw_w32_mask(7 << 3, 0, gpios->led_sw_p_ctrl(bit)); - } - if (offset >= 128 && offset < 160 - && offset >= (128 + gpios->min_led) - && offset < (128 + gpios->min_led + gpios->num_leds)) { - if (value) - sw_w32_mask(7 << 6, 5 << 6, gpios->led_sw_p_ctrl(bit)); - else - sw_w32_mask(7 << 6, 0, gpios->led_sw_p_ctrl(bit)); - } - __asm__ volatile ("sync"); -} - -static int rtl838x_direction_input(struct gpio_chip *gc, unsigned int offset) -{ - pr_debug("%s: %d\n", __func__, offset); - - if (offset < 32) { - rtl83xx_w32_mask(BIT(offset), 0, RTL838X_GPIO_PABC_DIR); - return 0; - } - - /* Internal LED driver does not support input */ - return -ENOTSUPP; -} - -static int rtl838x_direction_output(struct gpio_chip *gc, unsigned int offset, int value) -{ - pr_debug("%s: %d\n", __func__, offset); - if (offset < 32) - rtl83xx_w32_mask(0, BIT(offset), RTL838X_GPIO_PABC_DIR); - rtl838x_gpio_set(gc, offset, value); - - /* LED for PWR and SYS driver is direction output by default */ - return 0; -} - -static int rtl838x_get_direction(struct gpio_chip *gc, unsigned int offset) -{ - u32 v = 0; - - pr_debug("%s: %d\n", __func__, offset); - if (offset < 32) { - v = rtl83xx_r32(RTL838X_GPIO_PABC_DIR); - if (v & BIT(offset)) - return 0; - return 1; - } - - /* LED driver for PWR and SYS is direction output by default */ - if (offset >= 32 && offset < 64) - return 0; - - return 0; -} - -static int rtl838x_gpio_get(struct gpio_chip *gc, unsigned int offset) -{ - u32 v; - struct rtl838x_gpios *gpios = gpiochip_get_data(gc); - - pr_debug("%s: %d\n", __func__, offset); - - /* Internal GPIO of the RTL8380 */ - if (offset < 32) { - v = rtl83xx_r32(RTL838X_GPIO_PABC_DATA); - if (v & BIT(offset)) - return 1; - return 0; - } - - /* LED driver for PWR and SYS */ - if (offset >= 32 && offset < 64) { - v = sw_r32(gpios->led_glb_ctrl); - if (v & BIT(offset-32)) - return 1; - return 0; - } - -/* BUG: - bit = (offset - 64) % 32; - if (offset >= 64 && offset < 96) { - if (sw_r32(RTL838X_LED1_SW_P_EN_CTRL) & BIT(bit)) - return 1; - return 0; - } - if (offset >= 96 && offset < 128) { - if (sw_r32(RTL838X_LED1_SW_P_EN_CTRL) & BIT(bit)) - return 1; - return 0; - } - if (offset >= 128 && offset < 160) { - if (sw_r32(RTL838X_LED1_SW_P_EN_CTRL) & BIT(bit)) - return 1; - return 0; - } - */ - return 0; -} - -void rtl8380_led_test(struct rtl838x_gpios *gpios, u32 mask) -{ - int i; - u32 led_gbl = sw_r32(gpios->led_glb_ctrl); - u32 mode_sel, led_p_en; - - if (soc_info.family == RTL8380_FAMILY_ID) { - mode_sel = sw_r32(RTL838X_LED_MODE_SEL); - led_p_en = sw_r32(RTL838X_LED_P_EN_CTRL); - } - - /* 2 Leds for ports 0-23 and 24-27, 3 would be 0x7 */ - sw_w32_mask(0x3f, 0x3 | (0x3 << 3), gpios->led_glb_ctrl); - - if(soc_info.family == RTL8380_FAMILY_ID) { - /* Enable all leds */ - sw_w32(0xFFFFFFF, RTL838X_LED_P_EN_CTRL); - } - /* Enable software control of all leds */ - sw_w32(0xFFFFFFF, gpios->led_sw_ctrl); - sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(0)); - sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(10)); - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); - - for (i = 0; i < 28; i++) { - if (mask & BIT(i)) - sw_w32(5 | (5 << 3) | (5 << 6), gpios->led_sw_p_ctrl(i)); - } - msleep(3000); - - if (soc_info.family == RTL8380_FAMILY_ID) - sw_w32(led_p_en, RTL838X_LED_P_EN_CTRL); - /* Disable software control of all leds */ - sw_w32(0x0000000, gpios->led_sw_ctrl); - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(0)); - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(10)); - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); - - sw_w32(led_gbl, gpios->led_glb_ctrl); - if (soc_info.family == RTL8380_FAMILY_ID) - sw_w32(mode_sel, RTL838X_LED_MODE_SEL); -} - -void take_port_leds(struct rtl838x_gpios *gpios) -{ - int leds_per_port = gpios->leds_per_port; - int mode = gpios->led_mode; - - pr_info("%s, %d, %x\n", __func__, leds_per_port, mode); - pr_debug("Bootloader settings: %x %x %x\n", - sw_r32(gpios->led_sw_p_en_ctrl(0)), - sw_r32(gpios->led_sw_p_en_ctrl(10)), - sw_r32(gpios->led_sw_p_en_ctrl(20)) - ); - - if (soc_info.family == RTL8380_FAMILY_ID) { - pr_debug("led glb: %x, sel %x\n", - sw_r32(gpios->led_glb_ctrl), sw_r32(RTL838X_LED_MODE_SEL)); - pr_debug("RTL838X_LED_P_EN_CTRL: %x", sw_r32(RTL838X_LED_P_EN_CTRL)); - pr_debug("RTL838X_LED_MODE_CTRL: %x", sw_r32(RTL838X_LED_MODE_CTRL)); - sw_w32_mask(3, 0, RTL838X_LED_MODE_SEL); - sw_w32(mode, RTL838X_LED_MODE_CTRL); - } - - /* Enable software control of all leds */ - sw_w32(0xFFFFFFF, gpios->led_sw_ctrl); - if (soc_info.family == RTL8380_FAMILY_ID) - sw_w32(0xFFFFFFF, RTL838X_LED_P_EN_CTRL); - - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(0)); - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(10)); - sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); - - sw_w32_mask(0x3f, 0, gpios->led_glb_ctrl); - switch (leds_per_port) { - case 3: - sw_w32_mask(0, 0x7 | (0x7 << 3), gpios->led_glb_ctrl); - sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(20)); - /* FALLTHRU */ - case 2: - sw_w32_mask(0, 0x3 | (0x3 << 3), gpios->led_glb_ctrl); - sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(10)); - /* FALLTHRU */ - case 1: - sw_w32_mask(0, 0x1 | (0x1 << 3), gpios->led_glb_ctrl); - sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(0)); - break; - default: - pr_err("No LEDS configured for software control\n"); - } -} - -static const struct of_device_id rtl838x_gpio_of_match[] = { - { .compatible = "realtek,rtl838x-gpio" }, - {}, -}; - -MODULE_DEVICE_TABLE(of, rtl838x_gpio_of_match); - -static int rtl838x_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct rtl838x_gpios *gpios; - int err; - - pr_info("Probing RTL838X GPIOs\n"); - - if (!np) { - dev_err(&pdev->dev, "No DT found\n"); - return -EINVAL; - } - - gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); - if (!gpios) - return -ENOMEM; - - gpios->id = soc_info.id; - - switch (gpios->id) { - case 0x8332: - pr_debug("Found RTL8332M GPIO\n"); - break; - case 0x8380: - pr_debug("Found RTL8380M GPIO\n"); - break; - case 0x8381: - pr_debug("Found RTL8381M GPIO\n"); - break; - case 0x8382: - pr_debug("Found RTL8382M GPIO\n"); - break; - case 0x8391: - pr_debug("Found RTL8391 GPIO\n"); - break; - case 0x8393: - pr_debug("Found RTL8393 GPIO\n"); - break; - default: - pr_err("Unknown GPIO chip id (%04x)\n", gpios->id); - return -ENODEV; - } - - if (soc_info.family == RTL8380_FAMILY_ID) { - gpios->led_glb_ctrl = RTL838X_LED_GLB_CTRL; - gpios->led_sw_ctrl = RTL838X_LED_SW_CTRL; - gpios->led_sw_p_ctrl = rtl838x_led_sw_p_ctrl; - gpios->led_sw_p_en_ctrl = rtl838x_led_sw_p_en_ctrl; - gpios->ext_gpio_dir = rtl838x_ext_gpio_dir; - gpios->ext_gpio_data = rtl838x_ext_gpio_data; - } - - if (soc_info.family == RTL8390_FAMILY_ID) { - gpios->led_glb_ctrl = RTL839X_LED_GLB_CTRL; - gpios->led_sw_ctrl = RTL839X_LED_SW_CTRL; - gpios->led_sw_p_ctrl = rtl839x_led_sw_p_ctrl; - gpios->led_sw_p_en_ctrl = rtl839x_led_sw_p_en_ctrl; - gpios->ext_gpio_dir = rtl839x_ext_gpio_dir; - gpios->ext_gpio_data = rtl839x_ext_gpio_data; - } - - gpios->dev = dev; - gpios->gc.base = 0; - /* 0-31: internal - * 32-63, LED control register - * 64-95: PORT-LED 0 - * 96-127: PORT-LED 1 - * 128-159: PORT-LED 2 - */ - gpios->gc.ngpio = 160; - gpios->gc.label = "rtl838x"; - gpios->gc.parent = dev; - gpios->gc.owner = THIS_MODULE; - gpios->gc.can_sleep = true; - gpios->irq = 31; - - gpios->gc.direction_input = rtl838x_direction_input; - gpios->gc.direction_output = rtl838x_direction_output; - gpios->gc.set = rtl838x_gpio_set; - gpios->gc.get = rtl838x_gpio_get; - gpios->gc.get_direction = rtl838x_get_direction; - - if (of_property_read_bool(np, "take-port-leds")) { - if (of_property_read_u32(np, "leds-per-port", &gpios->leds_per_port)) - gpios->leds_per_port = 2; - if (of_property_read_u32(np, "led-mode", &gpios->led_mode)) - gpios->led_mode = (0x1ea << 15) | 0x1ea; - if (of_property_read_u32(np, "num-leds", &gpios->num_leds)) - gpios->num_leds = 32; - if (of_property_read_u32(np, "min-led", &gpios->min_led)) - gpios->min_led = 0; - take_port_leds(gpios); - } - - err = devm_gpiochip_add_data(dev, &gpios->gc, gpios); - return err; -} - -static struct platform_driver rtl838x_gpio_driver = { - .driver = { - .name = "rtl838x-gpio", - .of_match_table = rtl838x_gpio_of_match, - }, - .probe = rtl838x_gpio_probe, -}; - -module_platform_driver(rtl838x_gpio_driver); - -MODULE_DESCRIPTION("Realtek RTL838X GPIO API support"); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch b/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch similarity index 74% rename from target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch rename to target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch index 4f5901d87f..8a3d4810a6 100644 --- a/target/linux/realtek/patches-5.10/301-gpio-add-rtl838x-driver.patch +++ b/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch @@ -1,32 +1,25 @@ --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -441,6 +441,18 @@ config GPIO_REG +@@ -441,6 +441,12 @@ config GPIO_REG A 32-bit single register GPIO fixed in/out implementation. This can be used to represent any register as a set of GPIO signals. +config GPIO_RTL8231 + tristate "RTL8231 GPIO" -+ depends on GPIO_RTL838X -+ help -+ Say yes here to support Realtek RTL8231 GPIO expansion chips. -+ -+config GPIO_RTL838X -+ tristate "RTL838X GPIO" + depends on RTL838X + help -+ Say yes here to support RTL838X GPIO devices. ++ Say yes here to support Realtek RTL8231 GPIO expansion chips. + config GPIO_SAMA5D2_PIOBU tristate "SAMA5D2 PIOBU GPIO support" depends on MFD_SYSCON --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -117,6 +117,8 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t +@@ -117,6 +117,7 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_REG) += gpio-reg.o +obj-$(CONFIG_GPIO_RTL8231) += gpio-rtl8231.o -+obj-$(CONFIG_GPIO_RTL838X) += gpio-rtl838x.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o From 9bac1c20b8f39f2e0e342b087add5093b94feaed Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 22:05:39 +0900 Subject: [PATCH 62/82] realtek: backport gpio-realtek-otto driver from 5.13 to 5.10 This patch backports "gpio-realtek-otto" driver to Kernel 5.10. "MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X" is used in OpenWrt, so update the dependency by the additional patch. Note: GPIO mapping is changed in the upstreamed driver. old - new 24 - 0 25 - 1 26 - 2 27 - 3 28 - 4 29 - 5 30 - 6 31 - 7 16 - 8 17 - 9 18 - 10 19 - 11 20 - 12 21 - 13 22 - 14 23 - 15 8 - 16 9 - 17 10 - 18 11 - 19 12 - 20 13 - 21 14 - 22 15 - 23 Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/config-5.10 | 3 + ...s-gpio-binding-for-realtek-otto-gpio.patch | 109 +++++ ...3-gpio-add-realtek-otto-gpio-support.patch | 394 ++++++++++++++++++ ...e-dependencies-for-gpio-realtek-otto.patch | 13 + 4 files changed, 519 insertions(+) create mode 100644 target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch create mode 100644 target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch create mode 100644 target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 index b9ed86b426..8baecf42f3 100644 --- a/target/linux/realtek/config-5.10 +++ b/target/linux/realtek/config-5.10 @@ -72,6 +72,9 @@ CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_REALTEK_OTTO=y CONFIG_GPIO_RTL8231=y CONFIG_REALTEK_SOC_PHY=y CONFIG_GRO_CELLS=y diff --git a/target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch b/target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch new file mode 100644 index 0000000000..111591c640 --- /dev/null +++ b/target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch @@ -0,0 +1,109 @@ +From a362c0ce64866939c3daa17c76943cfed555b065 Mon Sep 17 00:00:00 2001 +From: Sander Vanheule +Date: Tue, 30 Mar 2021 19:48:42 +0200 +Subject: dt-bindings: gpio: Binding for Realtek Otto GPIO + +Add a binding description for Realtek's GPIO controller found on several +of their MIPS-based SoCs (codenamed Otto), such as the RTL838x and +RTL839x series of switch SoCs. + +A fallback binding 'realtek,otto-gpio' is provided for cases where the +actual port ordering is not known yet, and enabling the interrupt +controller may result in uncaught interrupts. + +Signed-off-by: Sander Vanheule +Reviewed-by: Linus Walleij +Reviewed-by: Rob Herring +Signed-off-by: Bartosz Golaszewski +--- + .../bindings/gpio/realtek,otto-gpio.yaml | 78 ++++++++++++++++++++++ + 1 file changed, 78 insertions(+) + create mode 100644 Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml + +diff --git a/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml +new file mode 100644 +index 0000000000000..100f20cebd76a +--- /dev/null ++++ b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml +@@ -0,0 +1,78 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/gpio/realtek,otto-gpio.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Realtek Otto GPIO controller ++ ++maintainers: ++ - Sander Vanheule ++ - Bert Vermeulen ++ ++description: | ++ Realtek's GPIO controller on their MIPS switch SoCs (Otto platform) consists ++ of two banks of 32 GPIOs. These GPIOs can generate edge-triggered interrupts. ++ Each bank's interrupts are cascased into one interrupt line on the parent ++ interrupt controller, if provided. ++ This binding allows defining a single bank in the devicetree. The interrupt ++ controller is not supported on the fallback compatible name, which only ++ allows for GPIO port use. ++ ++properties: ++ $nodename: ++ pattern: "^gpio@[0-9a-f]+$" ++ ++ compatible: ++ items: ++ - enum: ++ - realtek,rtl8380-gpio ++ - realtek,rtl8390-gpio ++ - const: realtek,otto-gpio ++ ++ reg: ++ maxItems: 1 ++ ++ "#gpio-cells": ++ const: 2 ++ ++ gpio-controller: true ++ ++ ngpios: ++ minimum: 1 ++ maximum: 32 ++ ++ interrupt-controller: true ++ ++ "#interrupt-cells": ++ const: 2 ++ ++ interrupts: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - "#gpio-cells" ++ - gpio-controller ++ ++additionalProperties: false ++ ++dependencies: ++ interrupt-controller: [ interrupts ] ++ ++examples: ++ - | ++ gpio@3500 { ++ compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; ++ reg = <0x3500 0x1c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ngpios = <24>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&rtlintc>; ++ interrupts = <23>; ++ }; ++ ++... +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch b/target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch new file mode 100644 index 0000000000..fc13824282 --- /dev/null +++ b/target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch @@ -0,0 +1,394 @@ +From f0f7d662e8514169c90d3d84cd6df773b2983088 Mon Sep 17 00:00:00 2001 +From: Sander Vanheule +Date: Tue, 30 Mar 2021 19:48:43 +0200 +Subject: gpio: Add Realtek Otto GPIO support + +Realtek MIPS SoCs (platform name Otto) have GPIO controllers with up to +64 GPIOs, divided over two banks. Each bank has a set of registers for +32 GPIOs, with support for edge-triggered interrupts. + +Each GPIO bank consists of four 8-bit GPIO ports (ABCD and EFGH). Most +registers pack one bit per GPIO, except for the IMR register, which +packs two bits per GPIO (AB-CD). + +Although the byte order is currently assumed to have port A..D at offset +0x0..0x3, this has been observed to be reversed on other, Lexra-based, +SoCs (e.g. RTL8196E/97D/97F). + +Interrupt support is disabled for the fallback devicetree-compatible +'realtek,otto-gpio'. This allows for quick support of GPIO banks in +which the byte order would be unknown. In this case, the port ordering +in the IMR registers may not match the reversed order in the other +registers (DCBA, and BA-DC or DC-BA). + +Signed-off-by: Sander Vanheule +Reviewed-by: Linus Walleij +Reviewed-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/Kconfig | 13 ++ + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-realtek-otto.c | 325 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 339 insertions(+) + create mode 100644 drivers/gpio/gpio-realtek-otto.c + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -489,6 +489,19 @@ config GPIO_RDA + help + Say Y here to support RDA Micro GPIO controller. + ++config GPIO_REALTEK_OTTO ++ tristate "Realtek Otto GPIO support" ++ depends on MACH_REALTEK_RTL ++ default MACH_REALTEK_RTL ++ select GPIO_GENERIC ++ select GPIOLIB_IRQCHIP ++ help ++ The GPIO controller on the Otto MIPS platform supports up to two ++ banks of 32 GPIOs, with edge triggered interrupts. The 32 GPIOs ++ are grouped in four 8-bit wide ports. ++ ++ When built as a module, the module will be called realtek_otto_gpio. ++ + config GPIO_REG + bool + help +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -124,6 +124,7 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o + obj-$(CONFIG_GPIO_RDA) += gpio-rda.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o ++obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o + obj-$(CONFIG_GPIO_REG) += gpio-reg.o + obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o + obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o +--- /dev/null ++++ b/drivers/gpio/gpio-realtek-otto.c +@@ -0,0 +1,325 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Total register block size is 0x1C for one bank of four ports (A, B, C, D). ++ * An optional second bank, with ports E, F, G, and H, may be present, starting ++ * at register offset 0x1C. ++ */ ++ ++/* ++ * Pin select: (0) "normal", (1) "dedicate peripheral" ++ * Not used on RTL8380/RTL8390, peripheral selection is managed by control bits ++ * in the peripheral registers. ++ */ ++#define REALTEK_GPIO_REG_CNR 0x00 ++/* Clear bit (0) for input, set bit (1) for output */ ++#define REALTEK_GPIO_REG_DIR 0x08 ++#define REALTEK_GPIO_REG_DATA 0x0C ++/* Read bit for IRQ status, write 1 to clear IRQ */ ++#define REALTEK_GPIO_REG_ISR 0x10 ++/* Two bits per GPIO in IMR registers */ ++#define REALTEK_GPIO_REG_IMR 0x14 ++#define REALTEK_GPIO_REG_IMR_AB 0x14 ++#define REALTEK_GPIO_REG_IMR_CD 0x18 ++#define REALTEK_GPIO_IMR_LINE_MASK GENMASK(1, 0) ++#define REALTEK_GPIO_IRQ_EDGE_FALLING 1 ++#define REALTEK_GPIO_IRQ_EDGE_RISING 2 ++#define REALTEK_GPIO_IRQ_EDGE_BOTH 3 ++ ++#define REALTEK_GPIO_MAX 32 ++#define REALTEK_GPIO_PORTS_PER_BANK 4 ++ ++/** ++ * realtek_gpio_ctrl - Realtek Otto GPIO driver data ++ * ++ * @gc: Associated gpio_chip instance ++ * @base: Base address of the register block for a GPIO bank ++ * @lock: Lock for accessing the IRQ registers and values ++ * @intr_mask: Mask for interrupts lines ++ * @intr_type: Interrupt type selection ++ * ++ * Because the interrupt mask register (IMR) combines the function of IRQ type ++ * selection and masking, two extra values are stored. @intr_mask is used to ++ * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store ++ * the selected interrupt types. The logical AND of these values is written to ++ * IMR on changes. ++ */ ++struct realtek_gpio_ctrl { ++ struct gpio_chip gc; ++ void __iomem *base; ++ raw_spinlock_t lock; ++ u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK]; ++ u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK]; ++}; ++ ++/* Expand with more flags as devices with other quirks are added */ ++enum realtek_gpio_flags { ++ /* ++ * Allow disabling interrupts, for cases where the port order is ++ * unknown. This may result in a port mismatch between ISR and IMR. ++ * An interrupt would appear to come from a different line than the ++ * line the IRQ handler was assigned to, causing uncaught interrupts. ++ */ ++ GPIO_INTERRUPTS_DISABLED = BIT(0), ++}; ++ ++static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(data); ++ ++ return container_of(gc, struct realtek_gpio_ctrl, gc); ++} ++ ++/* ++ * Normal port order register access ++ * ++ * Port information is stored with the first port at offset 0, followed by the ++ * second, etc. Most registers store one bit per GPIO and use a u8 value per ++ * port. The two interrupt mask registers store two bits per GPIO, so use u16 ++ * values. ++ */ ++static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl, ++ unsigned int port, u16 irq_type, u16 irq_mask) ++{ ++ iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port); ++} ++ ++static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl, ++ unsigned int port, u8 mask) ++{ ++ iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port); ++} ++ ++static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port) ++{ ++ return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port); ++} ++ ++/* Set the rising and falling edge mask bits for a GPIO port pin */ ++static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value) ++{ ++ return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin; ++} ++ ++static void realtek_gpio_irq_ack(struct irq_data *data) ++{ ++ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data); ++ irq_hw_number_t line = irqd_to_hwirq(data); ++ unsigned int port = line / 8; ++ unsigned int port_pin = line % 8; ++ ++ realtek_gpio_clear_isr(ctrl, port, BIT(port_pin)); ++} ++ ++static void realtek_gpio_irq_unmask(struct irq_data *data) ++{ ++ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data); ++ unsigned int line = irqd_to_hwirq(data); ++ unsigned int port = line / 8; ++ unsigned int port_pin = line % 8; ++ unsigned long flags; ++ u16 m; ++ ++ raw_spin_lock_irqsave(&ctrl->lock, flags); ++ m = ctrl->intr_mask[port]; ++ m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK); ++ ctrl->intr_mask[port] = m; ++ realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m); ++ raw_spin_unlock_irqrestore(&ctrl->lock, flags); ++} ++ ++static void realtek_gpio_irq_mask(struct irq_data *data) ++{ ++ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data); ++ unsigned int line = irqd_to_hwirq(data); ++ unsigned int port = line / 8; ++ unsigned int port_pin = line % 8; ++ unsigned long flags; ++ u16 m; ++ ++ raw_spin_lock_irqsave(&ctrl->lock, flags); ++ m = ctrl->intr_mask[port]; ++ m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK); ++ ctrl->intr_mask[port] = m; ++ realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m); ++ raw_spin_unlock_irqrestore(&ctrl->lock, flags); ++} ++ ++static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) ++{ ++ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data); ++ unsigned int line = irqd_to_hwirq(data); ++ unsigned int port = line / 8; ++ unsigned int port_pin = line % 8; ++ unsigned long flags; ++ u16 type, t; ++ ++ switch (flow_type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_FALLING: ++ type = REALTEK_GPIO_IRQ_EDGE_FALLING; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ type = REALTEK_GPIO_IRQ_EDGE_RISING; ++ break; ++ case IRQ_TYPE_EDGE_BOTH: ++ type = REALTEK_GPIO_IRQ_EDGE_BOTH; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ irq_set_handler_locked(data, handle_edge_irq); ++ ++ raw_spin_lock_irqsave(&ctrl->lock, flags); ++ t = ctrl->intr_type[port]; ++ t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK); ++ t |= realtek_gpio_imr_bits(port_pin, type); ++ ctrl->intr_type[port] = t; ++ realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]); ++ raw_spin_unlock_irqrestore(&ctrl->lock, flags); ++ ++ return 0; ++} ++ ++static void realtek_gpio_irq_handler(struct irq_desc *desc) ++{ ++ struct gpio_chip *gc = irq_desc_get_handler_data(desc); ++ struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc); ++ struct irq_chip *irq_chip = irq_desc_get_chip(desc); ++ unsigned int lines_done; ++ unsigned int port_pin_count; ++ unsigned int irq; ++ unsigned long status; ++ int offset; ++ ++ chained_irq_enter(irq_chip, desc); ++ ++ for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) { ++ status = realtek_gpio_read_isr(ctrl, lines_done / 8); ++ port_pin_count = min(gc->ngpio - lines_done, 8U); ++ for_each_set_bit(offset, &status, port_pin_count) { ++ irq = irq_find_mapping(gc->irq.domain, offset); ++ generic_handle_irq(irq); ++ } ++ } ++ ++ chained_irq_exit(irq_chip, desc); ++} ++ ++static int realtek_gpio_irq_init(struct gpio_chip *gc) ++{ ++ struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc); ++ unsigned int port; ++ ++ for (port = 0; (port * 8) < gc->ngpio; port++) { ++ realtek_gpio_write_imr(ctrl, port, 0, 0); ++ realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0)); ++ } ++ ++ return 0; ++} ++ ++static struct irq_chip realtek_gpio_irq_chip = { ++ .name = "realtek-otto-gpio", ++ .irq_ack = realtek_gpio_irq_ack, ++ .irq_mask = realtek_gpio_irq_mask, ++ .irq_unmask = realtek_gpio_irq_unmask, ++ .irq_set_type = realtek_gpio_irq_set_type, ++}; ++ ++static const struct of_device_id realtek_gpio_of_match[] = { ++ { ++ .compatible = "realtek,otto-gpio", ++ .data = (void *)GPIO_INTERRUPTS_DISABLED, ++ }, ++ { ++ .compatible = "realtek,rtl8380-gpio", ++ }, ++ { ++ .compatible = "realtek,rtl8390-gpio", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, realtek_gpio_of_match); ++ ++static int realtek_gpio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ unsigned int dev_flags; ++ struct gpio_irq_chip *girq; ++ struct realtek_gpio_ctrl *ctrl; ++ u32 ngpios; ++ int err, irq; ++ ++ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); ++ if (!ctrl) ++ return -ENOMEM; ++ ++ dev_flags = (unsigned int) device_get_match_data(dev); ++ ++ ngpios = REALTEK_GPIO_MAX; ++ device_property_read_u32(dev, "ngpios", &ngpios); ++ ++ if (ngpios > REALTEK_GPIO_MAX) { ++ dev_err(&pdev->dev, "invalid ngpios (max. %d)\n", ++ REALTEK_GPIO_MAX); ++ return -EINVAL; ++ } ++ ++ ctrl->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(ctrl->base)) ++ return PTR_ERR(ctrl->base); ++ ++ raw_spin_lock_init(&ctrl->lock); ++ ++ err = bgpio_init(&ctrl->gc, dev, 4, ++ ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL, ++ ctrl->base + REALTEK_GPIO_REG_DIR, NULL, ++ BGPIOF_BIG_ENDIAN_BYTE_ORDER); ++ if (err) { ++ dev_err(dev, "unable to init generic GPIO"); ++ return err; ++ } ++ ++ ctrl->gc.ngpio = ngpios; ++ ctrl->gc.owner = THIS_MODULE; ++ ++ irq = platform_get_irq_optional(pdev, 0); ++ if (!(dev_flags & GPIO_INTERRUPTS_DISABLED) && irq > 0) { ++ girq = &ctrl->gc.irq; ++ girq->chip = &realtek_gpio_irq_chip; ++ girq->default_type = IRQ_TYPE_NONE; ++ girq->handler = handle_bad_irq; ++ girq->parent_handler = realtek_gpio_irq_handler; ++ girq->num_parents = 1; ++ girq->parents = devm_kcalloc(dev, girq->num_parents, ++ sizeof(*girq->parents), GFP_KERNEL); ++ if (!girq->parents) ++ return -ENOMEM; ++ girq->parents[0] = irq; ++ girq->init_hw = realtek_gpio_irq_init; ++ } ++ ++ return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); ++} ++ ++static struct platform_driver realtek_gpio_driver = { ++ .driver = { ++ .name = "realtek-otto-gpio", ++ .of_match_table = realtek_gpio_of_match, ++ }, ++ .probe = realtek_gpio_probe, ++}; ++module_platform_driver(realtek_gpio_driver); ++ ++MODULE_DESCRIPTION("Realtek Otto GPIO support"); ++MODULE_AUTHOR("Sander Vanheule "); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch b/target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch new file mode 100644 index 0000000000..4ff98e44e8 --- /dev/null +++ b/target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch @@ -0,0 +1,13 @@ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -491,8 +491,8 @@ config GPIO_RDA + + config GPIO_REALTEK_OTTO + tristate "Realtek Otto GPIO support" +- depends on MACH_REALTEK_RTL +- default MACH_REALTEK_RTL ++ depends on RTL838X ++ default RTL838X + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help From b2bd0199a845281ca1c097d84caab022e98c2c59 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Fri, 21 May 2021 23:20:43 +0900 Subject: [PATCH 63/82] realtek: drop platform irq driver from 5.10 To use backported irq driver, drop old irq driver from realtek target and call irqchip_init() in setup.c. Signed-off-by: INAGAKI Hiroshi --- .../arch/mips/include/asm/mach-rtl838x/irq.h | 93 ------- .../files-5.10/arch/mips/rtl838x/Makefile | 2 +- .../files-5.10/arch/mips/rtl838x/irq.c | 226 ------------------ .../files-5.10/arch/mips/rtl838x/setup.c | 6 + 4 files changed, 7 insertions(+), 320 deletions(-) delete mode 100644 target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h delete mode 100644 target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c diff --git a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h deleted file mode 100644 index a4e95ab511..0000000000 --- a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/irq.h +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#ifndef _RTL83XX_IRQ_H_ -#define _RTL83XX_IRQ_H_ - -#define NR_IRQS 32 -#include_next - -/* Global Interrupt Mask Register */ -#define RTL83XX_ICTL_GIMR 0x00 -/* Global Interrupt Status Register */ -#define RTL83XX_ICTL_GISR 0x04 - -#define RTL83XX_IRQ_CPU_BASE 0 -#define RTL83XX_IRQ_CPU_NUM 8 -#define RTL83XX_IRQ_ICTL_BASE (RTL83XX_IRQ_CPU_BASE + RTL83XX_IRQ_CPU_NUM) -#define RTL83XX_IRQ_ICTL_NUM 32 - -/* Cascaded interrupts */ -#define RTL83XX_ICTL1_IRQ (RTL83XX_IRQ_CPU_BASE + 2) -#define RTL83XX_ICTL2_IRQ (RTL83XX_IRQ_CPU_BASE + 3) -#define RTL83XX_ICTL3_IRQ (RTL83XX_IRQ_CPU_BASE + 4) -#define RTL83XX_ICTL4_IRQ (RTL83XX_IRQ_CPU_BASE + 5) -#define RTL83XX_ICTL5_IRQ (RTL83XX_IRQ_CPU_BASE + 6) - -/* Interrupt routing register */ -#define RTL83XX_IRR0 0x08 -#define RTL83XX_IRR1 0x0c -#define RTL83XX_IRR2 0x10 -#define RTL83XX_IRR3 0x14 - -/* Cascade map */ -#define UART0_CASCADE 2 -#define UART1_CASCADE 1 -#define TC0_CASCADE 5 -#define TC1_CASCADE 1 -#define TC2_CASCADE 1 -#define TC3_CASCADE 1 -#define TC4_CASCADE 1 -#define OCPTO_CASCADE 1 -#define HLXTO_CASCADE 1 -#define SLXTO_CASCADE 1 -#define NIC_CASCADE 4 -#define GPIO_ABCD_CASCADE 4 -#define GPIO_EFGH_CASCADE 4 -#define RTC_CASCADE 4 -#define SWCORE_CASCADE 3 -#define WDT_IP1_CASCADE 4 -#define WDT_IP2_CASCADE 5 -#define USB_H2_CASCADE 1 - -/* Pack cascade map into interrupt routing registers */ -#define RTL83XX_IRR0_SETTING (\ - (UART0_CASCADE << 28) | \ - (UART1_CASCADE << 24) | \ - (TC0_CASCADE << 20) | \ - (TC1_CASCADE << 16) | \ - (OCPTO_CASCADE << 12) | \ - (HLXTO_CASCADE << 8) | \ - (SLXTO_CASCADE << 4) | \ - (NIC_CASCADE << 0)) -#define RTL83XX_IRR1_SETTING (\ - (GPIO_ABCD_CASCADE << 28) | \ - (GPIO_EFGH_CASCADE << 24) | \ - (RTC_CASCADE << 20) | \ - (SWCORE_CASCADE << 16)) -#define RTL83XX_IRR2_SETTING 0 -#define RTL83XX_IRR3_SETTING 0 - -/* On the RTL8390 there is no GPIO_EFGH and RTC IRQ */ -#define RTL8390_IRR1_SETTING (\ - (GPIO_ABCD_CASCADE << 28) | \ - (SWCORE_CASCADE << 16)) - -/* The RTL9300 has a different external IRQ numbering scheme */ -#define RTL9300_IRR0_SETTING (\ - (UART1_CASCADE << 28) | \ - (UART0_CASCADE << 24) | \ - (USB_H2_CASCADE << 16) | \ - (NIC_CASCADE << 0)) -#define RTL9300_IRR1_SETTING (\ - (SWCORE_CASCADE << 28)) -#define RTL9300_IRR2_SETTING (\ - (GPIO_ABCD_CASCADE << 20) | \ - (TC4_CASCADE << 12) | \ - (TC3_CASCADE << 8) | \ - (TC2_CASCADE << 4) | \ - (TC1_CASCADE << 0)) -#define RTL9300_IRR3_SETTING (\ - (TC0_CASCADE << 28) | \ - (WDT_IP1_CASCADE << 20)) - -#endif /* _RTL83XX_IRQ_H_ */ diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile index 8212dc3f48..a9d1666d46 100644 --- a/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Makefile @@ -2,4 +2,4 @@ # Makefile for the rtl838x specific parts of the kernel # -obj-y := setup.o prom.o irq.o +obj-y := setup.o prom.o diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c b/target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c deleted file mode 100644 index c0dd2f608c..0000000000 --- a/target/linux/realtek/files-5.10/arch/mips/rtl838x/irq.c +++ /dev/null @@ -1,226 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Realtek RTL83XX architecture specific IRQ handling - * - * based on the original BSP - * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com) - * Copyright (C) 2020 B. Koblitz - * Copyright (C) 2020 Bert Vermeulen - * Copyright (C) 2020 John Crispin - */ - -#include -#include -#include -#include -#include -#include - -#include -#include "irq.h" - -#define REALTEK_CPU_IRQ_SHARED0 (MIPS_CPU_IRQ_BASE + 2) -#define REALTEK_CPU_IRQ_UART (MIPS_CPU_IRQ_BASE + 3) -#define REALTEK_CPU_IRQ_SWITCH (MIPS_CPU_IRQ_BASE + 4) -#define REALTEK_CPU_IRQ_SHARED1 (MIPS_CPU_IRQ_BASE + 5) -#define REALTEK_CPU_IRQ_EXTERNAL (MIPS_CPU_IRQ_BASE + 6) -#define REALTEK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7) - -#define REG(x) (rtl83xx_ictl_base + x) - -extern struct rtl83xx_soc_info soc_info; - -static DEFINE_RAW_SPINLOCK(irq_lock); -static void __iomem *rtl83xx_ictl_base; - -static void rtl83xx_ictl_enable_irq(struct irq_data *i) -{ - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&irq_lock, flags); - - value = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)); - value |= BIT(i->hwirq); - rtl83xx_w32(value, REG(RTL83XX_ICTL_GIMR)); - - raw_spin_unlock_irqrestore(&irq_lock, flags); -} - -static void rtl83xx_ictl_disable_irq(struct irq_data *i) -{ - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&irq_lock, flags); - - value = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)); - value &= ~BIT(i->hwirq); - rtl83xx_w32(value, REG(RTL83XX_ICTL_GIMR)); - - raw_spin_unlock_irqrestore(&irq_lock, flags); -} - -static struct irq_chip rtl83xx_ictl_irq = { - .name = "RTL83xx", - .irq_enable = rtl83xx_ictl_enable_irq, - .irq_disable = rtl83xx_ictl_disable_irq, - .irq_ack = rtl83xx_ictl_disable_irq, - .irq_mask = rtl83xx_ictl_disable_irq, - .irq_unmask = rtl83xx_ictl_enable_irq, - .irq_eoi = rtl83xx_ictl_enable_irq, -}; - -static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -{ - irq_set_chip_and_handler(hw, &rtl83xx_ictl_irq, handle_level_irq); - - return 0; -} - -static const struct irq_domain_ops irq_domain_ops = { - .map = intc_map, - .xlate = irq_domain_xlate_onecell, -}; - -static void rtl838x_irq_dispatch(struct irq_desc *desc) -{ - unsigned int pending = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)) & - rtl83xx_r32(REG(RTL83XX_ICTL_GISR)); - - if (pending) { - struct irq_domain *domain = irq_desc_get_handler_data(desc); - generic_handle_irq(irq_find_mapping(domain, __ffs(pending))); - } else { - spurious_interrupt(); - } -} - -asmlinkage void plat_rtl83xx_irq_dispatch(void) -{ - unsigned int pending; - - pending = read_c0_cause() & read_c0_status() & ST0_IM; - - if (pending & CAUSEF_IP7) - do_IRQ(REALTEK_CPU_IRQ_COUNTER); - - else if (pending & CAUSEF_IP6) - do_IRQ(REALTEK_CPU_IRQ_EXTERNAL); - - else if (pending & CAUSEF_IP5) - do_IRQ(REALTEK_CPU_IRQ_SHARED1); - - else if (pending & CAUSEF_IP4) - do_IRQ(REALTEK_CPU_IRQ_SWITCH); - - else if (pending & CAUSEF_IP3) - do_IRQ(REALTEK_CPU_IRQ_UART); - - else if (pending & CAUSEF_IP2) - do_IRQ(REALTEK_CPU_IRQ_SHARED0); - - else - spurious_interrupt(); -} - -static int icu_setup_domain(struct device_node *node) -{ - struct irq_domain *domain; - - domain = irq_domain_add_simple(node, 32, 0, - &irq_domain_ops, NULL); - irq_set_chained_handler_and_data(2, rtl838x_irq_dispatch, domain); - irq_set_chained_handler_and_data(3, rtl838x_irq_dispatch, domain); - irq_set_chained_handler_and_data(4, rtl838x_irq_dispatch, domain); - irq_set_chained_handler_and_data(5, rtl838x_irq_dispatch, domain); - - rtl83xx_ictl_base = of_iomap(node, 0); - if (!rtl83xx_ictl_base) - return -EINVAL; - - return 0; -} - -static void __init rtl8380_icu_of_init(struct device_node *node, struct device_node *parent) -{ - if (icu_setup_domain(node)) - return; - - /* Disable all cascaded interrupts */ - rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR)); - - /* Set up interrupt routing */ - rtl83xx_w32(RTL83XX_IRR0_SETTING, REG(RTL83XX_IRR0)); - rtl83xx_w32(RTL83XX_IRR1_SETTING, REG(RTL83XX_IRR1)); - rtl83xx_w32(RTL83XX_IRR2_SETTING, REG(RTL83XX_IRR2)); - rtl83xx_w32(RTL83XX_IRR3_SETTING, REG(RTL83XX_IRR3)); - - /* Clear timer interrupt */ - write_c0_compare(0); - - /* Enable all CPU interrupts */ - write_c0_status(read_c0_status() | ST0_IM); - - /* Enable timer0 and uart0 interrupts */ - rtl83xx_w32(BIT(RTL83XX_IRQ_TC0) | BIT(RTL83XX_IRQ_UART0), REG(RTL83XX_ICTL_GIMR)); -} - -static void __init rtl8390_icu_of_init(struct device_node *node, struct device_node *parent) -{ - if (icu_setup_domain(node)) - return; - - /* Disable all cascaded interrupts */ - rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR)); - - /* Set up interrupt routing */ - rtl83xx_w32(RTL83XX_IRR0_SETTING, REG(RTL83XX_IRR0)); - rtl83xx_w32(RTL8390_IRR1_SETTING, REG(RTL83XX_IRR1)); - rtl83xx_w32(RTL83XX_IRR2_SETTING, REG(RTL83XX_IRR2)); - rtl83xx_w32(RTL83XX_IRR3_SETTING, REG(RTL83XX_IRR3)); - - /* Clear timer interrupt */ - write_c0_compare(0); - - /* Enable all CPU interrupts */ - write_c0_status(read_c0_status() | ST0_IM); - - /* Enable timer0 and uart0 interrupts */ - rtl83xx_w32(BIT(RTL83XX_IRQ_TC0) | BIT(RTL83XX_IRQ_UART0), REG(RTL83XX_ICTL_GIMR)); -} - -static void __init rtl9300_icu_of_init(struct device_node *node, struct device_node *parent) -{ - pr_info("RTL9300: Setting up IRQs\n"); - if (icu_setup_domain(node)) - return; - - /* Disable all cascaded interrupts */ - rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR)); - - /* Set up interrupt routing */ - rtl83xx_w32(RTL9300_IRR0_SETTING, REG(RTL83XX_IRR0)); - rtl83xx_w32(RTL9300_IRR1_SETTING, REG(RTL83XX_IRR1)); - rtl83xx_w32(RTL9300_IRR2_SETTING, REG(RTL83XX_IRR2)); - rtl83xx_w32(RTL9300_IRR3_SETTING, REG(RTL83XX_IRR3)); - - /* Clear timer interrupt */ - write_c0_compare(0); - - /* Enable all CPU interrupts */ - write_c0_status(read_c0_status() | ST0_IM); -} - -static struct of_device_id __initdata of_irq_ids[] = { - { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init }, - { .compatible = "realtek,rt8380-intc", .data = rtl8380_icu_of_init }, - { .compatible = "realtek,rt8390-intc", .data = rtl8390_icu_of_init }, - { .compatible = "realtek,rt9300-intc", .data = rtl9300_icu_of_init }, - {}, -}; - -void __init arch_init_irq(void) -{ - of_irq_init(of_irq_ids); -} diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c b/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c index ef97d485e1..752a856437 100644 --- a/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -193,3 +194,8 @@ void __init plat_time_init(void) mips_hpt_frequency = freq / 2; } + +void __init arch_init_irq(void) +{ + irqchip_init(); +} From 2cd00b51470a30198b048a5fca48a04db77e29cc Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Fri, 21 May 2021 23:16:37 +0900 Subject: [PATCH 64/82] realtek: backport irq-realtek-rtl driver from 5.12 to 5.10 This patch backports "irq-realtek-rtl" driver to Kernel 5.10 from 5.12. "MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X" is used in OpenWrt, so update the dependency by the additional patch. Signed-off-by: INAGAKI Hiroshi --- ...-add-realtek-rtl838x-rtl839x-support.patch | 84 +++++++ ...rtl838x-rtl839x-interrupt-controller.patch | 211 ++++++++++++++++++ ...pdate-dependency-for-irq-realtek-rtl.patch | 8 + 3 files changed, 303 insertions(+) create mode 100644 target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch create mode 100644 target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch create mode 100644 target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch diff --git a/target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch b/target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch new file mode 100644 index 0000000000..d6817d209d --- /dev/null +++ b/target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch @@ -0,0 +1,84 @@ +From 4a2b92a5d3519fc2c1edda4d4aa0e05bff41e8de Mon Sep 17 00:00:00 2001 +From: Bert Vermeulen +Date: Fri, 22 Jan 2021 21:42:23 +0100 +Subject: dt-bindings: interrupt-controller: Add Realtek RTL838x/RTL839x + support + +Document the binding for the Realtek RTL838x/RTL839x interrupt controller. + +Reviewed-by: Rob Herring +Signed-off-by: Bert Vermeulen +[maz: Add a commit message, as the author couldn't be bothered...] +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20210122204224.509124-2-bert@biot.com +--- + .../interrupt-controller/realtek,rtl-intc.yaml | 57 ++++++++++++++++++++++ + 1 file changed, 57 insertions(+) + create mode 100644 Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml + +diff --git a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml +new file mode 100644 +index 0000000000000..9e76fff20323c +--- /dev/null ++++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml +@@ -0,0 +1,57 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/interrupt-controller/realtek,rtl-intc.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Realtek RTL SoC interrupt controller devicetree bindings ++ ++maintainers: ++ - Birger Koblitz ++ - Bert Vermeulen ++ - John Crispin ++ ++properties: ++ compatible: ++ const: realtek,rtl-intc ++ ++ "#interrupt-cells": ++ const: 1 ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ interrupt-controller: true ++ ++ "#address-cells": ++ const: 0 ++ ++ interrupt-map: ++ description: Describes mapping from SoC interrupts to CPU interrupts ++ ++required: ++ - compatible ++ - reg ++ - "#interrupt-cells" ++ - interrupt-controller ++ - "#address-cells" ++ - interrupt-map ++ ++additionalProperties: false ++ ++examples: ++ - | ++ intc: interrupt-controller@3000 { ++ compatible = "realtek,rtl-intc"; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ reg = <0x3000 0x20>; ++ #address-cells = <0>; ++ interrupt-map = ++ <31 &cpuintc 2>, ++ <30 &cpuintc 1>, ++ <29 &cpuintc 5>; ++ }; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch b/target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch new file mode 100644 index 0000000000..753c41eb2f --- /dev/null +++ b/target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch @@ -0,0 +1,211 @@ +From 9f3a0f34b84ad1b9a8f2bdae44b66f16685b2143 Mon Sep 17 00:00:00 2001 +From: Bert Vermeulen +Date: Fri, 22 Jan 2021 21:42:24 +0100 +Subject: irqchip: Add support for Realtek RTL838x/RTL839x interrupt controller + +This is a standard IRQ driver with only status and mask registers. + +The mapping from SoC interrupts (18-31) to MIPS core interrupts is +done via an interrupt-map in device tree. + +Signed-off-by: Bert Vermeulen +Signed-off-by: Birger Koblitz +Acked-by: John Crispin +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20210122204224.509124-3-bert@biot.com +--- + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-realtek-rtl.c | 180 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 181 insertions(+) + create mode 100644 drivers/irqchip/irq-realtek-rtl.c + +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -114,3 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-l + obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o + obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o + obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o ++obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o +--- /dev/null ++++ b/drivers/irqchip/irq-realtek-rtl.c +@@ -0,0 +1,180 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Birger Koblitz ++ * Copyright (C) 2020 Bert Vermeulen ++ * Copyright (C) 2020 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Global Interrupt Mask Register */ ++#define RTL_ICTL_GIMR 0x00 ++/* Global Interrupt Status Register */ ++#define RTL_ICTL_GISR 0x04 ++/* Interrupt Routing Registers */ ++#define RTL_ICTL_IRR0 0x08 ++#define RTL_ICTL_IRR1 0x0c ++#define RTL_ICTL_IRR2 0x10 ++#define RTL_ICTL_IRR3 0x14 ++ ++#define REG(x) (realtek_ictl_base + x) ++ ++static DEFINE_RAW_SPINLOCK(irq_lock); ++static void __iomem *realtek_ictl_base; ++ ++static void realtek_ictl_unmask_irq(struct irq_data *i) ++{ ++ unsigned long flags; ++ u32 value; ++ ++ raw_spin_lock_irqsave(&irq_lock, flags); ++ ++ value = readl(REG(RTL_ICTL_GIMR)); ++ value |= BIT(i->hwirq); ++ writel(value, REG(RTL_ICTL_GIMR)); ++ ++ raw_spin_unlock_irqrestore(&irq_lock, flags); ++} ++ ++static void realtek_ictl_mask_irq(struct irq_data *i) ++{ ++ unsigned long flags; ++ u32 value; ++ ++ raw_spin_lock_irqsave(&irq_lock, flags); ++ ++ value = readl(REG(RTL_ICTL_GIMR)); ++ value &= ~BIT(i->hwirq); ++ writel(value, REG(RTL_ICTL_GIMR)); ++ ++ raw_spin_unlock_irqrestore(&irq_lock, flags); ++} ++ ++static struct irq_chip realtek_ictl_irq = { ++ .name = "realtek-rtl-intc", ++ .irq_mask = realtek_ictl_mask_irq, ++ .irq_unmask = realtek_ictl_unmask_irq, ++}; ++ ++static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .map = intc_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++static void realtek_irq_dispatch(struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct irq_domain *domain; ++ unsigned int pending; ++ ++ chained_irq_enter(chip, desc); ++ pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR)); ++ if (unlikely(!pending)) { ++ spurious_interrupt(); ++ goto out; ++ } ++ domain = irq_desc_get_handler_data(desc); ++ generic_handle_irq(irq_find_mapping(domain, __ffs(pending))); ++ ++out: ++ chained_irq_exit(chip, desc); ++} ++ ++/* ++ * SoC interrupts are cascaded to MIPS CPU interrupts according to the ++ * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for ++ * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts ++ * thus go into 4 IRRs. ++ */ ++static int __init map_interrupts(struct device_node *node, struct irq_domain *domain) ++{ ++ struct device_node *cpu_ictl; ++ const __be32 *imap; ++ u32 imaplen, soc_int, cpu_int, tmp, regs[4]; ++ int ret, i, irr_regs[] = { ++ RTL_ICTL_IRR3, ++ RTL_ICTL_IRR2, ++ RTL_ICTL_IRR1, ++ RTL_ICTL_IRR0, ++ }; ++ u8 mips_irqs_set; ++ ++ ret = of_property_read_u32(node, "#address-cells", &tmp); ++ if (ret || tmp) ++ return -EINVAL; ++ ++ imap = of_get_property(node, "interrupt-map", &imaplen); ++ if (!imap || imaplen % 3) ++ return -EINVAL; ++ ++ mips_irqs_set = 0; ++ memset(regs, 0, sizeof(regs)); ++ for (i = 0; i < imaplen; i += 3 * sizeof(u32)) { ++ soc_int = be32_to_cpup(imap); ++ if (soc_int > 31) ++ return -EINVAL; ++ ++ cpu_ictl = of_find_node_by_phandle(be32_to_cpup(imap + 1)); ++ if (!cpu_ictl) ++ return -EINVAL; ++ ret = of_property_read_u32(cpu_ictl, "#interrupt-cells", &tmp); ++ if (ret || tmp != 1) ++ return -EINVAL; ++ of_node_put(cpu_ictl); ++ ++ cpu_int = be32_to_cpup(imap + 2); ++ if (cpu_int > 7) ++ return -EINVAL; ++ ++ if (!(mips_irqs_set & BIT(cpu_int))) { ++ irq_set_chained_handler_and_data(cpu_int, realtek_irq_dispatch, ++ domain); ++ mips_irqs_set |= BIT(cpu_int); ++ } ++ ++ regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32; ++ imap += 3; ++ } ++ ++ for (i = 0; i < 4; i++) ++ writel(regs[i], REG(irr_regs[i])); ++ ++ return 0; ++} ++ ++static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent) ++{ ++ struct irq_domain *domain; ++ int ret; ++ ++ realtek_ictl_base = of_iomap(node, 0); ++ if (!realtek_ictl_base) ++ return -ENXIO; ++ ++ /* Disable all cascaded interrupts */ ++ writel(0, REG(RTL_ICTL_GIMR)); ++ ++ domain = irq_domain_add_simple(node, 32, 0, ++ &irq_domain_ops, NULL); ++ ++ ret = map_interrupts(node, domain); ++ if (ret) { ++ pr_err("invalid interrupt map\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++IRQCHIP_DECLARE(realtek_rtl_intc, "realtek,rtl-intc", realtek_rtl_of_init); diff --git a/target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch b/target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch new file mode 100644 index 0000000000..96321f0bba --- /dev/null +++ b/target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch @@ -0,0 +1,8 @@ +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -114,4 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-l + obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o + obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o + obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o +-obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o ++obj-$(CONFIG_RTL838X) += irq-realtek-rtl.o From 2ec38bfea1f5a66848a086f1cc09844c66512847 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 14:18:43 +0900 Subject: [PATCH 65/82] realtek: fix "help" line in Kconfig in files/patches for 5.10 In Kernel 5.10, "help" must be used instead of "---help---". this patch fixes the following errors: drivers/net/dsa/rtl83xx/Kconfig:7: syntax errorgit drivers/net/dsa/rtl83xx/Kconfig:6: unknown statement "---help---" drivers/net/dsa/rtl83xx/Kconfig:7:warning: ignoring unsupported character '.' drivers/net/dsa/rtl83xx/Kconfig:7: unknown statement "This" drivers/net/ethernet/Kconfig:170: syntax error drivers/net/ethernet/Kconfig:169: unknown statement "---help---" drivers/net/ethernet/Kconfig:170:warning: ignoring unsupported character '.' drivers/net/ethernet/Kconfig:170: unknown statement "Say" drivers/net/phy/Kconfig:331: syntax error drivers/net/phy/Kconfig:330: unknown statement "---help---" drivers/net/phy/Kconfig:331: unknown statement "Supports" Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig | 2 +- .../702-net-ethernet-add-support-for-rtl838x-ethernet.patch | 2 +- target/linux/realtek/patches-5.10/705-add-rtl-phy.patch | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig index f293832eb5..b423d2c3ea 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Kconfig @@ -3,6 +3,6 @@ config NET_DSA_RTL83XX tristate "Realtek RTL838x/RTL839x switch support" depends on RTL838X select NET_DSA_TAG_TRAILER - ---help--- + help This driver adds support for Realtek RTL83xx series switching. diff --git a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch index 11e62450d5..b3a6dd9a72 100644 --- a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch +++ b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch @@ -8,7 +8,7 @@ +config NET_RTL838X + tristate "Realtek rtl838x Ethernet MAC support" + depends on RTL838X -+ ---help--- ++ help + Say Y here if you want to use the Realtek rtl838x Gbps Ethernet MAC. + source "drivers/net/ethernet/samsung/Kconfig" diff --git a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch index f4cd8f2d6d..c1b74f7fe4 100644 --- a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch +++ b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch @@ -7,7 +7,7 @@ +config REALTEK_SOC_PHY + tristate "Realtek SoC PHYs" + depends on RTL838X -+ ---help--- ++ help + Supports the PHYs found in combination with Realtek Switch SoCs + config RENESAS_PHY From 781f50705c05d18eab48b2bc885e01608030e19b Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 15:20:03 +0900 Subject: [PATCH 66/82] realtek: drop fixup_bigphys_addr from ioremap.h in 5.10 A macro with the same name is provided in asm/pgtable.h in Kernel 5.10, use it and drop from ioremap.h. Signed-off-by: INAGAKI Hiroshi --- .../files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h index e7a5bfaffc..c49a095792 100644 --- a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h +++ b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/ioremap.h @@ -2,11 +2,6 @@ #ifndef RTL838X_IOREMAP_H_ #define RTL838X_IOREMAP_H_ -static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) -{ - return phys_addr; -} - static inline int is_rtl838x_internal_registers(phys_addr_t offset) { /* IO-Block */ From 46945e02d3527e3948dacb3e74e5ddbc35da7238 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 6 May 2021 18:17:54 +0900 Subject: [PATCH 67/82] realtek: remove unnecessary line from rtl838x/Platform in 5.10 The following line is already defined in arch/mips/Kbuild.platforms by 300-mips-add-rtl838x-platform.patch. platform-$(CONFIG_RTL838X) += rtl838x/ Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform | 1 - 1 file changed, 1 deletion(-) diff --git a/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform index 4d48932d80..f9f189b689 100644 --- a/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform +++ b/target/linux/realtek/files-5.10/arch/mips/rtl838x/Platform @@ -1,6 +1,5 @@ # # Realtek RTL838x SoCs # -platform-$(CONFIG_RTL838X) += rtl838x/ cflags-$(CONFIG_RTL838X) += -I$(srctree)/arch/mips/include/asm/mach-rtl838x/ load-$(CONFIG_RTL838X) += 0xffffffff80000000 From 95f089dafefccb2ce1892506dd936f47caf657bf Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 14:02:49 +0900 Subject: [PATCH 68/82] realtek: refresh patches for Kernel 5.10 This patch refresh all patches in patches-5.10/ to adjust for Kernel 5.10. Signed-off-by: INAGAKI Hiroshi --- .../300-mips-add-rtl838x-platform.patch | 20 +++++++++--------- .../301-gpio-add-rtl8231-driver.patch | 6 +++--- .../302-clocksource-add-rtl9300-driver.patch | 10 ++------- ...t-dsa-add-support-for-rtl838x-switch.patch | 8 +++---- ...-add-rtl838x-support-for-tag-trailer.patch | 6 +++--- ...net-add-support-for-rtl838x-ethernet.patch | 4 ++-- ...nclude-linux-add-phy-ops-for-rtl838x.patch | 8 +++---- ...vers-net-phy-eee-support-for-rtl838x.patch | 21 +++++++++---------- .../patches-5.10/705-add-rtl-phy.patch | 10 ++++----- ...rease-phy-address-number-for-rtl839x.patch | 2 +- 10 files changed, 44 insertions(+), 51 deletions(-) diff --git a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch index ecc77b2a73..6217d80d3f 100644 --- a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch +++ b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch @@ -1,16 +1,16 @@ --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms -@@ -27,6 +27,7 @@ platforms += pistachio - platforms += pmcs-msp71xx - platforms += pnx833x - platforms += ralink -+platforms += rtl838x - platforms += rb532 - platforms += sgi-ip22 - platforms += sgi-ip27 +@@ -23,6 +23,7 @@ platform-$(CONFIG_PIC32MZDA) += pic32/ + platform-$(CONFIG_MACH_PISTACHIO) += pistachio/ + platform-$(CONFIG_RALINK) += ralink/ + platform-$(CONFIG_MIKROTIK_RB532) += rb532/ ++platform-$(CONFIG_RTL838X) += rtl838x/ + platform-$(CONFIG_SGI_IP22) += sgi-ip22/ + platform-$(CONFIG_SGI_IP27) += sgi-ip27/ + platform-$(CONFIG_SGI_IP28) += sgi-ip22/ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -631,6 +631,26 @@ config RALINK +@@ -627,6 +627,26 @@ config RALINK select ARCH_HAS_RESET_CONTROLLER select RESET_CONTROLLER @@ -36,4 +36,4 @@ + config SGI_IP22 bool "SGI IP22 (Indy/Indigo2)" - select FW_ARC + select ARC_MEMORY diff --git a/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch b/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch index 8a3d4810a6..496d3f4162 100644 --- a/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch +++ b/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch @@ -1,6 +1,6 @@ --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -441,6 +441,12 @@ config GPIO_REG +@@ -508,6 +508,12 @@ config GPIO_REG A 32-bit single register GPIO fixed in/out implementation. This can be used to represent any register as a set of GPIO signals. @@ -15,9 +15,9 @@ depends on MFD_SYSCON --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -117,6 +117,7 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t - obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +@@ -126,6 +126,7 @@ obj-$(CONFIG_GPIO_RDA) += gpio-rda.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o obj-$(CONFIG_GPIO_REG) += gpio-reg.o +obj-$(CONFIG_GPIO_RTL8231) += gpio-rtl8231.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o diff --git a/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch b/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch index 1c41db75b2..a78f070d63 100644 --- a/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch +++ b/target/linux/realtek/patches-5.10/302-clocksource-add-rtl9300-driver.patch @@ -1,6 +1,6 @@ --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig -@@ -127,6 +127,15 @@ config RDA_TIMER +@@ -126,6 +126,15 @@ config RDA_TIMER help Enables the support for the RDA Micro timer driver. @@ -16,15 +16,9 @@ config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST depends on HAS_IOMEM -@@ -696,5 +705,4 @@ config INGENIC_TIMER - select IRQ_DOMAIN - help - Support for the timer/counter unit of the Ingenic JZ SoCs. -- - endmenu --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile -@@ -61,6 +61,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) += timer-mi +@@ -63,6 +63,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) += timer-mi obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o obj-$(CONFIG_RDA_TIMER) += timer-rda.o diff --git a/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch b/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch index bb6f83e55d..af5fb18c26 100644 --- a/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch +++ b/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch @@ -1,6 +1,6 @@ --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig -@@ -63,6 +63,8 @@ config NET_DSA_QCA8K +@@ -67,6 +67,8 @@ config NET_DSA_QCA8K This enables support for the Qualcomm Atheros QCA8K Ethernet switch chips. @@ -11,8 +11,8 @@ depends on NET_DSA --- a/drivers/net/dsa/Makefile +++ b/drivers/net/dsa/Makefile -@@ -21,3 +21,4 @@ obj-y += b53/ - obj-y += microchip/ - obj-y += mv88e6xxx/ +@@ -23,3 +23,4 @@ obj-y += mv88e6xxx/ + obj-y += ocelot/ + obj-y += qca/ obj-y += sja1105/ +obj-y += rtl83xx/ diff --git a/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch b/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch index 803614e7c0..8c7efb58f3 100644 --- a/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch +++ b/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch @@ -1,8 +1,8 @@ --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c -@@ -44,7 +44,12 @@ static struct sk_buff *trailer_xmit(stru +@@ -17,7 +17,12 @@ static struct sk_buff *trailer_xmit(stru - trailer = skb_put(nskb, 4); + trailer = skb_put(skb, 4); trailer[0] = 0x80; + +#ifdef CONFIG_NET_DSA_RTL83XX @@ -13,7 +13,7 @@ trailer[2] = 0x10; trailer[3] = 0x00; -@@ -61,12 +66,23 @@ static struct sk_buff *trailer_rcv(struc +@@ -34,12 +39,23 @@ static struct sk_buff *trailer_rcv(struc return NULL; trailer = skb_tail_pointer(skb) - 4; diff --git a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch index b3a6dd9a72..1a6668550d 100644 --- a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch +++ b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch @@ -1,6 +1,6 @@ --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig -@@ -163,6 +163,13 @@ source "drivers/net/ethernet/rdc/Kconfig +@@ -162,6 +162,13 @@ source "drivers/net/ethernet/rdc/Kconfig source "drivers/net/ethernet/realtek/Kconfig" source "drivers/net/ethernet/renesas/Kconfig" source "drivers/net/ethernet/rocker/Kconfig" @@ -16,7 +16,7 @@ source "drivers/net/ethernet/sfc/Kconfig" --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_NET_VENDOR_REALTEK) += real +@@ -75,6 +75,7 @@ obj-$(CONFIG_NET_VENDOR_REALTEK) += real obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/ obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/ diff --git a/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch b/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch index 3682eb30a3..0a771b64f0 100644 --- a/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch +++ b/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch @@ -1,9 +1,9 @@ --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -645,6 +645,10 @@ struct phy_driver { - struct ethtool_tunable *tuna, - const void *data); - int (*set_loopback)(struct phy_device *dev, bool enable); +@@ -881,6 +881,10 @@ struct phy_driver { + int (*get_sqi)(struct phy_device *dev); + /** @get_sqi_max: Get the maximum signal quality indication */ + int (*get_sqi_max)(struct phy_device *dev); + int (*get_port)(struct phy_device *dev); + int (*set_port)(struct phy_device *dev, int port); + int (*get_eee)(struct phy_device *dev, struct ethtool_eee *e); diff --git a/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch b/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch index 7743147ea3..cca724293d 100644 --- a/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch +++ b/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch @@ -1,18 +1,18 @@ --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -1242,6 +1242,11 @@ int phylink_ethtool_ksettings_set(struct - - /* If we have a PHY, configure the phy */ - if (pl->phydev) { +@@ -1425,6 +1425,11 @@ int phylink_ethtool_ksettings_set(struct + * the presence of a PHY, this should not be changed as that + * should be determined from the media side advertisement. + */ + if (pl->phydev->drv->get_port && pl->phydev->drv->set_port) { + if(pl->phydev->drv->get_port(pl->phydev) != kset->base.port) { + pl->phydev->drv->set_port(pl->phydev, kset->base.port); + } + } - ret = phy_ethtool_ksettings_set(pl->phydev, &our_kset); - if (ret) - return ret; -@@ -1420,8 +1425,11 @@ int phylink_ethtool_get_eee(struct phyli + return phy_ethtool_ksettings_set(pl->phydev, kset); + } + +@@ -1700,8 +1705,11 @@ int phylink_ethtool_get_eee(struct phyli ASSERT_RTNL(); @@ -25,7 +25,7 @@ return ret; } -@@ -1438,9 +1446,11 @@ int phylink_ethtool_set_eee(struct phyli +@@ -1718,8 +1726,11 @@ int phylink_ethtool_set_eee(struct phyli ASSERT_RTNL(); @@ -34,8 +34,7 @@ + if (pl->phydev->drv->set_eee) + return pl->phydev->drv->set_eee(pl->phydev, eee); ret = phy_ethtool_set_eee(pl->phydev, eee); -- + } + return ret; } - EXPORT_SYMBOL_GPL(phylink_ethtool_set_eee); diff --git a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch index c1b74f7fe4..dbd936b446 100644 --- a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch +++ b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch @@ -1,7 +1,7 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -540,6 +540,12 @@ config REALTEK_PHY - ---help--- +@@ -324,6 +324,12 @@ config REALTEK_PHY + help Supports the Realtek 821x PHY. +config REALTEK_SOC_PHY @@ -11,11 +11,11 @@ + Supports the PHYs found in combination with Realtek Switch SoCs + config RENESAS_PHY - tristate "Driver for Renesas PHYs" - ---help--- + tristate "Renesas PHYs" + help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -102,6 +102,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o +@@ -86,6 +86,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o diff --git a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch index ca6deb74d8..d36299d43b 100644 --- a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch +++ b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch @@ -1,6 +1,6 @@ --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -188,7 +188,7 @@ static inline const char *phy_modes(phy_ +@@ -226,7 +226,7 @@ static inline const char *phy_modes(phy_ #define PHY_INIT_TIMEOUT 100000 #define PHY_FORCE_TIMEOUT 10 From 9e418b061c1720d677e73f2ee06651533889a69a Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 22:47:19 +0900 Subject: [PATCH 69/82] realtek: refresh and update config-5.10 This patch adjusts config-5.10 by running kernel_menuconfig. Note: - disable psb6970 phy driver (unused in realtek target?) Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/config-5.10 | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 index 8baecf42f3..1b050fc081 100644 --- a/target/linux/realtek/config-5.10 +++ b/target/linux/realtek/config-5.10 @@ -1,22 +1,22 @@ CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_CEVT_R4K=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_HAVE_CLK=y CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_BOSTON=y +CONFIG_COMPAT_32BIT_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 CONFIG_CPU_BIG_ENDIAN=y CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_LOAD_STORE_LR=y +CONFIG_CPU_HAS_DIEI=y CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_RIXI=y CONFIG_CPU_HAS_SYNC=y @@ -29,25 +29,20 @@ CONFIG_CPU_R4K_CACHE_TLB=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 +CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_RNG2=y CONFIG_CSRC_R4K=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_SECTION_MISMATCH=y CONFIG_DMA_NONCOHERENT=y -CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y CONFIG_DTC=y CONFIG_EARLY_PRINTK=y CONFIG_EARLY_PRINTK_8250=y -CONFIG_EFI_EARLYCON=y -CONFIG_ETHERNET_PACKET_MANGLE=y CONFIG_EXTRA_FIRMWARE="rtl838x_phy/rtl838x_8214fc.fw rtl838x_phy/rtl838x_8218b.fw rtl838x_phy/rtl838x_8380.fw" CONFIG_EXTRA_FIRMWARE_DIR="firmware" CONFIG_FIXED_PHY=y -CONFIG_FONT_8x16=y -CONFIG_FONT_AUTOSELECT=y -CONFIG_FONT_SUPPORT=y CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -76,7 +71,6 @@ CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_GENERIC=y CONFIG_GPIO_REALTEK_OTTO=y CONFIG_GPIO_RTL8231=y -CONFIG_REALTEK_SOC_PHY=y CONFIG_GRO_CELLS=y CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y @@ -101,10 +95,12 @@ CONFIG_LEDS_GPIO=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 CONFIG_LIBFDT=y +CONFIG_LLD_VERSION=0 CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_MARVELL_PHY=y CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y CONFIG_MDIO_I2C=y CONFIG_MEMFD_CREATE=y CONFIG_MFD_SYSCON=y @@ -119,6 +115,7 @@ CONFIG_MIPS_CLOCK_VSYSCALL=y CONFIG_MIPS_CMDLINE_FROM_DTB=y # CONFIG_MIPS_ELF_APPENDED_DTB is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_MIPS_LD_CAN_LINK_VDSO=y # CONFIG_MIPS_NO_APPENDED_DTB is not set CONFIG_MIPS_RAW_APPENDED_DTB=y CONFIG_MIPS_SPRAM=y @@ -160,8 +157,9 @@ CONFIG_PHYLINK=y CONFIG_PINCTRL=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_SYSCON=y -CONFIG_PSB6970_PHY=y +CONFIG_RATIONAL=y CONFIG_REALTEK_PHY=y +CONFIG_REALTEK_SOC_PHY=y CONFIG_REGMAP=y CONFIG_REGMAP_MMIO=y CONFIG_RESET_CONTROLLER=y @@ -174,7 +172,6 @@ CONFIG_SPI=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y CONFIG_SWPHY=y CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y @@ -186,6 +183,8 @@ CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y CONFIG_TARGET_ISA_REV=2 CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y CONFIG_TINY_SRCU=y CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y CONFIG_USE_OF=y From 0de230bd0ce1c011a6d57ce7692b1b7898e7b735 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 11 Aug 2021 20:23:06 +0900 Subject: [PATCH 70/82] realtek: copy dts directory for Kernel 5.10 This patch adds "dts-5.10" directory to use backported drivers. There are several specification changes in the new drivers, so there are some compatibility issues in using dts/dtsi files for 5.4. The old DTS files are moved to "dts-5.4", so their corresponding kernel version is obvious as well. Signed-off-by: INAGAKI Hiroshi [change "dts" to "dts-5.4", adjust Makefile] Signed-off-by: Adrian Schmutzler --- .../rtl8380_netgear_gigabit.dtsi | 0 .../rtl8380_netgear_gigabit_1xx.dtsi | 0 .../rtl8380_netgear_gigabit_3xx.dtsi | 0 .../rtl8380_netgear_gs108t-v3.dts | 0 .../rtl8380_netgear_gs110tpp-v1.dts | 0 .../rtl8380_netgear_gs308t-v1.dts | 0 .../rtl8380_netgear_gs310tp-v1.dts | 0 .../rtl8380_zyxel_gs1900-10hp.dts | 0 .../rtl8380_zyxel_gs1900-8.dts | 0 .../rtl8380_zyxel_gs1900-8hp-v1.dts | 0 .../rtl8380_zyxel_gs1900-8hp-v2.dts | 0 .../rtl8380_zyxel_gs1900.dtsi | 0 .../rtl8382_allnet_all-sg8208m.dts | 0 .../rtl8382_d-link_dgs-1210-10p.dts | 0 .../rtl8382_d-link_dgs-1210-16.dts | 0 .../rtl8382_d-link_dgs-1210-28.dts | 0 .../rtl8382_d-link_dgs-1210.dtsi | 0 .../rtl8382_inaba_aml2-17gp.dts | 0 .../rtl8382_zyxel_gs1900-24hp-v2.dts | 0 .../realtek/{dts => dts-5.10}/rtl838x.dtsi | 0 .../realtek/{dts => dts-5.10}/rtl930x.dtsi | 0 .../dts-5.4/rtl8380_netgear_gigabit.dtsi | 78 ++++++++ .../dts-5.4/rtl8380_netgear_gigabit_1xx.dtsi | 61 ++++++ .../dts-5.4/rtl8380_netgear_gigabit_3xx.dtsi | 61 ++++++ .../dts-5.4/rtl8380_netgear_gs108t-v3.dts | 8 + .../dts-5.4/rtl8380_netgear_gs110tpp-v1.dts | 8 + .../dts-5.4/rtl8380_netgear_gs308t-v1.dts | 8 + .../dts-5.4/rtl8380_netgear_gs310tp-v1.dts | 21 ++ .../dts-5.4/rtl8380_zyxel_gs1900-10hp.dts | 71 +++++++ .../dts-5.4/rtl8380_zyxel_gs1900-8.dts | 12 ++ .../dts-5.4/rtl8380_zyxel_gs1900-8hp-v1.dts | 8 + .../dts-5.4/rtl8380_zyxel_gs1900-8hp-v2.dts | 8 + .../realtek/dts-5.4/rtl8380_zyxel_gs1900.dtsi | 148 ++++++++++++++ .../dts-5.4/rtl8382_allnet_all-sg8208m.dts | 146 ++++++++++++++ .../dts-5.4/rtl8382_d-link_dgs-1210-10p.dts | 152 ++++++++++++++ .../dts-5.4/rtl8382_d-link_dgs-1210-16.dts | 80 ++++++++ .../dts-5.4/rtl8382_d-link_dgs-1210-28.dts | 98 +++++++++ .../dts-5.4/rtl8382_d-link_dgs-1210.dtsi | 88 ++++++++ .../dts-5.4/rtl8382_inaba_aml2-17gp.dts | 164 +++++++++++++++ .../dts-5.4/rtl8382_zyxel_gs1900-24hp-v2.dts | 117 +++++++++++ target/linux/realtek/dts-5.4/rtl838x.dtsi | 188 ++++++++++++++++++ target/linux/realtek/dts-5.4/rtl930x.dtsi | 182 +++++++++++++++++ target/linux/realtek/image/Makefile | 2 +- 43 files changed, 1708 insertions(+), 1 deletion(-) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gigabit.dtsi (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gigabit_1xx.dtsi (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gigabit_3xx.dtsi (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gs108t-v3.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gs110tpp-v1.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gs308t-v1.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_netgear_gs310tp-v1.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_zyxel_gs1900-10hp.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_zyxel_gs1900-8.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_zyxel_gs1900-8hp-v1.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_zyxel_gs1900-8hp-v2.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8380_zyxel_gs1900.dtsi (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_allnet_all-sg8208m.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_d-link_dgs-1210-10p.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_d-link_dgs-1210-16.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_d-link_dgs-1210-28.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_d-link_dgs-1210.dtsi (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_inaba_aml2-17gp.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl8382_zyxel_gs1900-24hp-v2.dts (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl838x.dtsi (100%) rename target/linux/realtek/{dts => dts-5.10}/rtl930x.dtsi (100%) create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit.dtsi create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_1xx.dtsi create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_3xx.dtsi create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gs108t-v3.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gs110tpp-v1.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gs308t-v1.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_netgear_gs310tp-v1.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-10hp.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v1.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v2.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900.dtsi create mode 100644 target/linux/realtek/dts-5.4/rtl8382_allnet_all-sg8208m.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-10p.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-16.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-28.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210.dtsi create mode 100644 target/linux/realtek/dts-5.4/rtl8382_inaba_aml2-17gp.dts create mode 100644 target/linux/realtek/dts-5.4/rtl8382_zyxel_gs1900-24hp-v2.dts create mode 100644 target/linux/realtek/dts-5.4/rtl838x.dtsi create mode 100644 target/linux/realtek/dts-5.4/rtl930x.dtsi diff --git a/target/linux/realtek/dts/rtl8380_netgear_gigabit.dtsi b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gigabit.dtsi rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi diff --git a/target/linux/realtek/dts/rtl8380_netgear_gigabit_1xx.dtsi b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit_1xx.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gigabit_1xx.dtsi rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit_1xx.dtsi diff --git a/target/linux/realtek/dts/rtl8380_netgear_gigabit_3xx.dtsi b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit_3xx.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gigabit_3xx.dtsi rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit_3xx.dtsi diff --git a/target/linux/realtek/dts/rtl8380_netgear_gs108t-v3.dts b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs108t-v3.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gs108t-v3.dts rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gs108t-v3.dts diff --git a/target/linux/realtek/dts/rtl8380_netgear_gs110tpp-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gs110tpp-v1.dts rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts diff --git a/target/linux/realtek/dts/rtl8380_netgear_gs308t-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs308t-v1.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gs308t-v1.dts rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gs308t-v1.dts diff --git a/target/linux/realtek/dts/rtl8380_netgear_gs310tp-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_netgear_gs310tp-v1.dts rename to target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts diff --git a/target/linux/realtek/dts/rtl8380_zyxel_gs1900-10hp.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_zyxel_gs1900-10hp.dts rename to target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts diff --git a/target/linux/realtek/dts/rtl8380_zyxel_gs1900-8.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_zyxel_gs1900-8.dts rename to target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8.dts diff --git a/target/linux/realtek/dts/rtl8380_zyxel_gs1900-8hp-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_zyxel_gs1900-8hp-v1.dts rename to target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts diff --git a/target/linux/realtek/dts/rtl8380_zyxel_gs1900-8hp-v2.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts similarity index 100% rename from target/linux/realtek/dts/rtl8380_zyxel_gs1900-8hp-v2.dts rename to target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts diff --git a/target/linux/realtek/dts/rtl8380_zyxel_gs1900.dtsi b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl8380_zyxel_gs1900.dtsi rename to target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900.dtsi diff --git a/target/linux/realtek/dts/rtl8382_allnet_all-sg8208m.dts b/target/linux/realtek/dts-5.10/rtl8382_allnet_all-sg8208m.dts similarity index 100% rename from target/linux/realtek/dts/rtl8382_allnet_all-sg8208m.dts rename to target/linux/realtek/dts-5.10/rtl8382_allnet_all-sg8208m.dts diff --git a/target/linux/realtek/dts/rtl8382_d-link_dgs-1210-10p.dts b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts similarity index 100% rename from target/linux/realtek/dts/rtl8382_d-link_dgs-1210-10p.dts rename to target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts diff --git a/target/linux/realtek/dts/rtl8382_d-link_dgs-1210-16.dts b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-16.dts similarity index 100% rename from target/linux/realtek/dts/rtl8382_d-link_dgs-1210-16.dts rename to target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-16.dts diff --git a/target/linux/realtek/dts/rtl8382_d-link_dgs-1210-28.dts b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-28.dts similarity index 100% rename from target/linux/realtek/dts/rtl8382_d-link_dgs-1210-28.dts rename to target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-28.dts diff --git a/target/linux/realtek/dts/rtl8382_d-link_dgs-1210.dtsi b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl8382_d-link_dgs-1210.dtsi rename to target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210.dtsi diff --git a/target/linux/realtek/dts/rtl8382_inaba_aml2-17gp.dts b/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts similarity index 100% rename from target/linux/realtek/dts/rtl8382_inaba_aml2-17gp.dts rename to target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts diff --git a/target/linux/realtek/dts/rtl8382_zyxel_gs1900-24hp-v2.dts b/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts similarity index 100% rename from target/linux/realtek/dts/rtl8382_zyxel_gs1900-24hp-v2.dts rename to target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts diff --git a/target/linux/realtek/dts/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl838x.dtsi rename to target/linux/realtek/dts-5.10/rtl838x.dtsi diff --git a/target/linux/realtek/dts/rtl930x.dtsi b/target/linux/realtek/dts-5.10/rtl930x.dtsi similarity index 100% rename from target/linux/realtek/dts/rtl930x.dtsi rename to target/linux/realtek/dts-5.10/rtl930x.dtsi diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit.dtsi b/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit.dtsi new file mode 100644 index 0000000000..8ba66d6023 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit.dtsi @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl838x.dtsi" + +#include +#include + +/ { + compatible = "realtek,rtl838x-soc"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + mode { + label = "reset"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&gpio0 { + indirect-access-bus-id = <0>; +}; + +ðernet0 { + mdio: mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(8, 1, internal) + SWITCH_PORT(9, 2, internal) + SWITCH_PORT(10, 3, internal) + SWITCH_PORT(11, 4, internal) + SWITCH_PORT(12, 5, internal) + SWITCH_PORT(13, 6, internal) + SWITCH_PORT(14, 7, internal) + SWITCH_PORT(15, 8, internal) + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_1xx.dtsi b/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_1xx.dtsi new file mode 100644 index 0000000000..7eccfcb5a2 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_1xx.dtsi @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit.dtsi" + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x00e0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0x00e0000 0x0010000>; + read-only; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0x00f0000 0x0010000>; + }; + + partition@100000 { + label = "jffs"; + reg = <0x0100000 0x0100000>; + read-only; + }; + + partition@200000 { + label = "jffs2"; + reg = <0x0200000 0x0100000>; + read-only; + }; + + partition@300000 { + label = "firmware"; + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x4e474520>; + reg = <0x0300000 0x0e80000>; + }; + + partition@1180000 { + label = "runtime2"; + reg = <0x1180000 0x0e80000>; + read-only; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_3xx.dtsi b/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_3xx.dtsi new file mode 100644 index 0000000000..efb146a25a --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gigabit_3xx.dtsi @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit.dtsi" + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x00e0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0x00e0000 0x0010000>; + read-only; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0x00f0000 0x0010000>; + }; + + partition@100000 { + label = "jffs"; + reg = <0x0100000 0x0100000>; + read-only; + }; + + partition@200000 { + label = "jffs2"; + reg = <0x0200000 0x0100000>; + read-only; + }; + + partition@300000 { + label = "firmware"; + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x4e474335>; + reg = <0x0300000 0x0e80000>; + }; + + partition@1180000 { + label = "runtime2"; + reg = <0x1180000 0x0e80000>; + read-only; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gs108t-v3.dts b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs108t-v3.dts new file mode 100644 index 0000000000..b701e88d1a --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs108t-v3.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit_1xx.dtsi" + +/ { + compatible = "netgear,gs108t-v3", "realtek,rtl838x-soc"; + model = "Netgear GS108T v3"; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gs110tpp-v1.dts b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs110tpp-v1.dts new file mode 100644 index 0000000000..646f4ed516 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs110tpp-v1.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit_1xx.dtsi" + +/ { + compatible = "netgear,gs110tpp-v1", "realtek,rtl838x-soc"; + model = "Netgear GS110TPP v1"; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gs308t-v1.dts b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs308t-v1.dts new file mode 100644 index 0000000000..016ed8beb6 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs308t-v1.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit_3xx.dtsi" + +/ { + compatible = "netgear,gs308t-v1", "realtek,rtl838x-soc"; + model = "Netgear GS308T v1"; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_netgear_gs310tp-v1.dts b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs310tp-v1.dts new file mode 100644 index 0000000000..e3f59bde69 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_netgear_gs310tp-v1.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit_3xx.dtsi" + +/ { + compatible = "netgear,gs310tp-v1", "realtek,rtl838x-soc"; + model = "Netgear GS310TP v1"; + +}; + +&mdio { + INTERNAL_PHY(24) + INTERNAL_PHY(26) +}; + +&switch0 { + ports { + SWITCH_SFP_PORT(24, 9, rgmii-id) + SWITCH_SFP_PORT(26, 10, rgmii-id) + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-10hp.dts b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-10hp.dts new file mode 100644 index 0000000000..c16028788e --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-10hp.dts @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_zyxel_gs1900.dtsi" + +/ { + compatible = "zyxel,gs1900-10hp", "realtek,rtl838x-soc"; + model = "ZyXEL GS1900-10HP Switch"; + + /* i2c of the left SFP cage: port 9 */ + i2c0: i2c-gpio-0 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp0: sfp-p9 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + /* i2c of the right SFP cage: port 10 */ + i2c1: i2c-gpio-1 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp-p10 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>; + }; +}; + +&mdio { + INTERNAL_PHY(24) + INTERNAL_PHY(26) +}; + +&switch0 { + ports { + port@24 { + reg = <24>; + label = "lan9"; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp0>; + }; + + port@26 { + reg = <26>; + label = "lan10"; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp1>; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8.dts b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8.dts new file mode 100644 index 0000000000..e9c5efe603 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_zyxel_gs1900.dtsi" + +/ { + compatible = "zyxel,gs1900-8", "realtek,rtl838x-soc"; + model = "ZyXEL GS1900-8 Switch"; +}; + +&gpio1 { + /delete-node/ poe_enable; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v1.dts b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v1.dts new file mode 100644 index 0000000000..0d9b7c97c0 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v1.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_zyxel_gs1900.dtsi" + +/ { + compatible = "zyxel,gs1900-8hp-v1", "realtek,rtl838x-soc"; + model = "ZyXEL GS1900-8HP v1 Switch"; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v2.dts b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v2.dts new file mode 100644 index 0000000000..cdc4aed6d1 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900-8hp-v2.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_zyxel_gs1900.dtsi" + +/ { + compatible = "zyxel,gs1900-8hp-v2", "realtek,rtl838x-soc"; + model = "ZyXEL GS1900-8HP v2 Switch"; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900.dtsi b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900.dtsi new file mode 100644 index 0000000000..d61ac3b2b8 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8380_zyxel_gs1900.dtsi @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl838x.dtsi" + +#include +#include + +/ { + aliases { + led-boot = &led_sys; + led-failsafe = &led_sys; + led-running = &led_sys; + led-upgrade = &led_sys; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + gpio1: rtl8231-gpio { + status = "okay"; + + poe_enable { + gpio-hog; + gpios = <13 0>; + output-high; + }; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_sys: sys { + label = "green:sys"; + gpios = <&gpio0 47 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x40000>; + read-only; + }; + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + partition@50000 { + label = "u-boot-env2"; + reg = <0x50000 0x10000>; + }; + partition@60000 { + label = "jffs"; + reg = <0x60000 0x100000>; + }; + partition@160000 { + label = "jffs2"; + reg = <0x160000 0x100000>; + }; + partition@b260000 { + label = "firmware"; + reg = <0x260000 0x6d0000>; + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x83800000>; + }; + partition@930000 { + label = "runtime2"; + reg = <0x930000 0x6d0000>; + }; + }; + }; +}; + +ðernet0 { + mdio: mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(8, 1, internal) + SWITCH_PORT(9, 2, internal) + SWITCH_PORT(10, 3, internal) + SWITCH_PORT(11, 4, internal) + SWITCH_PORT(12, 5, internal) + SWITCH_PORT(13, 6, internal) + SWITCH_PORT(14, 7, internal) + SWITCH_PORT(15, 8, internal) + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_allnet_all-sg8208m.dts b/target/linux/realtek/dts-5.4/rtl8382_allnet_all-sg8208m.dts new file mode 100644 index 0000000000..fdcc01fdac --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_allnet_all-sg8208m.dts @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl838x.dtsi" + +#include +#include + +/ { + compatible = "allnet,all-sg8208m", "realtek,rtl838x-soc"; + model = "ALLNET ALL-SG8208M"; + + aliases { + led-boot = &led_sys; + led-failsafe = &led_sys; + led-running = &led_sys; + led-upgrade = &led_sys; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 67 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_sys: sys { + label = "green:sys"; + gpios = <&gpio0 47 GPIO_ACTIVE_HIGH>; + }; + // GPIO 25: power on/off all port leds + }; +}; + +&gpio0 { + indirect-access-bus-id = <0>; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "u-boot-env"; + reg = <0x80000 0x10000>; + read-only; + }; + + partition@90000 { + label = "u-boot-env2"; + reg = <0x90000 0x10000>; + }; + + partition@a0000 { + label = "jffs"; + reg = <0xa0000 0x100000>; + }; + + partition@1a0000 { + label = "jffs2"; + reg = <0x1a0000 0x100000>; + }; + + partition@2a0000 { + label = "firmware"; + reg = <0x2a0000 0xd60000>; + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x00000006>; + }; + }; + }; +}; + +ðernet0 { + mdio: mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(8, 1, internal) + SWITCH_PORT(9, 2, internal) + SWITCH_PORT(10, 3, internal) + SWITCH_PORT(11, 4, internal) + SWITCH_PORT(12, 5, internal) + SWITCH_PORT(13, 6, internal) + SWITCH_PORT(14, 7, internal) + SWITCH_PORT(15, 8, internal) + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-10p.dts b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-10p.dts new file mode 100644 index 0000000000..e2f5e7a4c0 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-10p.dts @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rtl838x.dtsi" + +#include +#include + +/ { + compatible = "d-link,dgs-1210-10p", "realtek,rtl838x-soc"; + model = "D-Link DGS-1210-10P"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + // GPIO 24 seems to provide power to the leds + label = "green:power"; + gpios = <&gpio0 47 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + mode { + label = "reset"; + gpios = <&gpio0 94 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + + +&gpio0 { + indirect-access-bus-id = <0>; +}; + +&spi0 { + status = "okay"; + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x00000000 0x80000>; + read-only; + }; + partition@80000 { + label = "u-boot-env"; + reg = <0x00080000 0x40000>; + read-only; + }; + partition@c0000 { + label = "u-boot-env2"; + reg = <0x000c0000 0x40000>; + }; + partition@280000 { + label = "firmware"; + compatible = "denx,uimage"; + reg = <0x00100000 0xd80000>; + }; + partition@be80000 { + label = "kernel2"; + reg = <0x00e80000 0x180000>; + }; + partition@1000000 { + label = "sysinfo"; + reg = <0x01000000 0x40000>; + }; + partition@1040000 { + label = "rootfs2"; + reg = <0x01040000 0xc00000>; + }; + partition@1c40000 { + label = "jffs2"; + reg = <0x01c40000 0x3c0000>; + }; + }; + }; +}; + +ðernet0 { + mdio: mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + INTERNAL_PHY(24) + INTERNAL_PHY(26) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(8, 1, internal) + SWITCH_PORT(9, 2, internal) + SWITCH_PORT(10, 3, internal) + SWITCH_PORT(11, 4, internal) + SWITCH_PORT(12, 5, internal) + SWITCH_PORT(13, 6, internal) + SWITCH_PORT(14, 7, internal) + SWITCH_PORT(15, 8, internal) + SWITCH_SFP_PORT(24, 9, rgmii-id) + SWITCH_SFP_PORT(26, 10, rgmii-id) + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-16.dts b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-16.dts new file mode 100644 index 0000000000..ac51185ed0 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-16.dts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rtl8382_d-link_dgs-1210.dtsi" + +/ { + compatible = "d-link,dgs-1210-16", "realtek,rtl838x-soc"; + model = "D-Link DGS-1210-16"; +}; + +ðernet0 { + mdio: mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + EXTERNAL_PHY(0) + EXTERNAL_PHY(1) + EXTERNAL_PHY(2) + EXTERNAL_PHY(3) + EXTERNAL_PHY(4) + EXTERNAL_PHY(5) + EXTERNAL_PHY(6) + EXTERNAL_PHY(7) + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + + EXTERNAL_SFP_PHY(24) + EXTERNAL_SFP_PHY(25) + EXTERNAL_SFP_PHY(26) + EXTERNAL_SFP_PHY(27) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(0, 1, qsgmii) + SWITCH_PORT(1, 2, qsgmii) + SWITCH_PORT(2, 3, qsgmii) + SWITCH_PORT(3, 4, qsgmii) + SWITCH_PORT(4, 5, qsgmii) + SWITCH_PORT(5, 6, qsgmii) + SWITCH_PORT(6, 7, qsgmii) + SWITCH_PORT(7, 8, qsgmii) + + SWITCH_PORT(8, 9, internal) + SWITCH_PORT(9, 10, internal) + SWITCH_PORT(10, 11, internal) + SWITCH_PORT(11, 12, internal) + SWITCH_PORT(12, 13, internal) + SWITCH_PORT(13, 14, internal) + SWITCH_PORT(14, 15, internal) + SWITCH_PORT(15, 16, internal) + + SWITCH_PORT(24, 17, qsgmii) + SWITCH_PORT(25, 18, qsgmii) + SWITCH_PORT(26, 19, qsgmii) + SWITCH_PORT(27, 20, qsgmii) + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-28.dts b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-28.dts new file mode 100644 index 0000000000..edd4fb140f --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210-28.dts @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rtl8382_d-link_dgs-1210.dtsi" + +/ { + compatible = "d-link,dgs-1210-28", "realtek,rtl838x-soc"; + model = "D-Link DGS-1210-28"; +}; + +ðernet0 { + mdio: mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + EXTERNAL_PHY(0) + EXTERNAL_PHY(1) + EXTERNAL_PHY(2) + EXTERNAL_PHY(3) + EXTERNAL_PHY(4) + EXTERNAL_PHY(5) + EXTERNAL_PHY(6) + EXTERNAL_PHY(7) + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + + EXTERNAL_PHY(16) + EXTERNAL_PHY(17) + EXTERNAL_PHY(18) + EXTERNAL_PHY(19) + EXTERNAL_PHY(20) + EXTERNAL_PHY(21) + EXTERNAL_PHY(22) + EXTERNAL_PHY(23) + + EXTERNAL_SFP_PHY(24) + EXTERNAL_SFP_PHY(25) + EXTERNAL_SFP_PHY(26) + EXTERNAL_SFP_PHY(27) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(0, 1, qsgmii) + SWITCH_PORT(1, 2, qsgmii) + SWITCH_PORT(2, 3, qsgmii) + SWITCH_PORT(3, 4, qsgmii) + SWITCH_PORT(4, 5, qsgmii) + SWITCH_PORT(5, 6, qsgmii) + SWITCH_PORT(6, 7, qsgmii) + SWITCH_PORT(7, 8, qsgmii) + + SWITCH_PORT(8, 9, internal) + SWITCH_PORT(9, 10, internal) + SWITCH_PORT(10, 11, internal) + SWITCH_PORT(11, 12, internal) + SWITCH_PORT(12, 13, internal) + SWITCH_PORT(13, 14, internal) + SWITCH_PORT(14, 15, internal) + SWITCH_PORT(15, 16, internal) + + SWITCH_PORT(16, 17, qsgmii) + SWITCH_PORT(17, 18, qsgmii) + SWITCH_PORT(18, 19, qsgmii) + SWITCH_PORT(19, 20, qsgmii) + SWITCH_PORT(20, 21, qsgmii) + SWITCH_PORT(21, 22, qsgmii) + SWITCH_PORT(22, 23, qsgmii) + SWITCH_PORT(23, 24, qsgmii) + + SWITCH_PORT(24, 25, qsgmii) + SWITCH_PORT(25, 26, qsgmii) + SWITCH_PORT(26, 27, qsgmii) + SWITCH_PORT(27, 28, qsgmii) + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210.dtsi b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210.dtsi new file mode 100644 index 0000000000..a14738c8a9 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_d-link_dgs-1210.dtsi @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rtl838x.dtsi" + +#include +#include + +/ { + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gpio0 { + indirect-access-bus-id = <0>; +}; + +&spi0 { + status = "okay"; + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x00000000 0x80000>; + read-only; + }; + partition@80000 { + label = "u-boot-env"; + reg = <0x00080000 0x40000>; + read-only; + }; + partition@c0000 { + label = "u-boot-env2"; + reg = <0x000c0000 0x40000>; + }; + partition@280000 { + label = "firmware"; + compatible = "denx,uimage"; + reg = <0x00100000 0xd80000>; + }; + partition@be80000 { + label = "kernel2"; + reg = <0x00e80000 0x180000>; + }; + partition@1000000 { + label = "sysinfo"; + reg = <0x01000000 0x40000>; + }; + partition@1040000 { + label = "rootfs2"; + reg = <0x01040000 0xc00000>; + }; + partition@1c40000 { + label = "jffs2"; + reg = <0x01c40000 0x3c0000>; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_inaba_aml2-17gp.dts b/target/linux/realtek/dts-5.4/rtl8382_inaba_aml2-17gp.dts new file mode 100644 index 0000000000..87761ac462 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_inaba_aml2-17gp.dts @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rtl838x.dtsi" + +#include +#include + +/ { + compatible = "inaba,aml2-17gp", "realtek,rtl838x-soc"; + model = "INABA Abaniact AML2-17GP"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&gpio0 { + indirect-access-bus-id = <0>; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "u-boot-env"; + reg = <0x80000 0x10000>; + read-only; + }; + + partition@90000 { + label = "u-boot-env2"; + reg = <0x90000 0x10000>; + }; + + partition@a0000 { + label = "jffs2_cfg"; + reg = <0xa0000 0x400000>; + read-only; + }; + + partition@4a0000 { + label = "jffs2_log"; + reg = <0x4a0000 0x100000>; + read-only; + }; + + partition@5a0000 { + compatible = "openwrt,uimage", "denx,uimage"; + label = "firmware"; + reg = <0x5a0000 0xd30000>; + openwrt,ih-magic = <0x83800000>; + }; + + partition@12d0000 { + label = "runtime2"; + reg = <0x12d0000 0xd30000>; + }; + }; + }; +}; + +ðernet0 { + mdio-bus { + compatible = "realtek,rtl838x-mdio"; + regmap = <ðernet0>; + #address-cells = <1>; + #size-cells = <0>; + + INTERNAL_PHY(8) + INTERNAL_PHY(9) + INTERNAL_PHY(10) + INTERNAL_PHY(11) + INTERNAL_PHY(12) + INTERNAL_PHY(13) + INTERNAL_PHY(14) + INTERNAL_PHY(15) + + EXTERNAL_PHY(16) + EXTERNAL_PHY(17) + EXTERNAL_PHY(18) + EXTERNAL_PHY(19) + EXTERNAL_PHY(20) + EXTERNAL_PHY(21) + EXTERNAL_PHY(22) + EXTERNAL_PHY(23) + + EXTERNAL_PHY(24) + }; +}; + +&switch0 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT(8, 1, internal) + SWITCH_PORT(9, 2, internal) + SWITCH_PORT(10, 3, internal) + SWITCH_PORT(11, 4, internal) + SWITCH_PORT(12, 5, internal) + SWITCH_PORT(13, 6, internal) + SWITCH_PORT(14, 7, internal) + SWITCH_PORT(15, 8, internal) + + SWITCH_PORT(16, 9, qsgmii) + SWITCH_PORT(17, 10, qsgmii) + SWITCH_PORT(18, 11, qsgmii) + SWITCH_PORT(19, 12, qsgmii) + SWITCH_PORT(20, 13, qsgmii) + SWITCH_PORT(21, 14, qsgmii) + SWITCH_PORT(22, 15, qsgmii) + SWITCH_PORT(23, 16, qsgmii) + + port@24 { + reg = <24>; + label = "wan"; + phy-handle = <&phy24>; + phy-mode = "qsgmii"; + }; + + port@28 { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl8382_zyxel_gs1900-24hp-v2.dts b/target/linux/realtek/dts-5.4/rtl8382_zyxel_gs1900-24hp-v2.dts new file mode 100644 index 0000000000..c16152521e --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl8382_zyxel_gs1900-24hp-v2.dts @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_zyxel_gs1900.dtsi" + +/ { + compatible = "zyxel,gs1900-24hp-v2", "realtek,rtl838x-soc"; + model = "ZyXEL GS1900-24HP v2 Switch"; + + /* i2c of the left SFP cage: port 25 */ + i2c0: i2c-gpio-0 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp0: sfp-p25 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + /* i2c of the right SFP cage: port 26 */ + i2c1: i2c-gpio-1 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp-p26 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>; + }; +}; + +&mdio { + EXTERNAL_PHY(0) + EXTERNAL_PHY(1) + EXTERNAL_PHY(2) + EXTERNAL_PHY(3) + EXTERNAL_PHY(4) + EXTERNAL_PHY(5) + EXTERNAL_PHY(6) + EXTERNAL_PHY(7) + + EXTERNAL_PHY(16) + EXTERNAL_PHY(17) + EXTERNAL_PHY(18) + EXTERNAL_PHY(19) + EXTERNAL_PHY(20) + EXTERNAL_PHY(21) + EXTERNAL_PHY(22) + EXTERNAL_PHY(23) + + INTERNAL_PHY(24) + INTERNAL_PHY(26) +}; + +&switch0 { + ports { + SWITCH_PORT(0, 1, qsgmii) + SWITCH_PORT(1, 2, qsgmii) + SWITCH_PORT(2, 3, qsgmii) + SWITCH_PORT(3, 4, qsgmii) + SWITCH_PORT(4, 5, qsgmii) + SWITCH_PORT(5, 6, qsgmii) + SWITCH_PORT(6, 7, qsgmii) + SWITCH_PORT(7, 8, qsgmii) + + SWITCH_PORT(8, 9, internal) + SWITCH_PORT(9, 10, internal) + SWITCH_PORT(10, 11, internal) + SWITCH_PORT(11, 12, internal) + SWITCH_PORT(12, 13, internal) + SWITCH_PORT(13, 14, internal) + SWITCH_PORT(14, 15, internal) + SWITCH_PORT(15, 16, internal) + + SWITCH_PORT(16, 17, qsgmii) + SWITCH_PORT(17, 18, qsgmii) + SWITCH_PORT(18, 19, qsgmii) + SWITCH_PORT(19, 20, qsgmii) + SWITCH_PORT(20, 21, qsgmii) + SWITCH_PORT(21, 22, qsgmii) + SWITCH_PORT(22, 23, qsgmii) + SWITCH_PORT(23, 24, qsgmii) + + + port@24 { + reg = <24>; + label = "lan25"; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp0>; + }; + + port@26 { + reg = <26>; + label = "lan26"; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp1>; + }; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl838x.dtsi b/target/linux/realtek/dts-5.4/rtl838x.dtsi new file mode 100644 index 0000000000..b59b141f66 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl838x.dtsi @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#define STRINGIZE(s) #s +#define LAN_LABEL(p, s) STRINGIZE(p ## s) +#define SWITCH_PORT_LABEL(n) LAN_LABEL(lan, n) + +#define INTERNAL_PHY(n) \ + phy##n: ethernet-phy@##n { \ + reg = <##n>; \ + compatible = "ethernet-phy-ieee802.3-c22"; \ + phy-is-integrated; \ + }; + +#define EXTERNAL_PHY(n) \ + phy##n: ethernet-phy@##n { \ + reg = <##n>; \ + compatible = "ethernet-phy-ieee802.3-c22"; \ + }; + +#define EXTERNAL_SFP_PHY(n) \ + phy##n: ethernet-phy@##n { \ + compatible = "ethernet-phy-ieee802.3-c22"; \ + sfp; \ + media = "fibre"; \ + reg = <##n>; \ + }; + +#define SWITCH_PORT(n, s, m) \ + port@##n { \ + reg = <##n>; \ + label = SWITCH_PORT_LABEL(s) ; \ + phy-handle = <&phy##n>; \ + phy-mode = #m ; \ + }; + +#define SWITCH_SFP_PORT(n, s, m) \ + port@##n { \ + reg = <##n>; \ + label = SWITCH_PORT_LABEL(s) ; \ + phy-handle = <&phy##n>; \ + phy-mode = #m ; \ + fixed-link { \ + speed = <1000>; \ + full-duplex; \ + }; \ + }; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "realtek,rtl838x-soc"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + frequency = <500000000>; + + cpu@0 { + compatible = "mips,mips4KEc"; + reg = <0>; + }; + }; + + chosen { + bootargs = "console=ttyS0,38400"; + }; + + cpuintc: cpuintc { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: rtlintc { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "realtek,rt8380-intc"; + reg = <0xb8003000 0x20>; + }; + + spi0: spi@b8001200 { + status = "okay"; + + compatible = "realtek,rtl838x-nor"; + reg = <0xb8001200 0x100>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + uart0: uart@b8002000 { + status = "okay"; + + compatible = "ns16550a"; + reg = <0xb8002000 0x100>; + + clock-frequency = <200000000>; + + interrupt-parent = <&intc>; + interrupts = <31>; + + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + }; + + uart1: uart@b8002100 { + pinctrl-names = "default"; + pinctrl-0 = <&enable_uart1>; + + status = "okay"; + + compatible = "ns16550a"; + reg = <0xb8002100 0x100>; + + clock-frequency = <200000000>; + + interrupt-parent = <&intc>; + interrupts = <30>; + + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + }; + + gpio0: gpio-controller@b8003500 { + compatible = "realtek,rtl838x-gpio"; + reg = <0xb8003500 0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <23>; + }; + + gpio1: rtl8231-gpio { + status = "disabled"; + compatible = "realtek,rtl8231-gpio"; + #gpio-cells = <2>; + indirect-access-bus-id = <0>; + gpio-controller; + }; + + pinmux: pinmux@bb001000 { + compatible = "pinctrl-single"; + reg = <0xbb001000 0x4>; + + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x1>; + #pinctrl-cells = <2>; + + enable_uart1: pinmux_enable_uart1 { + pinctrl-single,bits = <0x0 0x10 0x10>; + }; + }; + + ethernet0: ethernet@bb00a300 { + status = "okay"; + + compatible = "realtek,rtl838x-eth"; + reg = <0xbb00a300 0x100>; + interrupt-parent = <&intc>; + interrupts = <24>; + #interrupt-cells = <1>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + switch0: switch@bb000000 { + status = "okay"; + + interrupt-parent = <&intc>; + interrupts = <20>; + + compatible = "realtek,rtl83xx-switch"; + }; +}; diff --git a/target/linux/realtek/dts-5.4/rtl930x.dtsi b/target/linux/realtek/dts-5.4/rtl930x.dtsi new file mode 100644 index 0000000000..5d13fc31b3 --- /dev/null +++ b/target/linux/realtek/dts-5.4/rtl930x.dtsi @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#define STRINGIZE(s) #s +#define LAN_LABEL(p, s) STRINGIZE(p ## s) +#define SWITCH_PORT_LABEL(n) LAN_LABEL(lan, n) + +#define INTERNAL_PHY(n) \ + phy##n: ethernet-phy@##n { \ + reg = <##n>; \ + compatible = "ethernet-phy-ieee802.3-c22"; \ + phy-is-integrated; \ + }; + +#define EXTERNAL_PHY(n) \ + phy##n: ethernet-phy@##n { \ + reg = <##n>; \ + compatible = "ethernet-phy-ieee802.3-c22"; \ + }; + +#define EXTERNAL_SFP_PHY(n) \ + phy##n: ethernet-phy@##n { \ + compatible = "ethernet-phy-ieee802.3-c22"; \ + sfp; \ + media = "fibre"; \ + reg = <##n>; \ + }; + +#define SWITCH_PORT(n, s, m) \ + port@##n { \ + reg = <##n>; \ + label = SWITCH_PORT_LABEL(s) ; \ + phy-handle = <&phy##n>; \ + phy-mode = #m ; \ + }; + +#define SWITCH_SFP_PORT(n, s, m) \ + port@##n { \ + reg = <##n>; \ + label = SWITCH_PORT_LABEL(s) ; \ + phy-handle = <&phy##n>; \ + phy-mode = #m ; \ + fixed-link { \ + speed = <1000>; \ + full-duplex; \ + }; \ + }; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "realtek,rtl838x-soc"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + frequency = <800000000>; + + cpu@0 { + compatible = "mips,mips34Kc"; + reg = <0>; + }; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,38400"; + }; + + cpuintc: cpuintc { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: rtlintc { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "realtek,rt9300-intc"; + reg = <0xb8003000 0x20>; + }; + + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <175000000>; + clock-output-names = "osc"; + }; + + timer: timer@b8003200 { + compatible = "realtek,rtl9300-timer"; + reg = <0xb8003200 0x60>; + interrupt-parent = <&intc>; + interrupts = <8>; + interrupt-names = "ostimer"; + clocks = <&osc 0>; + }; + + spi0: spi@b8001200 { + status = "okay"; + + compatible = "realtek,rtl838x-nor"; + reg = <0xb8001200 0x100>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + uart0: uart@b8002000 { + compatible = "ns16550a"; + reg = <0xb8002000 0x100>; + + clock-frequency = <175000000>; + + interrupt-parent = <&intc>; + interrupts = <30>; + + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + + status = "okay"; + }; + + uart1: uart@b8002100 { + compatible = "ns16550a"; + reg = <0xb8002100 0x100>; + + clock-frequency = <175000000>; + + interrupt-parent = <&intc>; + interrupts = <31>; + + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + + status = "okay"; + }; + + gpio0: gpio-controller@b8003500 { + compatible = "realtek,rtl838x-gpio"; + reg = <0xb8003500 0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <31>; + }; + + ethernet0: ethernet@bb00a300 { + status = "okay"; + compatible = "realtek,rtl838x-eth"; + reg = <0xbb00a300 0x100>; + interrupt-parent = <&intc>; + interrupts = <24>; + #interrupt-cells = <1>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + switch0: switch@bb000000 { + status = "okay"; + + interrupt-parent = <&intc>; + interrupts = <20>; + + compatible = "realtek,rtl83xx-switch"; + }; +}; diff --git a/target/linux/realtek/image/Makefile b/target/linux/realtek/image/Makefile index 5900750797..5e4b4cde80 100644 --- a/target/linux/realtek/image/Makefile +++ b/target/linux/realtek/image/Makefile @@ -20,7 +20,7 @@ define Device/Default PROFILES = Default KERNEL := kernel-bin | append-dtb | gzip | uImage gzip KERNEL_INITRAMFS := kernel-bin | append-dtb | gzip | uImage gzip - DEVICE_DTS_DIR := ../dts + DEVICE_DTS_DIR := ../dts-$(KERNEL_PATCHVER) DEVICE_DTS = $$(SOC)_$(1) IMAGES := sysupgrade.bin IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | append-rootfs | pad-rootfs | \ From 1c020f8b439bf6439cb878e2888ed3dd1562b92e Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 11 Aug 2021 20:27:38 +0900 Subject: [PATCH 71/82] realtek: cleanup and update soc dtsi in 5.10 the following changes are included in this patch: - node is enabled by default, drop 'status = "okay"' - adjust order of "compatible" lines and "reg" lines - add a new blank line before fixed-link node in rtl830x.dtsi Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl838x.dtsi | 21 ++++++--------------- target/linux/realtek/dts-5.10/rtl930x.dtsi | 18 +++++------------- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi index b59b141f66..315d34ac0c 100644 --- a/target/linux/realtek/dts-5.10/rtl838x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi @@ -69,23 +69,21 @@ }; cpuintc: cpuintc { + compatible = "mti,cpu-interrupt-controller"; #address-cells = <0>; #interrupt-cells = <1>; interrupt-controller; - compatible = "mti,cpu-interrupt-controller"; }; intc: rtlintc { + compatible = "realtek,rt8380-intc"; + reg = <0xb8003000 0x20>; #address-cells = <0>; #interrupt-cells = <1>; interrupt-controller; - compatible = "realtek,rt8380-intc"; - reg = <0xb8003000 0x20>; }; spi0: spi@b8001200 { - status = "okay"; - compatible = "realtek,rtl838x-nor"; reg = <0xb8001200 0x100>; @@ -94,8 +92,6 @@ }; uart0: uart@b8002000 { - status = "okay"; - compatible = "ns16550a"; reg = <0xb8002000 0x100>; @@ -114,8 +110,6 @@ pinctrl-names = "default"; pinctrl-0 = <&enable_uart1>; - status = "okay"; - compatible = "ns16550a"; reg = <0xb8002100 0x100>; @@ -140,11 +134,12 @@ }; gpio1: rtl8231-gpio { - status = "disabled"; compatible = "realtek,rtl8231-gpio"; #gpio-cells = <2>; indirect-access-bus-id = <0>; gpio-controller; + + status = "disabled"; }; pinmux: pinmux@bb001000 { @@ -162,8 +157,6 @@ }; ethernet0: ethernet@bb00a300 { - status = "okay"; - compatible = "realtek,rtl838x-eth"; reg = <0xbb00a300 0x100>; interrupt-parent = <&intc>; @@ -178,11 +171,9 @@ }; switch0: switch@bb000000 { - status = "okay"; + compatible = "realtek,rtl83xx-switch"; interrupt-parent = <&intc>; interrupts = <20>; - - compatible = "realtek,rtl83xx-switch"; }; }; diff --git a/target/linux/realtek/dts-5.10/rtl930x.dtsi b/target/linux/realtek/dts-5.10/rtl930x.dtsi index 5d13fc31b3..ea89fd2584 100644 --- a/target/linux/realtek/dts-5.10/rtl930x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl930x.dtsi @@ -74,18 +74,18 @@ }; cpuintc: cpuintc { + compatible = "mti,cpu-interrupt-controller"; #address-cells = <0>; #interrupt-cells = <1>; interrupt-controller; - compatible = "mti,cpu-interrupt-controller"; }; intc: rtlintc { + compatible = "realtek,rt9300-intc"; + reg = <0xb8003000 0x20>; #address-cells = <0>; #interrupt-cells = <1>; interrupt-controller; - compatible = "realtek,rt9300-intc"; - reg = <0xb8003000 0x20>; }; osc: oscillator { @@ -105,8 +105,6 @@ }; spi0: spi@b8001200 { - status = "okay"; - compatible = "realtek,rtl838x-nor"; reg = <0xb8001200 0x100>; @@ -127,8 +125,6 @@ reg-shift = <2>; fifo-size = <1>; no-loopback-test; - - status = "okay"; }; uart1: uart@b8002100 { @@ -144,8 +140,6 @@ reg-shift = <2>; fifo-size = <1>; no-loopback-test; - - status = "okay"; }; gpio0: gpio-controller@b8003500 { @@ -158,13 +152,13 @@ }; ethernet0: ethernet@bb00a300 { - status = "okay"; compatible = "realtek,rtl838x-eth"; reg = <0xbb00a300 0x100>; interrupt-parent = <&intc>; interrupts = <24>; #interrupt-cells = <1>; phy-mode = "internal"; + fixed-link { speed = <1000>; full-duplex; @@ -172,11 +166,9 @@ }; switch0: switch@bb000000 { - status = "okay"; + compatible = "realtek,rtl83xx-switch"; interrupt-parent = <&intc>; interrupts = <20>; - - compatible = "realtek,rtl83xx-switch"; }; }; From ddaeb73de029d3d93200ff5758f2da89de0d30ce Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 6 May 2021 19:40:04 +0900 Subject: [PATCH 72/82] realtek: update soc dtsi in 5.10 for backported drivers this patch updates SoC dtsi (rtl838x.dtsi, rtl930x.dtsi) for the following backported drivers: - gpio-realtek-otto (5.13) - spi-realtek-rtl (5.12) - irq-realtek-rtl (5.12) And, disable SoC GPIO node (gpio0) in rtl930x.dtsi in dts-5.10. Currently, the upstreamed driver doesn't support the GPIO controller on RTL930x SoC. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl838x.dtsi | 22 ++++++++++++++++--- target/linux/realtek/dts-5.10/rtl930x.dtsi | 25 +++++++++++++++++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi index 315d34ac0c..1751c57e28 100644 --- a/target/linux/realtek/dts-5.10/rtl838x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi @@ -76,15 +76,30 @@ }; intc: rtlintc { - compatible = "realtek,rt8380-intc"; + compatible = "realtek,rtl-intc"; reg = <0xb8003000 0x20>; #address-cells = <0>; #interrupt-cells = <1>; interrupt-controller; + interrupt-map = + <31 &cpuintc 2>, /* UART0 */ + <30 &cpuintc 1>, /* UART1 */ + <29 &cpuintc 5>, /* TC0 */ + <28 &cpuintc 1>, /* TC1 */ + <27 &cpuintc 1>, /* OCPTO */ + <26 &cpuintc 1>, /* HLXTO */ + <25 &cpuintc 1>, /* SLXTO */ + <24 &cpuintc 4>, /* NIC */ + <23 &cpuintc 4>, /* GPIO_ABCD */ + <22 &cpuintc 4>, /* GPIO_EFGH */ + <21 &cpuintc 4>, /* RTC */ + <20 &cpuintc 3>, /* SWCORE */ + <19 &cpuintc 4>, /* WDT_IP1 */ + <18 &cpuintc 5>; /* WDT_IP2 */ }; spi0: spi@b8001200 { - compatible = "realtek,rtl838x-nor"; + compatible = "realtek,rtl8380-spi"; reg = <0xb8001200 0x100>; #address-cells = <1>; @@ -125,10 +140,11 @@ }; gpio0: gpio-controller@b8003500 { - compatible = "realtek,rtl838x-gpio"; + compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; reg = <0xb8003500 0x20>; gpio-controller; #gpio-cells = <2>; + ngpios = <24>; interrupt-parent = <&intc>; interrupts = <23>; }; diff --git a/target/linux/realtek/dts-5.10/rtl930x.dtsi b/target/linux/realtek/dts-5.10/rtl930x.dtsi index ea89fd2584..c0cb53af08 100644 --- a/target/linux/realtek/dts-5.10/rtl930x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl930x.dtsi @@ -81,11 +81,23 @@ }; intc: rtlintc { - compatible = "realtek,rt9300-intc"; + compatible = "realtek,rtl-intc"; reg = <0xb8003000 0x20>; #address-cells = <0>; #interrupt-cells = <1>; interrupt-controller; + interrupt-map = + <31 &cpuintc 1>, /* UART1 */ + <30 &cpuintc 2>, /* UART0 */ + <28 &cpuintc 1>, /* USB_H2 */ + <24 &cpuintc 4>, /* NIC */ + <23 &cpuintc 3>, /* SWCORE */ + <13 &cpuintc 4>, /* GPIO_ABCD */ + <11 &cpuintc 1>, /* TC4 */ + <10 &cpuintc 1>, /* TC3 */ + <9 &cpuintc 1>, /* TC2 */ + <8 &cpuintc 1>, /* TC1 */ + <7 &cpuintc 5>; /* TC0 */ }; osc: oscillator { @@ -105,7 +117,7 @@ }; spi0: spi@b8001200 { - compatible = "realtek,rtl838x-nor"; + compatible = "realtek,rtl8380-spi"; reg = <0xb8001200 0x100>; #address-cells = <1>; @@ -143,12 +155,19 @@ }; gpio0: gpio-controller@b8003500 { - compatible = "realtek,rtl838x-gpio"; + compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; reg = <0xb8003500 0x20>; gpio-controller; #gpio-cells = <2>; + ngpios = <32>; interrupt-parent = <&intc>; interrupts = <31>; + + /* + * currently, RTL930x GPIO is not supported in + * upstreamed driver (gpio-realtek-otto) + */ + status = "disabled"; }; ethernet0: ethernet@bb00a300 { From 3069fffe60941d0848a8e7917132506bd6fa0b6d Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 6 May 2021 20:46:42 +0900 Subject: [PATCH 73/82] realtek: add "soc" node to soc dtsi in dts-5.10 Add a "soc" node as a simple-bus to rtl838x.dtsi and rtl930x.dtsi. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl838x.dtsi | 131 +++++++++--------- target/linux/realtek/dts-5.10/rtl930x.dtsi | 149 +++++++++++---------- 2 files changed, 149 insertions(+), 131 deletions(-) diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi index 1751c57e28..f5903ec174 100644 --- a/target/linux/realtek/dts-5.10/rtl838x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi @@ -75,78 +75,87 @@ interrupt-controller; }; - intc: rtlintc { - compatible = "realtek,rtl-intc"; - reg = <0xb8003000 0x20>; - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - interrupt-map = - <31 &cpuintc 2>, /* UART0 */ - <30 &cpuintc 1>, /* UART1 */ - <29 &cpuintc 5>, /* TC0 */ - <28 &cpuintc 1>, /* TC1 */ - <27 &cpuintc 1>, /* OCPTO */ - <26 &cpuintc 1>, /* HLXTO */ - <25 &cpuintc 1>, /* SLXTO */ - <24 &cpuintc 4>, /* NIC */ - <23 &cpuintc 4>, /* GPIO_ABCD */ - <22 &cpuintc 4>, /* GPIO_EFGH */ - <21 &cpuintc 4>, /* RTC */ - <20 &cpuintc 3>, /* SWCORE */ - <19 &cpuintc 4>, /* WDT_IP1 */ - <18 &cpuintc 5>; /* WDT_IP2 */ - }; - - spi0: spi@b8001200 { - compatible = "realtek,rtl8380-spi"; - reg = <0xb8001200 0x100>; - + soc: soc { + compatible = "simple-bus"; #address-cells = <1>; - #size-cells = <0>; - }; + #size-cells = <1>; + ranges = <0x0 0xb8000000 0x10000>; - uart0: uart@b8002000 { - compatible = "ns16550a"; - reg = <0xb8002000 0x100>; + intc: rtlintc@3000 { + compatible = "realtek,rtl-intc"; + reg = <0x3000 0x20>; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + interrupt-map = + <31 &cpuintc 2>, /* UART0 */ + <30 &cpuintc 1>, /* UART1 */ + <29 &cpuintc 5>, /* TC0 */ + <28 &cpuintc 1>, /* TC1 */ + <27 &cpuintc 1>, /* OCPTO */ + <26 &cpuintc 1>, /* HLXTO */ + <25 &cpuintc 1>, /* SLXTO */ + <24 &cpuintc 4>, /* NIC */ + <23 &cpuintc 4>, /* GPIO_ABCD */ + <22 &cpuintc 4>, /* GPIO_EFGH */ + <21 &cpuintc 4>, /* RTC */ + <20 &cpuintc 3>, /* SWCORE */ + <19 &cpuintc 4>, /* WDT_IP1 */ + <18 &cpuintc 5>; /* WDT_IP2 */ + }; - clock-frequency = <200000000>; + spi0: spi@1200 { + compatible = "realtek,rtl8380-spi"; + reg = <0x1200 0x100>; - interrupt-parent = <&intc>; - interrupts = <31>; + #address-cells = <1>; + #size-cells = <0>; + }; - reg-io-width = <1>; - reg-shift = <2>; - fifo-size = <1>; - no-loopback-test; - }; + uart0: uart@2000 { + compatible = "ns16550a"; + reg = <0x2000 0x100>; - uart1: uart@b8002100 { - pinctrl-names = "default"; - pinctrl-0 = <&enable_uart1>; + clock-frequency = <200000000>; - compatible = "ns16550a"; - reg = <0xb8002100 0x100>; + interrupt-parent = <&intc>; + interrupts = <31>; - clock-frequency = <200000000>; + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + }; - interrupt-parent = <&intc>; - interrupts = <30>; + uart1: uart@2100 { + pinctrl-names = "default"; + pinctrl-0 = <&enable_uart1>; - reg-io-width = <1>; - reg-shift = <2>; - fifo-size = <1>; - no-loopback-test; - }; + compatible = "ns16550a"; + reg = <0x2100 0x100>; - gpio0: gpio-controller@b8003500 { - compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; - reg = <0xb8003500 0x20>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <24>; - interrupt-parent = <&intc>; - interrupts = <23>; + clock-frequency = <200000000>; + + interrupt-parent = <&intc>; + interrupts = <30>; + + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + + status = "disabled"; + }; + + gpio0: gpio-controller@3500 { + compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; + reg = <0x3500 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <24>; + interrupt-parent = <&intc>; + interrupts = <23>; + }; }; gpio1: rtl8231-gpio { diff --git a/target/linux/realtek/dts-5.10/rtl930x.dtsi b/target/linux/realtek/dts-5.10/rtl930x.dtsi index c0cb53af08..d01307a35d 100644 --- a/target/linux/realtek/dts-5.10/rtl930x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl930x.dtsi @@ -80,26 +80,6 @@ interrupt-controller; }; - intc: rtlintc { - compatible = "realtek,rtl-intc"; - reg = <0xb8003000 0x20>; - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - interrupt-map = - <31 &cpuintc 1>, /* UART1 */ - <30 &cpuintc 2>, /* UART0 */ - <28 &cpuintc 1>, /* USB_H2 */ - <24 &cpuintc 4>, /* NIC */ - <23 &cpuintc 3>, /* SWCORE */ - <13 &cpuintc 4>, /* GPIO_ABCD */ - <11 &cpuintc 1>, /* TC4 */ - <10 &cpuintc 1>, /* TC3 */ - <9 &cpuintc 1>, /* TC2 */ - <8 &cpuintc 1>, /* TC1 */ - <7 &cpuintc 5>; /* TC0 */ - }; - osc: oscillator { compatible = "fixed-clock"; #clock-cells = <1>; @@ -107,67 +87,96 @@ clock-output-names = "osc"; }; - timer: timer@b8003200 { - compatible = "realtek,rtl9300-timer"; - reg = <0xb8003200 0x60>; - interrupt-parent = <&intc>; - interrupts = <8>; - interrupt-names = "ostimer"; - clocks = <&osc 0>; - }; - - spi0: spi@b8001200 { - compatible = "realtek,rtl8380-spi"; - reg = <0xb8001200 0x100>; - + soc: soc { + compatible = "simple-bus"; #address-cells = <1>; - #size-cells = <0>; - }; + #size-cells = <1>; + ranges = <0x0 0xb8000000 0x10000>; - uart0: uart@b8002000 { - compatible = "ns16550a"; - reg = <0xb8002000 0x100>; + intc: rtlintc@3000 { + compatible = "realtek,rtl-intc"; + reg = <0x3000 0x20>; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + interrupt-map = + <31 &cpuintc 1>, /* UART1 */ + <30 &cpuintc 2>, /* UART0 */ + <28 &cpuintc 1>, /* USB_H2 */ + <24 &cpuintc 4>, /* NIC */ + <23 &cpuintc 3>, /* SWCORE */ + <13 &cpuintc 4>, /* GPIO_ABCD */ + <11 &cpuintc 1>, /* TC4 */ + <10 &cpuintc 1>, /* TC3 */ + <9 &cpuintc 1>, /* TC2 */ + <8 &cpuintc 1>, /* TC1 */ + <7 &cpuintc 5>; /* TC0 */ + }; - clock-frequency = <175000000>; + timer: timer@3200 { + compatible = "realtek,rtl9300-timer"; + reg = <0x3200 0x60>; + interrupt-parent = <&intc>; + interrupts = <8>; + interrupt-names = "ostimer"; + clocks = <&osc 0>; + }; - interrupt-parent = <&intc>; - interrupts = <30>; + spi0: spi@1200 { + compatible = "realtek,rtl8380-spi"; + reg = <0x1200 0x100>; - reg-io-width = <1>; - reg-shift = <2>; - fifo-size = <1>; - no-loopback-test; - }; + #address-cells = <1>; + #size-cells = <0>; + }; - uart1: uart@b8002100 { - compatible = "ns16550a"; - reg = <0xb8002100 0x100>; + uart0: uart@2000 { + compatible = "ns16550a"; + reg = <0x2000 0x100>; - clock-frequency = <175000000>; + clock-frequency = <175000000>; - interrupt-parent = <&intc>; - interrupts = <31>; + interrupt-parent = <&intc>; + interrupts = <30>; - reg-io-width = <1>; - reg-shift = <2>; - fifo-size = <1>; - no-loopback-test; - }; + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + }; - gpio0: gpio-controller@b8003500 { - compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; - reg = <0xb8003500 0x20>; - gpio-controller; - #gpio-cells = <2>; - ngpios = <32>; - interrupt-parent = <&intc>; - interrupts = <31>; + uart1: uart@2100 { + compatible = "ns16550a"; + reg = <0x2100 0x100>; - /* - * currently, RTL930x GPIO is not supported in - * upstreamed driver (gpio-realtek-otto) - */ - status = "disabled"; + clock-frequency = <175000000>; + + interrupt-parent = <&intc>; + interrupts = <31>; + + reg-io-width = <1>; + reg-shift = <2>; + fifo-size = <1>; + no-loopback-test; + + status = "disabled"; + }; + + gpio0: gpio-controller@3500 { + compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio"; + reg = <0x3500 0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + interrupt-parent = <&intc>; + interrupts = <31>; + + /* + * currently, RTL930x GPIO is not supported in + * upstreamed driver (gpio-realtek-otto) + */ + status = "disabled"; + }; }; ethernet0: ethernet@bb00a300 { From 9a4b8d6c306cef4dcdb442d541aaff6e3761da53 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Thu, 6 May 2021 23:22:19 +0900 Subject: [PATCH 74/82] realtek: fix compile errors in rtl838x_eth.c for 5.10 this patch fixes the following errors when compiling: - "unsigned int txqueue" is added as an additional parameter of ndo_tx_timeout in net_device_ops (include/linux/netdevice.h) - "mac_link_state" in phylink_mac_ops (include/linux/phylink.h) is renamed to "mac_pcs_get_state" and changed the return value to void from int - several parameters are added to "mac_link_up" in phylink_mac_ops (include/linux/phylink.h) and the order of the parameters is changed added: - int speed - int duplex - bool tx_pause - bool rx_pause - a parameter "phy_interface_t *interface" is added to of_get_phy_mode (drivers/of/of_net.c) and returns the state instead of phy mode Signed-off-by: INAGAKI Hiroshi --- .../drivers/net/ethernet/rtl838x_eth.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index 3f98e3bf81..ce3574b902 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -1094,7 +1094,7 @@ static void rtl931x_eth_set_multicast_list(struct net_device *ndev) } } -static void rtl838x_eth_tx_timeout(struct net_device *ndev) +static void rtl838x_eth_tx_timeout(struct net_device *ndev, unsigned int txqueue) { unsigned long flags; struct rtl838x_eth_priv *priv = netdev_priv(ndev); @@ -1436,7 +1436,7 @@ static void rtl838x_mac_an_restart(struct phylink_config *config) sw_w32(0x6192F, priv->r->mac_force_mode_ctrl + priv->cpu_port * 4); } -static int rtl838x_mac_pcs_get_state(struct phylink_config *config, +static void rtl838x_mac_pcs_get_state(struct phylink_config *config, struct phylink_link_state *state) { u32 speed; @@ -1470,8 +1470,6 @@ static int rtl838x_mac_pcs_get_state(struct phylink_config *config, state->pause |= MLO_PAUSE_RX; if (priv->r->get_mac_tx_pause_sts(port)) state->pause |= MLO_PAUSE_TX; - - return 1; } static void rtl838x_mac_link_down(struct phylink_config *config, @@ -1486,9 +1484,10 @@ static void rtl838x_mac_link_down(struct phylink_config *config, sw_w32_mask(0x03, 0, priv->r->mac_port_ctrl(priv->cpu_port)); } -static void rtl838x_mac_link_up(struct phylink_config *config, unsigned int mode, - phy_interface_t interface, - struct phy_device *phy) +static void rtl838x_mac_link_up(struct phylink_config *config, + struct phy_device *phy, unsigned int mode, + phy_interface_t interface, int speed, int duplex, + bool tx_pause, bool rx_pause) { struct net_device *dev = container_of(config->dev, struct net_device, dev); struct rtl838x_eth_priv *priv = netdev_priv(dev); @@ -1950,7 +1949,7 @@ static const struct net_device_ops rtl931x_eth_netdev_ops = { static const struct phylink_mac_ops rtl838x_phylink_ops = { .validate = rtl838x_validate, - .mac_link_state = rtl838x_mac_pcs_get_state, + .mac_pcs_get_state = rtl838x_mac_pcs_get_state, .mac_an_restart = rtl838x_mac_an_restart, .mac_config = rtl838x_mac_config, .mac_link_down = rtl838x_mac_link_down, @@ -2131,8 +2130,9 @@ static int __init rtl838x_eth_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - phy_mode = of_get_phy_mode(dn); - if (phy_mode < 0) { + phy_mode = PHY_INTERFACE_MODE_NA; + err = of_get_phy_mode(dn, &phy_mode); + if (err < 0) { dev_err(&pdev->dev, "incorrect phy-mode\n"); err = -EINVAL; goto err_free; From a22602728c02e380ef4496b833271d5c760fe46f Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Fri, 7 May 2021 00:38:22 +0900 Subject: [PATCH 75/82] realtek: fix compile errors in dsa driver for 5.10 this patch fixes the following errors when compiling: - dsa_switch_alloc is removed[1] - a parameter "enum dsa_tag_protocol mprot" is added to dsa_tag_protocol in dsa_switch_ops (include/net/dsa.h) - several paramters are added to "phylink_mac_link_up" in dsa_switch_ops (include/net/dsa.h) added: - int speed - int duplex - bool tx_pause - bool rx_pause - a parameter "struct switchdev_trans *trans" is added to port_vlan_filtering in dsa_switch_ops (include/net/dsa.h) [1]: https://lore.kernel.org/lkml/20191020031941.3805884-17-vivien.didelot@gmail.com/ Signed-off-by: INAGAKI Hiroshi --- .../files-5.10/drivers/net/dsa/rtl83xx/common.c | 2 +- .../realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) 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 a380906b92..ad69debcc8 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 @@ -546,7 +546,7 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->ds = dsa_switch_alloc(dev, DSA_MAX_PORTS); + priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); if (!priv->ds) return -ENOMEM; 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 c2a230c4cb..6c0ed5ae00 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 @@ -101,7 +101,9 @@ const struct rtl83xx_mib_desc rtl83xx_mib[] = { /* DSA callbacks */ -static enum dsa_tag_protocol rtl83xx_get_tag_protocol(struct dsa_switch *ds, int port) +static enum dsa_tag_protocol rtl83xx_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mprot) { /* The switch does not tag the frames, instead internally the header * structure for each packet is tagged accordingly. @@ -474,7 +476,9 @@ static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port, static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface, - struct phy_device *phydev) + struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) { struct rtl838x_switch_priv *priv = ds->priv; /* Restart TX/RX to port */ @@ -824,7 +828,8 @@ void rtl930x_fast_age(struct dsa_switch *ds, int port) } static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port, - bool vlan_filtering) + bool vlan_filtering, + struct switchdev_trans *trans) { struct rtl838x_switch_priv *priv = ds->priv; From 99a658cb71e474abf73ec77aa99b30b7eb2001a3 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Fri, 7 May 2021 12:10:10 +0900 Subject: [PATCH 76/82] realtek: add pinmux node of LED_GLB_CTRL to rtl838x.dtsi in dts-5.10 This patch adds a pinctrl-single pinmux node to allow disabling system LED and enabling GPIO 0 (old driver: GPIO 24). Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl838x.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi index f5903ec174..f2824cdceb 100644 --- a/target/linux/realtek/dts-5.10/rtl838x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi @@ -181,6 +181,22 @@ }; }; + /* LED_GLB_CTRL */ + pinmux_led: pinmux@bb00a000 { + compatible = "pinctrl-single"; + reg = <0xbb00a000 0x4>; + + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x1>; + #pinctrl-cells = <2>; + + /* enable GPIO 0 */ + pinmux_disable_sys_led: disable_sys_led { + pinctrl-single,bits = <0x0 0x0 0x8000>; + }; + }; + ethernet0: ethernet@bb00a300 { compatible = "realtek,rtl838x-eth"; reg = <0xbb00a300 0x100>; From 2e676c05dccc7d5c5cf4ab118f479471be52194a Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 8 May 2021 17:28:58 +0900 Subject: [PATCH 77/82] realtek: fix kernel panic in DSA driver for 5.10 dsa_to_port function in 5.10 returns dsa_port from the port list in dsa_switch_tree, but the tree is built when the switch is registered by dsa_register_switch and it's null in rtl83xx_mdio_probe. So, we need to use dsa_to_port after the registration of the switch. Signed-off-by: INAGAKI Hiroshi --- .../files-5.10/drivers/net/dsa/rtl83xx/common.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) 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 ad69debcc8..25ac2d4679 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 @@ -302,8 +302,6 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) if (of_property_read_u32(dn, "reg", &pn)) continue; - priv->ports[pn].dp = dsa_to_port(priv->ds, pn); - // Check for the integrated SerDes of the RTL8380M first if (of_property_read_bool(dn, "phy-is-integrated") && priv->id == 0x8380 && pn >= 24) { @@ -627,6 +625,14 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) return err; } + /* + * dsa_to_port returns dsa_port from the port list in + * dsa_switch_tree, the tree is built when the switch + * is registered by dsa_register_switch + */ + for (i = 0; i <= priv->cpu_port; i++) + priv->ports[i].dp = dsa_to_port(priv->ds, i); + /* Enable link and media change interrupts. Are the SERDES masks needed? */ sw_w32_mask(0, 3, priv->r->isr_glb_src); From 61a3d0075b151f6742862e123fdff1897d876176 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 8 May 2021 17:51:29 +0900 Subject: [PATCH 78/82] realtek: update GPIO bindings in the dts files in dts-5.10 this patch includes the following changes: - adjust mapping for the new driver - GPIO 24 -> GPIO 0 - GPIO 47 -> GPIO 0 (+ disabling system LED) - disable pins in the invalid range (out of the range 0-31 of the new driver) - are these pins on the external RTL8231 (&gpio1)? - GPIO 67 (-> GPIO 3 on &gpio1?) - GPIO 94 (-> GPIO 30 on &gpio1?) - drop "indirect-access-bus-id" property from gpio0 node in device dts files Signed-off-by: INAGAKI Hiroshi --- .../dts-5.10/rtl8380_netgear_gigabit.dtsi | 2 +- .../dts-5.10/rtl8380_zyxel_gs1900.dtsi | 24 ++++++++++--------- .../dts-5.10/rtl8382_allnet_all-sg8208m.dts | 13 +++++----- .../dts-5.10/rtl8382_d-link_dgs-1210-10p.dts | 15 ++++++------ .../dts-5.10/rtl8382_d-link_dgs-1210.dtsi | 2 +- .../dts-5.10/rtl8382_inaba_aml2-17gp.dts | 6 +---- 6 files changed, 29 insertions(+), 33 deletions(-) diff --git a/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi index 8ba66d6023..9cde00517e 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi +++ b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi @@ -23,7 +23,7 @@ mode { label = "reset"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900.dtsi b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900.dtsi index d61ac3b2b8..7233f6086c 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900.dtsi +++ b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900.dtsi @@ -22,16 +22,6 @@ reg = <0x0 0x8000000>; }; - gpio1: rtl8231-gpio { - status = "okay"; - - poe_enable { - gpio-hog; - gpios = <13 0>; - output-high; - }; - }; - keys { compatible = "gpio-keys-polled"; poll-interval = <20>; @@ -44,15 +34,27 @@ }; leds { + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_disable_sys_led>; compatible = "gpio-leds"; led_sys: sys { label = "green:sys"; - gpios = <&gpio0 47 GPIO_ACTIVE_HIGH>; + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; }; }; }; +&gpio1 { + status = "okay"; + + poe_enable { + gpio-hog; + gpios = <13 0>; + output-high; + }; +}; + &spi0 { status = "okay"; diff --git a/target/linux/realtek/dts-5.10/rtl8382_allnet_all-sg8208m.dts b/target/linux/realtek/dts-5.10/rtl8382_allnet_all-sg8208m.dts index fdcc01fdac..f4ca1686dd 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_allnet_all-sg8208m.dts +++ b/target/linux/realtek/dts-5.10/rtl8382_allnet_all-sg8208m.dts @@ -29,28 +29,27 @@ compatible = "gpio-keys-polled"; poll-interval = <20>; - reset { + /* is this pin 3 on the external RTL8231 (&gpio1)? */ + /*reset { label = "reset"; gpios = <&gpio0 67 GPIO_ACTIVE_LOW>; linux,code = ; - }; + };*/ }; leds { + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_disable_sys_led>; compatible = "gpio-leds"; led_sys: sys { label = "green:sys"; - gpios = <&gpio0 47 GPIO_ACTIVE_HIGH>; + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; }; // GPIO 25: power on/off all port leds }; }; -&gpio0 { - indirect-access-bus-id = <0>; -}; - &spi0 { status = "okay"; diff --git a/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts index e2f5e7a4c0..f347660283 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts +++ b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts @@ -26,12 +26,14 @@ }; leds { + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_disable_sys_led>; compatible = "gpio-leds"; led_power: power { - // GPIO 24 seems to provide power to the leds + // GPIO 0 seems to provide power to the leds label = "green:power"; - gpios = <&gpio0 47 GPIO_ACTIVE_LOW>; + gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; }; }; @@ -39,19 +41,16 @@ compatible = "gpio-keys-polled"; poll-interval = <20>; - mode { + /* is this pin 30 on the external RTL8231 (&gpio1)? */ + /*mode { label = "reset"; gpios = <&gpio0 94 GPIO_ACTIVE_LOW>; linux,code = ; - }; + };*/ }; }; -&gpio0 { - indirect-access-bus-id = <0>; -}; - &spi0 { status = "okay"; flash@0 { diff --git a/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210.dtsi b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210.dtsi index a14738c8a9..a4811dbf30 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210.dtsi +++ b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210.dtsi @@ -27,7 +27,7 @@ led_power: power { label = "green:power"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; }; }; }; diff --git a/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts b/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts index 87761ac462..a9af1d44f5 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts +++ b/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts @@ -24,16 +24,12 @@ reset { label = "reset"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; linux,code = ; }; }; }; -&gpio0 { - indirect-access-bus-id = <0>; -}; - &spi0 { status = "okay"; From d7b349db7cbadae3a9e11f1d2f375c037f6adb3b Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 26 Jun 2021 12:29:24 +0900 Subject: [PATCH 79/82] realtek: use gpio-keys instead of "-polled" if SoC GPIO is used in 5.10 The new backported GPIO driver supports interrupt, so use gpio-keys instead of gpio-keys-polled for keys connected to the internal GPIO controller. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi | 3 +-- target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi index 9cde00517e..e98a9bfc61 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi +++ b/target/linux/realtek/dts-5.10/rtl8380_netgear_gigabit.dtsi @@ -18,8 +18,7 @@ }; keys { - compatible = "gpio-keys-polled"; - poll-interval = <20>; + compatible = "gpio-keys"; mode { label = "reset"; diff --git a/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts b/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts index a9af1d44f5..1dc9e272fe 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts +++ b/target/linux/realtek/dts-5.10/rtl8382_inaba_aml2-17gp.dts @@ -19,8 +19,7 @@ }; keys { - compatible = "gpio-keys-polled"; - poll-interval = <20>; + compatible = "gpio-keys"; reset { label = "reset"; From 45b2a5d840590fb9b8a4c64fba4deca51a2b0b65 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 11 Aug 2021 19:06:09 +0900 Subject: [PATCH 80/82] realtek: use physical addresses in soc dtsi in 5.10 Use physical addresses instead of virtual address in dts files. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl838x.dtsi | 16 ++++++++-------- target/linux/realtek/dts-5.10/rtl930x.dtsi | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi index f2824cdceb..a72addcf36 100644 --- a/target/linux/realtek/dts-5.10/rtl838x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi @@ -79,7 +79,7 @@ compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0xb8000000 0x10000>; + ranges = <0x0 0x18000000 0x10000>; intc: rtlintc@3000 { compatible = "realtek,rtl-intc"; @@ -167,9 +167,9 @@ status = "disabled"; }; - pinmux: pinmux@bb001000 { + pinmux: pinmux@1b001000 { compatible = "pinctrl-single"; - reg = <0xbb001000 0x4>; + reg = <0x1b001000 0x4>; pinctrl-single,bit-per-mux; pinctrl-single,register-width = <32>; @@ -182,9 +182,9 @@ }; /* LED_GLB_CTRL */ - pinmux_led: pinmux@bb00a000 { + pinmux_led: pinmux@1b00a000 { compatible = "pinctrl-single"; - reg = <0xbb00a000 0x4>; + reg = <0x1b00a000 0x4>; pinctrl-single,bit-per-mux; pinctrl-single,register-width = <32>; @@ -197,9 +197,9 @@ }; }; - ethernet0: ethernet@bb00a300 { + ethernet0: ethernet@1b00a300 { compatible = "realtek,rtl838x-eth"; - reg = <0xbb00a300 0x100>; + reg = <0x1b00a300 0x100>; interrupt-parent = <&intc>; interrupts = <24>; #interrupt-cells = <1>; @@ -211,7 +211,7 @@ }; }; - switch0: switch@bb000000 { + switch0: switch@1b000000 { compatible = "realtek,rtl83xx-switch"; interrupt-parent = <&intc>; diff --git a/target/linux/realtek/dts-5.10/rtl930x.dtsi b/target/linux/realtek/dts-5.10/rtl930x.dtsi index d01307a35d..e78e9ebeb8 100644 --- a/target/linux/realtek/dts-5.10/rtl930x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl930x.dtsi @@ -91,7 +91,7 @@ compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0xb8000000 0x10000>; + ranges = <0x0 0x18000000 0x10000>; intc: rtlintc@3000 { compatible = "realtek,rtl-intc"; @@ -179,9 +179,9 @@ }; }; - ethernet0: ethernet@bb00a300 { + ethernet0: ethernet@1b00a300 { compatible = "realtek,rtl838x-eth"; - reg = <0xbb00a300 0x100>; + reg = <0x1b00a300 0x100>; interrupt-parent = <&intc>; interrupts = <24>; #interrupt-cells = <1>; @@ -193,7 +193,7 @@ }; }; - switch0: switch@bb000000 { + switch0: switch@1b000000 { compatible = "realtek,rtl83xx-switch"; interrupt-parent = <&intc>; From 216011e424cf438c3bb68e641139b8b720d93a87 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Mon, 23 Aug 2021 18:07:05 +0900 Subject: [PATCH 81/82] realtek: enable uart1 on the devices with PoE support in 5.10 On the devices with PoE support, the secondary UART (uart1) on the SoC is used to communicate between the SoC and controller. Enable the secondary UART on the following devices: - D-Link DGS-1210-10P - Netgear GS110TPP v1 - Netgear GS310TP v1 - ZyXEL GS1900-8HP v1/v2 - ZyXEL GS1900-10HP - ZyXEL GS1900-24HP v2 Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts | 4 ++++ target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts | 4 ++++ target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts | 4 ++++ target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts | 4 ++++ target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts | 4 ++++ target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts | 4 ++++ .../linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts index 646f4ed516..8382d35a9d 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts +++ b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs110tpp-v1.dts @@ -6,3 +6,7 @@ compatible = "netgear,gs110tpp-v1", "realtek,rtl838x-soc"; model = "Netgear GS110TPP v1"; }; + +&uart1 { + status = "okay"; +}; diff --git a/target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts index e3f59bde69..dacd504ac4 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts +++ b/target/linux/realtek/dts-5.10/rtl8380_netgear_gs310tp-v1.dts @@ -8,6 +8,10 @@ }; +&uart1 { + status = "okay"; +}; + &mdio { INTERNAL_PHY(24) INTERNAL_PHY(26) diff --git a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts index c16028788e..82df6789a9 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts +++ b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-10hp.dts @@ -45,6 +45,10 @@ }; }; +&uart1 { + status = "okay"; +}; + &mdio { INTERNAL_PHY(24) INTERNAL_PHY(26) diff --git a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts index 0d9b7c97c0..5ee340eac6 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts +++ b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v1.dts @@ -6,3 +6,7 @@ compatible = "zyxel,gs1900-8hp-v1", "realtek,rtl838x-soc"; model = "ZyXEL GS1900-8HP v1 Switch"; }; + +&uart1 { + status = "okay"; +}; diff --git a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts index cdc4aed6d1..0768462255 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts +++ b/target/linux/realtek/dts-5.10/rtl8380_zyxel_gs1900-8hp-v2.dts @@ -6,3 +6,7 @@ compatible = "zyxel,gs1900-8hp-v2", "realtek,rtl838x-soc"; model = "ZyXEL GS1900-8HP v2 Switch"; }; + +&uart1 { + status = "okay"; +}; diff --git a/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts index f347660283..119eaadc16 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts +++ b/target/linux/realtek/dts-5.10/rtl8382_d-link_dgs-1210-10p.dts @@ -102,6 +102,10 @@ }; }; +&uart1 { + status = "okay"; +}; + ðernet0 { mdio: mdio-bus { compatible = "realtek,rtl838x-mdio"; diff --git a/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts b/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts index c16152521e..7b6a9a1e7f 100644 --- a/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts +++ b/target/linux/realtek/dts-5.10/rtl8382_zyxel_gs1900-24hp-v2.dts @@ -45,6 +45,10 @@ }; }; +&uart1 { + status = "okay"; +}; + &mdio { EXTERNAL_PHY(0) EXTERNAL_PHY(1) From fc050c7b53116b6e3f2c31797b27cfc76af60e74 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Wed, 5 May 2021 09:31:53 +0900 Subject: [PATCH 82/82] realtek: add Kernel 5.10 as testing version This patch adds "KERNEL_TESTING_PATCHVER:=5.10" to the Makefile in realtek target to allow using Kernel 5.10 for testing. Signed-off-by: INAGAKI Hiroshi --- target/linux/realtek/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/realtek/Makefile b/target/linux/realtek/Makefile index 5159a40c4c..2eca7015e4 100644 --- a/target/linux/realtek/Makefile +++ b/target/linux/realtek/Makefile @@ -11,6 +11,7 @@ FEATURES:=ramdisk squashfs SUBTARGETS:=generic KERNEL_PATCHVER:=5.4 +KERNEL_TESTING_PATCHVER:=5.10 define Target/Description Build firmware images for Realtek RTL83xx based boards.