Lines Matching full:hellcreek

4  * Hirschmann Hellcreek TSN switch.
26 #include "hellcreek.h"
95 static u16 hellcreek_read(struct hellcreek *hellcreek, unsigned int offset) in hellcreek_read() argument
97 return readw(hellcreek->base + offset); in hellcreek_read()
100 static u16 hellcreek_read_ctrl(struct hellcreek *hellcreek) in hellcreek_read_ctrl() argument
102 return readw(hellcreek->base + HR_CTRL_C); in hellcreek_read_ctrl()
105 static u16 hellcreek_read_stat(struct hellcreek *hellcreek) in hellcreek_read_stat() argument
107 return readw(hellcreek->base + HR_SWSTAT); in hellcreek_read_stat()
110 static void hellcreek_write(struct hellcreek *hellcreek, u16 data, in hellcreek_write() argument
113 writew(data, hellcreek->base + offset); in hellcreek_write()
116 static void hellcreek_select_port(struct hellcreek *hellcreek, int port) in hellcreek_select_port() argument
120 hellcreek_write(hellcreek, val, HR_PSEL); in hellcreek_select_port()
123 static void hellcreek_select_prio(struct hellcreek *hellcreek, int prio) in hellcreek_select_prio() argument
127 hellcreek_write(hellcreek, val, HR_PSEL); in hellcreek_select_prio()
130 static void hellcreek_select_port_prio(struct hellcreek *hellcreek, int port, in hellcreek_select_port_prio() argument
137 hellcreek_write(hellcreek, val, HR_PSEL); in hellcreek_select_port_prio()
140 static void hellcreek_select_counter(struct hellcreek *hellcreek, int counter) in hellcreek_select_counter() argument
144 hellcreek_write(hellcreek, val, HR_CSEL); in hellcreek_select_counter()
150 static void hellcreek_select_vlan(struct hellcreek *hellcreek, int vid, in hellcreek_select_vlan() argument
158 hellcreek_write(hellcreek, val, HR_VIDCFG); in hellcreek_select_vlan()
162 hellcreek_write(hellcreek, val, HR_VIDCFG); in hellcreek_select_vlan()
165 static void hellcreek_select_tgd(struct hellcreek *hellcreek, int port) in hellcreek_select_tgd() argument
169 hellcreek_write(hellcreek, val, TR_TGDSEL); in hellcreek_select_tgd()
172 static int hellcreek_wait_until_ready(struct hellcreek *hellcreek) in hellcreek_wait_until_ready() argument
177 return readx_poll_timeout(hellcreek_read_ctrl, hellcreek, in hellcreek_wait_until_ready()
182 static int hellcreek_wait_until_transitioned(struct hellcreek *hellcreek) in hellcreek_wait_until_transitioned() argument
186 return readx_poll_timeout_atomic(hellcreek_read_ctrl, hellcreek, in hellcreek_wait_until_transitioned()
191 static int hellcreek_wait_fdb_ready(struct hellcreek *hellcreek) in hellcreek_wait_fdb_ready() argument
195 return readx_poll_timeout_atomic(hellcreek_read_stat, hellcreek, in hellcreek_wait_fdb_ready()
200 static int hellcreek_detect(struct hellcreek *hellcreek) in hellcreek_detect() argument
206 id = hellcreek_read(hellcreek, HR_MODID_C); in hellcreek_detect()
207 rel_low = hellcreek_read(hellcreek, HR_REL_L_C); in hellcreek_detect()
208 rel_high = hellcreek_read(hellcreek, HR_REL_H_C); in hellcreek_detect()
209 date_low = hellcreek_read(hellcreek, HR_BLD_L_C); in hellcreek_detect()
210 date_high = hellcreek_read(hellcreek, HR_BLD_H_C); in hellcreek_detect()
211 tgd_ver = hellcreek_read(hellcreek, TR_TGDVER); in hellcreek_detect()
213 if (id != hellcreek->pdata->module_id) in hellcreek_detect()
221 dev_info(hellcreek->dev, "Module ID=%02x Release=%04x Date=%04x TGD Version=%02x.%02x\n", in hellcreek_detect()
227 static void hellcreek_feature_detect(struct hellcreek *hellcreek) in hellcreek_feature_detect() argument
231 features = hellcreek_read(hellcreek, HR_FEABITS0); in hellcreek_feature_detect()
236 hellcreek->fdb_entries = ((features & HR_FEABITS0_FDBBINS_MASK) >> in hellcreek_feature_detect()
250 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_enable() local
254 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_enable()
256 dev_dbg(hellcreek->dev, "Enable port %d\n", port); in hellcreek_port_enable()
258 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_enable()
260 hellcreek_select_port(hellcreek, port); in hellcreek_port_enable()
263 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_enable()
266 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_enable()
273 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_disable() local
277 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_disable()
279 dev_dbg(hellcreek->dev, "Disable port %d\n", port); in hellcreek_port_disable()
281 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_disable()
283 hellcreek_select_port(hellcreek, port); in hellcreek_port_disable()
286 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_disable()
289 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_disable()
312 struct hellcreek *hellcreek = ds->priv; in hellcreek_get_ethtool_stats() local
316 hellcreek_port = &hellcreek->ports[port]; in hellcreek_get_ethtool_stats()
324 mutex_lock(&hellcreek->reg_lock); in hellcreek_get_ethtool_stats()
326 hellcreek_select_counter(hellcreek, offset); in hellcreek_get_ethtool_stats()
332 high = hellcreek_read(hellcreek, HR_CRDH); in hellcreek_get_ethtool_stats()
333 low = hellcreek_read(hellcreek, HR_CRDL); in hellcreek_get_ethtool_stats()
339 mutex_unlock(&hellcreek->reg_lock); in hellcreek_get_ethtool_stats()
352 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_prepare() local
355 dev_dbg(hellcreek->dev, "VLAN prepare for port %d\n", port); in hellcreek_vlan_prepare()
361 for (i = 0; i < hellcreek->pdata->num_ports; ++i) { in hellcreek_vlan_prepare()
376 static void hellcreek_select_vlan_params(struct hellcreek *hellcreek, int port, in hellcreek_select_vlan_params() argument
398 dev_err(hellcreek->dev, "Unknown port %d selected!\n", port); in hellcreek_select_vlan_params()
402 static void hellcreek_apply_vlan(struct hellcreek *hellcreek, int port, u16 vid, in hellcreek_apply_vlan() argument
408 dev_dbg(hellcreek->dev, "Apply VLAN: port=%d vid=%u pvid=%d untagged=%d", in hellcreek_apply_vlan()
411 mutex_lock(&hellcreek->reg_lock); in hellcreek_apply_vlan()
413 hellcreek_select_port(hellcreek, port); in hellcreek_apply_vlan()
414 hellcreek_select_vlan(hellcreek, vid, pvid); in hellcreek_apply_vlan()
417 hellcreek_select_vlan_params(hellcreek, port, &shift, &mask); in hellcreek_apply_vlan()
418 val = hellcreek->vidmbrcfg[vid]; in hellcreek_apply_vlan()
425 hellcreek_write(hellcreek, val, HR_VIDMBRCFG); in hellcreek_apply_vlan()
426 hellcreek->vidmbrcfg[vid] = val; in hellcreek_apply_vlan()
428 mutex_unlock(&hellcreek->reg_lock); in hellcreek_apply_vlan()
431 static void hellcreek_unapply_vlan(struct hellcreek *hellcreek, int port, in hellcreek_unapply_vlan() argument
437 dev_dbg(hellcreek->dev, "Unapply VLAN: port=%d vid=%u\n", port, vid); in hellcreek_unapply_vlan()
439 mutex_lock(&hellcreek->reg_lock); in hellcreek_unapply_vlan()
441 hellcreek_select_vlan(hellcreek, vid, false); in hellcreek_unapply_vlan()
444 hellcreek_select_vlan_params(hellcreek, port, &shift, &mask); in hellcreek_unapply_vlan()
445 val = hellcreek->vidmbrcfg[vid]; in hellcreek_unapply_vlan()
449 hellcreek_write(hellcreek, val, HR_VIDMBRCFG); in hellcreek_unapply_vlan()
450 hellcreek->vidmbrcfg[vid] = val; in hellcreek_unapply_vlan()
452 mutex_unlock(&hellcreek->reg_lock); in hellcreek_unapply_vlan()
461 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_add() local
468 dev_dbg(hellcreek->dev, "Add VLAN %d on port %d, %s, %s\n", in hellcreek_vlan_add()
472 hellcreek_apply_vlan(hellcreek, port, vlan->vid, pvid, untagged); in hellcreek_vlan_add()
480 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_del() local
482 dev_dbg(hellcreek->dev, "Remove VLAN %d on port %d\n", vlan->vid, port); in hellcreek_vlan_del()
484 hellcreek_unapply_vlan(hellcreek, port, vlan->vid); in hellcreek_vlan_del()
492 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_stp_state_set() local
497 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_stp_state_set()
499 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_stp_state_set()
532 hellcreek_select_port(hellcreek, port); in hellcreek_port_stp_state_set()
533 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_stp_state_set()
536 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_stp_state_set()
538 dev_dbg(hellcreek->dev, "Configured STP state for port %d: %s\n", in hellcreek_port_stp_state_set()
542 static void hellcreek_setup_ingressflt(struct hellcreek *hellcreek, int port, in hellcreek_setup_ingressflt() argument
545 struct hellcreek_port *hellcreek_port = &hellcreek->ports[port]; in hellcreek_setup_ingressflt()
548 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_ingressflt()
557 hellcreek_select_port(hellcreek, port); in hellcreek_setup_ingressflt()
558 hellcreek_write(hellcreek, ptcfg, HR_PTCFG); in hellcreek_setup_ingressflt()
561 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_ingressflt()
564 static void hellcreek_setup_vlan_awareness(struct hellcreek *hellcreek, in hellcreek_setup_vlan_awareness() argument
569 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_vlan_awareness()
571 swcfg = hellcreek->swcfg; in hellcreek_setup_vlan_awareness()
578 hellcreek_write(hellcreek, swcfg, HR_SWCFG); in hellcreek_setup_vlan_awareness()
580 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_vlan_awareness()
589 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup_vlan_membership() local
593 hellcreek_apply_vlan(hellcreek, port, vid, true, true); in hellcreek_setup_vlan_membership()
595 hellcreek_unapply_vlan(hellcreek, port, vid); in hellcreek_setup_vlan_membership()
599 hellcreek_apply_vlan(hellcreek, upstream, vid, false, true); in hellcreek_setup_vlan_membership()
601 hellcreek_unapply_vlan(hellcreek, upstream, vid); in hellcreek_setup_vlan_membership()
604 static void hellcreek_port_set_ucast_flood(struct hellcreek *hellcreek, in hellcreek_port_set_ucast_flood() argument
610 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_set_ucast_flood()
612 dev_dbg(hellcreek->dev, "%s unicast flooding on port %d\n", in hellcreek_port_set_ucast_flood()
615 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_ucast_flood()
617 hellcreek_select_port(hellcreek, port); in hellcreek_port_set_ucast_flood()
623 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_set_ucast_flood()
626 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_ucast_flood()
629 static void hellcreek_port_set_mcast_flood(struct hellcreek *hellcreek, in hellcreek_port_set_mcast_flood() argument
635 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_set_mcast_flood()
637 dev_dbg(hellcreek->dev, "%s multicast flooding on port %d\n", in hellcreek_port_set_mcast_flood()
640 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_mcast_flood()
642 hellcreek_select_port(hellcreek, port); in hellcreek_port_set_mcast_flood()
648 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_set_mcast_flood()
651 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_mcast_flood()
668 struct hellcreek *hellcreek = ds->priv; in hellcreek_bridge_flags() local
671 hellcreek_port_set_ucast_flood(hellcreek, port, in hellcreek_bridge_flags()
675 hellcreek_port_set_mcast_flood(hellcreek, port, in hellcreek_bridge_flags()
686 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_bridge_join() local
688 dev_dbg(hellcreek->dev, "Port %d joins a bridge\n", port); in hellcreek_port_bridge_join()
692 hellcreek_setup_vlan_awareness(hellcreek, false); in hellcreek_port_bridge_join()
703 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_bridge_leave() local
705 dev_dbg(hellcreek->dev, "Port %d leaves a bridge\n", port); in hellcreek_port_bridge_leave()
708 hellcreek_setup_vlan_awareness(hellcreek, true); in hellcreek_port_bridge_leave()
714 static int __hellcreek_fdb_add(struct hellcreek *hellcreek, in __hellcreek_fdb_add() argument
719 dev_dbg(hellcreek->dev, "Add static FDB entry: MAC=%pM, MASK=0x%02x, " in __hellcreek_fdb_add()
725 hellcreek_write(hellcreek, entry->mac[1] | (entry->mac[0] << 8), HR_FDBWDH); in __hellcreek_fdb_add()
726 hellcreek_write(hellcreek, entry->mac[3] | (entry->mac[2] << 8), HR_FDBWDM); in __hellcreek_fdb_add()
727 hellcreek_write(hellcreek, entry->mac[5] | (entry->mac[4] << 8), HR_FDBWDL); in __hellcreek_fdb_add()
739 hellcreek_write(hellcreek, meta, HR_FDBWRM0); in __hellcreek_fdb_add()
742 hellcreek_write(hellcreek, 0x00, HR_FDBWRCMD); in __hellcreek_fdb_add()
745 return hellcreek_wait_fdb_ready(hellcreek); in __hellcreek_fdb_add()
748 static int __hellcreek_fdb_del(struct hellcreek *hellcreek, in __hellcreek_fdb_del() argument
751 dev_dbg(hellcreek->dev, "Delete FDB entry: MAC=%pM!\n", entry->mac); in __hellcreek_fdb_del()
754 hellcreek_write(hellcreek, entry->idx | HR_FDBWRCMD_FDBDEL, HR_FDBWRCMD); in __hellcreek_fdb_del()
757 return hellcreek_wait_fdb_ready(hellcreek); in __hellcreek_fdb_del()
760 static void hellcreek_populate_fdb_entry(struct hellcreek *hellcreek, in hellcreek_populate_fdb_entry() argument
768 meta = hellcreek_read(hellcreek, HR_FDBMDRD); in hellcreek_populate_fdb_entry()
769 mac = hellcreek_read(hellcreek, HR_FDBRDL); in hellcreek_populate_fdb_entry()
772 mac = hellcreek_read(hellcreek, HR_FDBRDM); in hellcreek_populate_fdb_entry()
775 mac = hellcreek_read(hellcreek, HR_FDBRDH); in hellcreek_populate_fdb_entry()
798 static int hellcreek_fdb_get(struct hellcreek *hellcreek, in hellcreek_fdb_get() argument
808 hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_fdb_get()
809 hellcreek_write(hellcreek, 0x00, HR_FDBMAX); in hellcreek_fdb_get()
814 for (i = 0; i < hellcreek->fdb_entries; ++i) { in hellcreek_fdb_get()
818 hellcreek_populate_fdb_entry(hellcreek, &tmp, i); in hellcreek_fdb_get()
821 hellcreek_write(hellcreek, 0x00, HR_FDBRDH); in hellcreek_fdb_get()
840 struct hellcreek *hellcreek = ds->priv; in hellcreek_fdb_add() local
843 dev_dbg(hellcreek->dev, "Add FDB entry for MAC=%pM\n", addr); in hellcreek_fdb_add()
845 mutex_lock(&hellcreek->reg_lock); in hellcreek_fdb_add()
847 ret = hellcreek_fdb_get(hellcreek, addr, &entry); in hellcreek_fdb_add()
853 ret = __hellcreek_fdb_add(hellcreek, &entry); in hellcreek_fdb_add()
855 dev_err(hellcreek->dev, "Failed to add FDB entry!\n"); in hellcreek_fdb_add()
860 ret = __hellcreek_fdb_del(hellcreek, &entry); in hellcreek_fdb_add()
862 dev_err(hellcreek->dev, "Failed to delete FDB entry!\n"); in hellcreek_fdb_add()
868 ret = __hellcreek_fdb_add(hellcreek, &entry); in hellcreek_fdb_add()
870 dev_err(hellcreek->dev, "Failed to add FDB entry!\n"); in hellcreek_fdb_add()
876 mutex_unlock(&hellcreek->reg_lock); in hellcreek_fdb_add()
886 struct hellcreek *hellcreek = ds->priv; in hellcreek_fdb_del() local
889 dev_dbg(hellcreek->dev, "Delete FDB entry for MAC=%pM\n", addr); in hellcreek_fdb_del()
891 mutex_lock(&hellcreek->reg_lock); in hellcreek_fdb_del()
893 ret = hellcreek_fdb_get(hellcreek, addr, &entry); in hellcreek_fdb_del()
896 dev_err(hellcreek->dev, "FDB entry for deletion not found!\n"); in hellcreek_fdb_del()
899 ret = __hellcreek_fdb_del(hellcreek, &entry); in hellcreek_fdb_del()
901 dev_err(hellcreek->dev, "Failed to delete FDB entry!\n"); in hellcreek_fdb_del()
908 ret = __hellcreek_fdb_add(hellcreek, &entry); in hellcreek_fdb_del()
910 dev_err(hellcreek->dev, "Failed to add FDB entry!\n"); in hellcreek_fdb_del()
917 mutex_unlock(&hellcreek->reg_lock); in hellcreek_fdb_del()
925 struct hellcreek *hellcreek = ds->priv; in hellcreek_fdb_dump() local
930 mutex_lock(&hellcreek->reg_lock); in hellcreek_fdb_dump()
936 entries = hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_fdb_dump()
937 hellcreek_write(hellcreek, 0x00, HR_FDBMAX); in hellcreek_fdb_dump()
939 dev_dbg(hellcreek->dev, "FDB dump for port %d, entries=%d!\n", port, entries); in hellcreek_fdb_dump()
942 for (i = 0; i < hellcreek->fdb_entries; ++i) { in hellcreek_fdb_dump()
946 hellcreek_populate_fdb_entry(hellcreek, &entry, i); in hellcreek_fdb_dump()
949 hellcreek_write(hellcreek, 0x00, HR_FDBRDH); in hellcreek_fdb_dump()
964 mutex_unlock(&hellcreek->reg_lock); in hellcreek_fdb_dump()
973 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_filtering() local
975 dev_dbg(hellcreek->dev, "%s VLAN filtering on port %d\n", in hellcreek_vlan_filtering()
979 hellcreek_setup_ingressflt(hellcreek, port, vlan_filtering); in hellcreek_vlan_filtering()
984 hellcreek_setup_vlan_awareness(hellcreek, vlan_filtering); in hellcreek_vlan_filtering()
989 static int hellcreek_enable_ip_core(struct hellcreek *hellcreek) in hellcreek_enable_ip_core() argument
994 mutex_lock(&hellcreek->reg_lock); in hellcreek_enable_ip_core()
996 val = hellcreek_read(hellcreek, HR_CTRL_C); in hellcreek_enable_ip_core()
998 hellcreek_write(hellcreek, val, HR_CTRL_C); in hellcreek_enable_ip_core()
999 ret = hellcreek_wait_until_transitioned(hellcreek); in hellcreek_enable_ip_core()
1001 mutex_unlock(&hellcreek->reg_lock); in hellcreek_enable_ip_core()
1006 static void hellcreek_setup_cpu_and_tunnel_port(struct hellcreek *hellcreek) in hellcreek_setup_cpu_and_tunnel_port() argument
1008 struct hellcreek_port *tunnel_port = &hellcreek->ports[TUNNEL_PORT]; in hellcreek_setup_cpu_and_tunnel_port()
1009 struct hellcreek_port *cpu_port = &hellcreek->ports[CPU_PORT]; in hellcreek_setup_cpu_and_tunnel_port()
1014 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_cpu_and_tunnel_port()
1016 hellcreek_select_port(hellcreek, CPU_PORT); in hellcreek_setup_cpu_and_tunnel_port()
1017 hellcreek_write(hellcreek, ptcfg, HR_PTCFG); in hellcreek_setup_cpu_and_tunnel_port()
1019 hellcreek_select_port(hellcreek, TUNNEL_PORT); in hellcreek_setup_cpu_and_tunnel_port()
1020 hellcreek_write(hellcreek, ptcfg, HR_PTCFG); in hellcreek_setup_cpu_and_tunnel_port()
1025 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_cpu_and_tunnel_port()
1028 static void hellcreek_setup_tc_identity_mapping(struct hellcreek *hellcreek) in hellcreek_setup_tc_identity_mapping() argument
1051 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_tc_identity_mapping()
1053 hellcreek_select_prio(hellcreek, i); in hellcreek_setup_tc_identity_mapping()
1054 hellcreek_write(hellcreek, in hellcreek_setup_tc_identity_mapping()
1058 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_tc_identity_mapping()
1062 static int hellcreek_setup_fdb(struct hellcreek *hellcreek) in hellcreek_setup_fdb() argument
1143 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_fdb()
1144 ret = __hellcreek_fdb_add(hellcreek, &l2_ptp); in hellcreek_setup_fdb()
1147 ret = __hellcreek_fdb_add(hellcreek, &udp4_ptp); in hellcreek_setup_fdb()
1150 ret = __hellcreek_fdb_add(hellcreek, &udp6_ptp); in hellcreek_setup_fdb()
1153 ret = __hellcreek_fdb_add(hellcreek, &l2_p2p); in hellcreek_setup_fdb()
1156 ret = __hellcreek_fdb_add(hellcreek, &udp4_p2p); in hellcreek_setup_fdb()
1159 ret = __hellcreek_fdb_add(hellcreek, &udp6_p2p); in hellcreek_setup_fdb()
1162 ret = __hellcreek_fdb_add(hellcreek, &stp); in hellcreek_setup_fdb()
1164 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_fdb()
1173 struct hellcreek *hellcreek = ds->priv; in hellcreek_devlink_info_get() local
1177 hellcreek->pdata->name); in hellcreek_devlink_info_get()
1182 struct hellcreek *hellcreek = priv; in hellcreek_devlink_vlan_table_get() local
1186 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_vlan_table_get()
1188 if (hellcreek->vidmbrcfg[i]) in hellcreek_devlink_vlan_table_get()
1190 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_vlan_table_get()
1197 struct hellcreek *hellcreek = priv; in hellcreek_devlink_fdb_table_get() local
1203 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_fdb_table_get()
1204 count = hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_devlink_fdb_table_get()
1205 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_fdb_table_get()
1214 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup_devlink_resources() local
1222 hellcreek->fdb_entries, in hellcreek_setup_devlink_resources()
1223 hellcreek->fdb_entries, in hellcreek_setup_devlink_resources()
1233 err = dsa_devlink_resource_register(ds, "FDB", hellcreek->fdb_entries, in hellcreek_setup_devlink_resources()
1243 hellcreek); in hellcreek_setup_devlink_resources()
1248 hellcreek); in hellcreek_setup_devlink_resources()
1265 struct hellcreek *hellcreek = ds->priv; in hellcreek_devlink_region_vlan_snapshot() local
1274 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_region_vlan_snapshot()
1276 entry->member = hellcreek->vidmbrcfg[i]; in hellcreek_devlink_region_vlan_snapshot()
1279 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_region_vlan_snapshot()
1293 struct hellcreek *hellcreek = ds->priv; in hellcreek_devlink_region_fdb_snapshot() local
1296 table = kcalloc(hellcreek->fdb_entries, sizeof(*entry), GFP_KERNEL); in hellcreek_devlink_region_fdb_snapshot()
1302 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_region_fdb_snapshot()
1305 hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_devlink_region_fdb_snapshot()
1306 hellcreek_write(hellcreek, 0x00, HR_FDBMAX); in hellcreek_devlink_region_fdb_snapshot()
1308 for (i = 0; i < hellcreek->fdb_entries; ++i, ++entry) { in hellcreek_devlink_region_fdb_snapshot()
1310 hellcreek_populate_fdb_entry(hellcreek, entry, i); in hellcreek_devlink_region_fdb_snapshot()
1313 hellcreek_write(hellcreek, 0x00, HR_FDBRDH); in hellcreek_devlink_region_fdb_snapshot()
1316 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_region_fdb_snapshot()
1337 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup_devlink_regions() local
1351 hellcreek->vlan_region = region; in hellcreek_setup_devlink_regions()
1354 size = hellcreek->fdb_entries * sizeof(struct hellcreek_fdb_entry); in hellcreek_setup_devlink_regions()
1363 hellcreek->fdb_region = region; in hellcreek_setup_devlink_regions()
1368 dsa_devlink_region_destroy(hellcreek->vlan_region); in hellcreek_setup_devlink_regions()
1375 struct hellcreek *hellcreek = ds->priv; in hellcreek_teardown_devlink_regions() local
1377 dsa_devlink_region_destroy(hellcreek->fdb_region); in hellcreek_teardown_devlink_regions()
1378 dsa_devlink_region_destroy(hellcreek->vlan_region); in hellcreek_teardown_devlink_regions()
1383 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup() local
1387 dev_dbg(hellcreek->dev, "Set up the switch\n"); in hellcreek_setup()
1390 ret = hellcreek_enable_ip_core(hellcreek); in hellcreek_setup()
1392 dev_err(hellcreek->dev, "Failed to enable IP core!\n"); in hellcreek_setup()
1397 hellcreek_setup_cpu_and_tunnel_port(hellcreek); in hellcreek_setup()
1407 hellcreek->swcfg = swcfg; in hellcreek_setup()
1408 hellcreek_write(hellcreek, swcfg, HR_SWCFG); in hellcreek_setup()
1419 hellcreek_setup_tc_identity_mapping(hellcreek); in hellcreek_setup()
1428 ret = hellcreek_setup_fdb(hellcreek); in hellcreek_setup()
1430 dev_err(hellcreek->dev, in hellcreek_setup()
1438 dev_err(hellcreek->dev, in hellcreek_setup()
1445 dev_err(hellcreek->dev, in hellcreek_setup()
1467 struct hellcreek *hellcreek = ds->priv; in hellcreek_phylink_get_caps() local
1483 if (hellcreek->pdata->is_100_mbits) in hellcreek_phylink_get_caps()
1493 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_prechangeupper() local
1499 dev_dbg(hellcreek->dev, "Pre change upper for port %d\n", port); in hellcreek_port_prechangeupper()
1515 mutex_lock(&hellcreek->vlan_lock); in hellcreek_port_prechangeupper()
1516 for (i = 0; i < hellcreek->pdata->num_ports; ++i) { in hellcreek_port_prechangeupper()
1523 used = used && test_bit(vid, hellcreek->ports[i].vlan_dev_bitmap); in hellcreek_port_prechangeupper()
1530 set_bit(vid, hellcreek->ports[port].vlan_dev_bitmap); in hellcreek_port_prechangeupper()
1535 mutex_unlock(&hellcreek->vlan_lock); in hellcreek_port_prechangeupper()
1540 static void hellcreek_setup_maxsdu(struct hellcreek *hellcreek, int port, in hellcreek_setup_maxsdu() argument
1552 dev_dbg(hellcreek->dev, "Configure max-sdu %u for tc %d on port %d\n", in hellcreek_setup_maxsdu()
1555 hellcreek_select_port_prio(hellcreek, port, tc); in hellcreek_setup_maxsdu()
1559 hellcreek_write(hellcreek, val, HR_PTPRTCCFG); in hellcreek_setup_maxsdu()
1563 static void hellcreek_reset_maxsdu(struct hellcreek *hellcreek, int port) in hellcreek_reset_maxsdu() argument
1570 hellcreek_select_port_prio(hellcreek, port, tc); in hellcreek_reset_maxsdu()
1575 hellcreek_write(hellcreek, val, HR_PTPRTCCFG); in hellcreek_reset_maxsdu()
1579 static void hellcreek_setup_gcl(struct hellcreek *hellcreek, int port, in hellcreek_setup_gcl() argument
1605 hellcreek_write(hellcreek, data, TR_GCLDAT); in hellcreek_setup_gcl()
1608 hellcreek_write(hellcreek, in hellcreek_setup_gcl()
1611 hellcreek_write(hellcreek, in hellcreek_setup_gcl()
1619 hellcreek_write(hellcreek, data, TR_GCLCMD); in hellcreek_setup_gcl()
1626 static void hellcreek_set_cycle_time(struct hellcreek *hellcreek, in hellcreek_set_cycle_time() argument
1631 hellcreek_write(hellcreek, cycle_time & 0x0000ffff, TR_CTWRL); in hellcreek_set_cycle_time()
1632 hellcreek_write(hellcreek, (cycle_time & 0xffff0000) >> 16, TR_CTWRH); in hellcreek_set_cycle_time()
1635 static void hellcreek_switch_schedule(struct hellcreek *hellcreek, in hellcreek_switch_schedule() argument
1641 hellcreek_write(hellcreek, ts.tv_nsec & 0x0000ffff, TR_ESTWRL); in hellcreek_switch_schedule()
1642 hellcreek_write(hellcreek, (ts.tv_nsec & 0xffff0000) >> 16, TR_ESTWRH); in hellcreek_switch_schedule()
1645 hellcreek_write(hellcreek, TR_ESTCMD_ESTARM | TR_ESTCMD_ESTSWCFG | in hellcreek_switch_schedule()
1650 static bool hellcreek_schedule_startable(struct hellcreek *hellcreek, int port) in hellcreek_schedule_startable() argument
1652 struct hellcreek_port *hellcreek_port = &hellcreek->ports[port]; in hellcreek_schedule_startable()
1663 mutex_lock(&hellcreek->ptp_lock); in hellcreek_schedule_startable()
1664 current_ns = hellcreek->seconds * NSEC_PER_SEC + hellcreek->last_ts; in hellcreek_schedule_startable()
1665 mutex_unlock(&hellcreek->ptp_lock); in hellcreek_schedule_startable()
1673 static void hellcreek_start_schedule(struct hellcreek *hellcreek, int port) in hellcreek_start_schedule() argument
1675 struct hellcreek_port *hellcreek_port = &hellcreek->ports[port]; in hellcreek_start_schedule()
1681 hellcreek_select_tgd(hellcreek, port); in hellcreek_start_schedule()
1684 mutex_lock(&hellcreek->ptp_lock); in hellcreek_start_schedule()
1685 current_ns = hellcreek->seconds * NSEC_PER_SEC + hellcreek->last_ts; in hellcreek_start_schedule()
1686 mutex_unlock(&hellcreek->ptp_lock); in hellcreek_start_schedule()
1701 hellcreek_switch_schedule(hellcreek, base_time); in hellcreek_start_schedule()
1706 dev_dbg(hellcreek->dev, "Armed EST timer for port %d\n", in hellcreek_start_schedule()
1714 struct hellcreek *hellcreek; in hellcreek_check_schedule() local
1718 hellcreek = hellcreek_port->hellcreek; in hellcreek_check_schedule()
1720 mutex_lock(&hellcreek->reg_lock); in hellcreek_check_schedule()
1723 startable = hellcreek_schedule_startable(hellcreek, in hellcreek_check_schedule()
1726 hellcreek_start_schedule(hellcreek, hellcreek_port->port); in hellcreek_check_schedule()
1727 mutex_unlock(&hellcreek->reg_lock); in hellcreek_check_schedule()
1731 mutex_unlock(&hellcreek->reg_lock); in hellcreek_check_schedule()
1741 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_set_schedule() local
1746 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_set_schedule()
1748 dev_dbg(hellcreek->dev, "Configure traffic schedule on port %d\n", in hellcreek_port_set_schedule()
1754 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1763 hellcreek_setup_maxsdu(hellcreek, port, hellcreek_port->current_schedule); in hellcreek_port_set_schedule()
1766 hellcreek_select_tgd(hellcreek, port); in hellcreek_port_set_schedule()
1770 hellcreek_write(hellcreek, ctrl, TR_TGDCTRL); in hellcreek_port_set_schedule()
1773 hellcreek_write(hellcreek, 0x00, TR_ESTCMD); in hellcreek_port_set_schedule()
1776 hellcreek_setup_gcl(hellcreek, port, hellcreek_port->current_schedule); in hellcreek_port_set_schedule()
1779 hellcreek_set_cycle_time(hellcreek, hellcreek_port->current_schedule); in hellcreek_port_set_schedule()
1782 startable = hellcreek_schedule_startable(hellcreek, port); in hellcreek_port_set_schedule()
1784 hellcreek_start_schedule(hellcreek, port); in hellcreek_port_set_schedule()
1785 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1789 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1800 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_del_schedule() local
1803 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_del_schedule()
1805 dev_dbg(hellcreek->dev, "Remove traffic schedule on port %d\n", port); in hellcreek_port_del_schedule()
1810 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_del_schedule()
1818 hellcreek_reset_maxsdu(hellcreek, port); in hellcreek_port_del_schedule()
1821 hellcreek_select_tgd(hellcreek, port); in hellcreek_port_del_schedule()
1824 hellcreek_write(hellcreek, 0xff << TR_TGDCTRL_ADMINGATESTATES_SHIFT, in hellcreek_port_del_schedule()
1827 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_del_schedule()
1832 static bool hellcreek_validate_schedule(struct hellcreek *hellcreek, in hellcreek_validate_schedule() argument
1837 /* Does this hellcreek version support Qbv in hardware? */ in hellcreek_validate_schedule()
1838 if (!hellcreek->pdata->qbv_support) in hellcreek_validate_schedule()
1875 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_setup_tc() local
1885 if (!hellcreek_validate_schedule(hellcreek, taprio)) in hellcreek_port_setup_tc()
1934 struct hellcreek *hellcreek; in hellcreek_probe() local
1938 hellcreek = devm_kzalloc(dev, sizeof(*hellcreek), GFP_KERNEL); in hellcreek_probe()
1939 if (!hellcreek) in hellcreek_probe()
1942 hellcreek->vidmbrcfg = devm_kcalloc(dev, VLAN_N_VID, in hellcreek_probe()
1943 sizeof(*hellcreek->vidmbrcfg), in hellcreek_probe()
1945 if (!hellcreek->vidmbrcfg) in hellcreek_probe()
1948 hellcreek->pdata = of_device_get_match_data(dev); in hellcreek_probe()
1950 hellcreek->ports = devm_kcalloc(dev, hellcreek->pdata->num_ports, in hellcreek_probe()
1951 sizeof(*hellcreek->ports), in hellcreek_probe()
1953 if (!hellcreek->ports) in hellcreek_probe()
1956 for (i = 0; i < hellcreek->pdata->num_ports; ++i) { in hellcreek_probe()
1957 struct hellcreek_port *port = &hellcreek->ports[i]; in hellcreek_probe()
1972 port->hellcreek = hellcreek; in hellcreek_probe()
1979 mutex_init(&hellcreek->reg_lock); in hellcreek_probe()
1980 mutex_init(&hellcreek->vlan_lock); in hellcreek_probe()
1981 mutex_init(&hellcreek->ptp_lock); in hellcreek_probe()
1983 hellcreek->dev = dev; in hellcreek_probe()
1991 hellcreek->base = devm_ioremap_resource(dev, res); in hellcreek_probe()
1992 if (IS_ERR(hellcreek->base)) in hellcreek_probe()
1993 return PTR_ERR(hellcreek->base); in hellcreek_probe()
2001 hellcreek->ptp_base = devm_ioremap_resource(dev, res); in hellcreek_probe()
2002 if (IS_ERR(hellcreek->ptp_base)) in hellcreek_probe()
2003 return PTR_ERR(hellcreek->ptp_base); in hellcreek_probe()
2005 ret = hellcreek_detect(hellcreek); in hellcreek_probe()
2011 ret = hellcreek_wait_until_ready(hellcreek); in hellcreek_probe()
2017 hellcreek_feature_detect(hellcreek); in hellcreek_probe()
2019 hellcreek->ds = devm_kzalloc(dev, sizeof(*hellcreek->ds), GFP_KERNEL); in hellcreek_probe()
2020 if (!hellcreek->ds) in hellcreek_probe()
2023 hellcreek->ds->dev = dev; in hellcreek_probe()
2024 hellcreek->ds->priv = hellcreek; in hellcreek_probe()
2025 hellcreek->ds->ops = &hellcreek_ds_ops; in hellcreek_probe()
2026 hellcreek->ds->num_ports = hellcreek->pdata->num_ports; in hellcreek_probe()
2027 hellcreek->ds->num_tx_queues = HELLCREEK_NUM_EGRESS_QUEUES; in hellcreek_probe()
2029 ret = dsa_register_switch(hellcreek->ds); in hellcreek_probe()
2035 ret = hellcreek_ptp_setup(hellcreek); in hellcreek_probe()
2041 ret = hellcreek_hwtstamp_setup(hellcreek); in hellcreek_probe()
2047 platform_set_drvdata(pdev, hellcreek); in hellcreek_probe()
2052 hellcreek_ptp_free(hellcreek); in hellcreek_probe()
2054 dsa_unregister_switch(hellcreek->ds); in hellcreek_probe()
2061 struct hellcreek *hellcreek = platform_get_drvdata(pdev); in hellcreek_remove() local
2063 if (!hellcreek) in hellcreek_remove()
2066 hellcreek_hwtstamp_free(hellcreek); in hellcreek_remove()
2067 hellcreek_ptp_free(hellcreek); in hellcreek_remove()
2068 dsa_unregister_switch(hellcreek->ds); in hellcreek_remove()
2073 struct hellcreek *hellcreek = platform_get_drvdata(pdev); in hellcreek_shutdown() local
2075 if (!hellcreek) in hellcreek_shutdown()
2078 dsa_switch_shutdown(hellcreek->ds); in hellcreek_shutdown()
2095 .compatible = "hirschmann,hellcreek-de1soc-r1",
2107 .name = "hellcreek",
2114 MODULE_DESCRIPTION("Hirschmann Hellcreek driver");