Lines Matching full:hellcreek

4  * Hirschmann Hellcreek TSN switch.
27 #include "hellcreek.h"
96 static u16 hellcreek_read(struct hellcreek *hellcreek, unsigned int offset) in hellcreek_read() argument
98 return readw(hellcreek->base + offset); in hellcreek_read()
101 static u16 hellcreek_read_ctrl(struct hellcreek *hellcreek) in hellcreek_read_ctrl() argument
103 return readw(hellcreek->base + HR_CTRL_C); in hellcreek_read_ctrl()
106 static u16 hellcreek_read_stat(struct hellcreek *hellcreek) in hellcreek_read_stat() argument
108 return readw(hellcreek->base + HR_SWSTAT); in hellcreek_read_stat()
111 static void hellcreek_write(struct hellcreek *hellcreek, u16 data, in hellcreek_write() argument
114 writew(data, hellcreek->base + offset); in hellcreek_write()
117 static void hellcreek_select_port(struct hellcreek *hellcreek, int port) in hellcreek_select_port() argument
121 hellcreek_write(hellcreek, val, HR_PSEL); in hellcreek_select_port()
124 static void hellcreek_select_prio(struct hellcreek *hellcreek, int prio) in hellcreek_select_prio() argument
128 hellcreek_write(hellcreek, val, HR_PSEL); in hellcreek_select_prio()
131 static void hellcreek_select_counter(struct hellcreek *hellcreek, int counter) in hellcreek_select_counter() argument
135 hellcreek_write(hellcreek, val, HR_CSEL); in hellcreek_select_counter()
141 static void hellcreek_select_vlan(struct hellcreek *hellcreek, int vid, in hellcreek_select_vlan() argument
149 hellcreek_write(hellcreek, val, HR_VIDCFG); in hellcreek_select_vlan()
153 hellcreek_write(hellcreek, val, HR_VIDCFG); in hellcreek_select_vlan()
156 static void hellcreek_select_tgd(struct hellcreek *hellcreek, int port) in hellcreek_select_tgd() argument
160 hellcreek_write(hellcreek, val, TR_TGDSEL); in hellcreek_select_tgd()
163 static int hellcreek_wait_until_ready(struct hellcreek *hellcreek) in hellcreek_wait_until_ready() argument
168 return readx_poll_timeout(hellcreek_read_ctrl, hellcreek, in hellcreek_wait_until_ready()
173 static int hellcreek_wait_until_transitioned(struct hellcreek *hellcreek) in hellcreek_wait_until_transitioned() argument
177 return readx_poll_timeout_atomic(hellcreek_read_ctrl, hellcreek, in hellcreek_wait_until_transitioned()
182 static int hellcreek_wait_fdb_ready(struct hellcreek *hellcreek) in hellcreek_wait_fdb_ready() argument
186 return readx_poll_timeout_atomic(hellcreek_read_stat, hellcreek, in hellcreek_wait_fdb_ready()
191 static int hellcreek_detect(struct hellcreek *hellcreek) in hellcreek_detect() argument
197 id = hellcreek_read(hellcreek, HR_MODID_C); in hellcreek_detect()
198 rel_low = hellcreek_read(hellcreek, HR_REL_L_C); in hellcreek_detect()
199 rel_high = hellcreek_read(hellcreek, HR_REL_H_C); in hellcreek_detect()
200 date_low = hellcreek_read(hellcreek, HR_BLD_L_C); in hellcreek_detect()
201 date_high = hellcreek_read(hellcreek, HR_BLD_H_C); in hellcreek_detect()
202 tgd_ver = hellcreek_read(hellcreek, TR_TGDVER); in hellcreek_detect()
204 if (id != hellcreek->pdata->module_id) in hellcreek_detect()
212 dev_info(hellcreek->dev, "Module ID=%02x Release=%04x Date=%04x TGD Version=%02x.%02x\n", in hellcreek_detect()
218 static void hellcreek_feature_detect(struct hellcreek *hellcreek) in hellcreek_feature_detect() argument
222 features = hellcreek_read(hellcreek, HR_FEABITS0); in hellcreek_feature_detect()
227 hellcreek->fdb_entries = ((features & HR_FEABITS0_FDBBINS_MASK) >> in hellcreek_feature_detect()
241 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_enable() local
245 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_enable()
247 dev_dbg(hellcreek->dev, "Enable port %d\n", port); in hellcreek_port_enable()
249 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_enable()
251 hellcreek_select_port(hellcreek, port); in hellcreek_port_enable()
254 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_enable()
257 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_enable()
264 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_disable() local
268 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_disable()
270 dev_dbg(hellcreek->dev, "Disable port %d\n", port); in hellcreek_port_disable()
272 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_disable()
274 hellcreek_select_port(hellcreek, port); in hellcreek_port_disable()
277 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_disable()
280 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_disable()
307 struct hellcreek *hellcreek = ds->priv; in hellcreek_get_ethtool_stats() local
311 hellcreek_port = &hellcreek->ports[port]; in hellcreek_get_ethtool_stats()
319 mutex_lock(&hellcreek->reg_lock); in hellcreek_get_ethtool_stats()
321 hellcreek_select_counter(hellcreek, offset); in hellcreek_get_ethtool_stats()
327 high = hellcreek_read(hellcreek, HR_CRDH); in hellcreek_get_ethtool_stats()
328 low = hellcreek_read(hellcreek, HR_CRDL); in hellcreek_get_ethtool_stats()
334 mutex_unlock(&hellcreek->reg_lock); in hellcreek_get_ethtool_stats()
347 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_prepare() local
350 dev_dbg(hellcreek->dev, "VLAN prepare for port %d\n", port); in hellcreek_vlan_prepare()
356 for (i = 0; i < hellcreek->pdata->num_ports; ++i) { in hellcreek_vlan_prepare()
371 static void hellcreek_select_vlan_params(struct hellcreek *hellcreek, int port, in hellcreek_select_vlan_params() argument
393 dev_err(hellcreek->dev, "Unknown port %d selected!\n", port); in hellcreek_select_vlan_params()
397 static void hellcreek_apply_vlan(struct hellcreek *hellcreek, int port, u16 vid, in hellcreek_apply_vlan() argument
403 dev_dbg(hellcreek->dev, "Apply VLAN: port=%d vid=%u pvid=%d untagged=%d", in hellcreek_apply_vlan()
406 mutex_lock(&hellcreek->reg_lock); in hellcreek_apply_vlan()
408 hellcreek_select_port(hellcreek, port); in hellcreek_apply_vlan()
409 hellcreek_select_vlan(hellcreek, vid, pvid); in hellcreek_apply_vlan()
412 hellcreek_select_vlan_params(hellcreek, port, &shift, &mask); in hellcreek_apply_vlan()
413 val = hellcreek->vidmbrcfg[vid]; in hellcreek_apply_vlan()
420 hellcreek_write(hellcreek, val, HR_VIDMBRCFG); in hellcreek_apply_vlan()
421 hellcreek->vidmbrcfg[vid] = val; in hellcreek_apply_vlan()
423 mutex_unlock(&hellcreek->reg_lock); in hellcreek_apply_vlan()
426 static void hellcreek_unapply_vlan(struct hellcreek *hellcreek, int port, in hellcreek_unapply_vlan() argument
432 dev_dbg(hellcreek->dev, "Unapply VLAN: port=%d vid=%u\n", port, vid); in hellcreek_unapply_vlan()
434 mutex_lock(&hellcreek->reg_lock); in hellcreek_unapply_vlan()
436 hellcreek_select_vlan(hellcreek, vid, false); in hellcreek_unapply_vlan()
439 hellcreek_select_vlan_params(hellcreek, port, &shift, &mask); in hellcreek_unapply_vlan()
440 val = hellcreek->vidmbrcfg[vid]; in hellcreek_unapply_vlan()
444 hellcreek_write(hellcreek, val, HR_VIDMBRCFG); in hellcreek_unapply_vlan()
445 hellcreek->vidmbrcfg[vid] = val; in hellcreek_unapply_vlan()
447 mutex_unlock(&hellcreek->reg_lock); in hellcreek_unapply_vlan()
456 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_add() local
463 dev_dbg(hellcreek->dev, "Add VLAN %d on port %d, %s, %s\n", in hellcreek_vlan_add()
467 hellcreek_apply_vlan(hellcreek, port, vlan->vid, pvid, untagged); in hellcreek_vlan_add()
475 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_del() local
477 dev_dbg(hellcreek->dev, "Remove VLAN %d on port %d\n", vlan->vid, port); in hellcreek_vlan_del()
479 hellcreek_unapply_vlan(hellcreek, port, vlan->vid); in hellcreek_vlan_del()
487 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_stp_state_set() local
492 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_stp_state_set()
494 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_stp_state_set()
527 hellcreek_select_port(hellcreek, port); in hellcreek_port_stp_state_set()
528 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_stp_state_set()
531 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_stp_state_set()
533 dev_dbg(hellcreek->dev, "Configured STP state for port %d: %s\n", in hellcreek_port_stp_state_set()
537 static void hellcreek_setup_ingressflt(struct hellcreek *hellcreek, int port, in hellcreek_setup_ingressflt() argument
540 struct hellcreek_port *hellcreek_port = &hellcreek->ports[port]; in hellcreek_setup_ingressflt()
543 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_ingressflt()
552 hellcreek_select_port(hellcreek, port); in hellcreek_setup_ingressflt()
553 hellcreek_write(hellcreek, ptcfg, HR_PTCFG); in hellcreek_setup_ingressflt()
556 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_ingressflt()
559 static void hellcreek_setup_vlan_awareness(struct hellcreek *hellcreek, in hellcreek_setup_vlan_awareness() argument
564 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_vlan_awareness()
566 swcfg = hellcreek->swcfg; in hellcreek_setup_vlan_awareness()
573 hellcreek_write(hellcreek, swcfg, HR_SWCFG); in hellcreek_setup_vlan_awareness()
575 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_vlan_awareness()
584 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup_vlan_membership() local
588 hellcreek_apply_vlan(hellcreek, port, vid, true, true); in hellcreek_setup_vlan_membership()
590 hellcreek_unapply_vlan(hellcreek, port, vid); in hellcreek_setup_vlan_membership()
594 hellcreek_apply_vlan(hellcreek, upstream, vid, false, true); in hellcreek_setup_vlan_membership()
596 hellcreek_unapply_vlan(hellcreek, upstream, vid); in hellcreek_setup_vlan_membership()
599 static void hellcreek_port_set_ucast_flood(struct hellcreek *hellcreek, in hellcreek_port_set_ucast_flood() argument
605 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_set_ucast_flood()
607 dev_dbg(hellcreek->dev, "%s unicast flooding on port %d\n", in hellcreek_port_set_ucast_flood()
610 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_ucast_flood()
612 hellcreek_select_port(hellcreek, port); in hellcreek_port_set_ucast_flood()
618 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_set_ucast_flood()
621 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_ucast_flood()
624 static void hellcreek_port_set_mcast_flood(struct hellcreek *hellcreek, in hellcreek_port_set_mcast_flood() argument
630 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_set_mcast_flood()
632 dev_dbg(hellcreek->dev, "%s multicast flooding on port %d\n", in hellcreek_port_set_mcast_flood()
635 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_mcast_flood()
637 hellcreek_select_port(hellcreek, port); in hellcreek_port_set_mcast_flood()
643 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_set_mcast_flood()
646 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_mcast_flood()
663 struct hellcreek *hellcreek = ds->priv; in hellcreek_bridge_flags() local
666 hellcreek_port_set_ucast_flood(hellcreek, port, in hellcreek_bridge_flags()
670 hellcreek_port_set_mcast_flood(hellcreek, port, in hellcreek_bridge_flags()
679 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_bridge_join() local
681 dev_dbg(hellcreek->dev, "Port %d joins a bridge\n", port); in hellcreek_port_bridge_join()
685 hellcreek_setup_vlan_awareness(hellcreek, false); in hellcreek_port_bridge_join()
696 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_bridge_leave() local
698 dev_dbg(hellcreek->dev, "Port %d leaves a bridge\n", port); in hellcreek_port_bridge_leave()
701 hellcreek_setup_vlan_awareness(hellcreek, true); in hellcreek_port_bridge_leave()
707 static int __hellcreek_fdb_add(struct hellcreek *hellcreek, in __hellcreek_fdb_add() argument
712 dev_dbg(hellcreek->dev, "Add static FDB entry: MAC=%pM, MASK=0x%02x, " in __hellcreek_fdb_add()
717 hellcreek_write(hellcreek, entry->mac[1] | (entry->mac[0] << 8), HR_FDBWDH); in __hellcreek_fdb_add()
718 hellcreek_write(hellcreek, entry->mac[3] | (entry->mac[2] << 8), HR_FDBWDM); in __hellcreek_fdb_add()
719 hellcreek_write(hellcreek, entry->mac[5] | (entry->mac[4] << 8), HR_FDBWDL); in __hellcreek_fdb_add()
729 hellcreek_write(hellcreek, meta, HR_FDBWRM0); in __hellcreek_fdb_add()
732 hellcreek_write(hellcreek, 0x00, HR_FDBWRCMD); in __hellcreek_fdb_add()
735 return hellcreek_wait_fdb_ready(hellcreek); in __hellcreek_fdb_add()
738 static int __hellcreek_fdb_del(struct hellcreek *hellcreek, in __hellcreek_fdb_del() argument
741 dev_dbg(hellcreek->dev, "Delete FDB entry: MAC=%pM!\n", entry->mac); in __hellcreek_fdb_del()
744 hellcreek_write(hellcreek, entry->idx | HR_FDBWRCMD_FDBDEL, HR_FDBWRCMD); in __hellcreek_fdb_del()
747 return hellcreek_wait_fdb_ready(hellcreek); in __hellcreek_fdb_del()
750 static void hellcreek_populate_fdb_entry(struct hellcreek *hellcreek, in hellcreek_populate_fdb_entry() argument
758 meta = hellcreek_read(hellcreek, HR_FDBMDRD); in hellcreek_populate_fdb_entry()
759 mac = hellcreek_read(hellcreek, HR_FDBRDL); in hellcreek_populate_fdb_entry()
762 mac = hellcreek_read(hellcreek, HR_FDBRDM); in hellcreek_populate_fdb_entry()
765 mac = hellcreek_read(hellcreek, HR_FDBRDH); in hellcreek_populate_fdb_entry()
788 static int hellcreek_fdb_get(struct hellcreek *hellcreek, in hellcreek_fdb_get() argument
798 hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_fdb_get()
799 hellcreek_write(hellcreek, 0x00, HR_FDBMAX); in hellcreek_fdb_get()
804 for (i = 0; i < hellcreek->fdb_entries; ++i) { in hellcreek_fdb_get()
808 hellcreek_populate_fdb_entry(hellcreek, &tmp, i); in hellcreek_fdb_get()
811 hellcreek_write(hellcreek, 0x00, HR_FDBRDH); in hellcreek_fdb_get()
829 struct hellcreek *hellcreek = ds->priv; in hellcreek_fdb_add() local
832 dev_dbg(hellcreek->dev, "Add FDB entry for MAC=%pM\n", addr); in hellcreek_fdb_add()
834 mutex_lock(&hellcreek->reg_lock); in hellcreek_fdb_add()
836 ret = hellcreek_fdb_get(hellcreek, addr, &entry); in hellcreek_fdb_add()
842 ret = __hellcreek_fdb_add(hellcreek, &entry); in hellcreek_fdb_add()
844 dev_err(hellcreek->dev, "Failed to add FDB entry!\n"); in hellcreek_fdb_add()
849 ret = __hellcreek_fdb_del(hellcreek, &entry); in hellcreek_fdb_add()
851 dev_err(hellcreek->dev, "Failed to delete FDB entry!\n"); in hellcreek_fdb_add()
857 ret = __hellcreek_fdb_add(hellcreek, &entry); in hellcreek_fdb_add()
859 dev_err(hellcreek->dev, "Failed to add FDB entry!\n"); in hellcreek_fdb_add()
865 mutex_unlock(&hellcreek->reg_lock); in hellcreek_fdb_add()
874 struct hellcreek *hellcreek = ds->priv; in hellcreek_fdb_del() local
877 dev_dbg(hellcreek->dev, "Delete FDB entry for MAC=%pM\n", addr); in hellcreek_fdb_del()
879 mutex_lock(&hellcreek->reg_lock); in hellcreek_fdb_del()
881 ret = hellcreek_fdb_get(hellcreek, addr, &entry); in hellcreek_fdb_del()
884 dev_err(hellcreek->dev, "FDB entry for deletion not found!\n"); in hellcreek_fdb_del()
887 ret = __hellcreek_fdb_del(hellcreek, &entry); in hellcreek_fdb_del()
889 dev_err(hellcreek->dev, "Failed to delete FDB entry!\n"); in hellcreek_fdb_del()
896 ret = __hellcreek_fdb_add(hellcreek, &entry); in hellcreek_fdb_del()
898 dev_err(hellcreek->dev, "Failed to add FDB entry!\n"); in hellcreek_fdb_del()
905 mutex_unlock(&hellcreek->reg_lock); in hellcreek_fdb_del()
913 struct hellcreek *hellcreek = ds->priv; in hellcreek_fdb_dump() local
918 mutex_lock(&hellcreek->reg_lock); in hellcreek_fdb_dump()
924 entries = hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_fdb_dump()
925 hellcreek_write(hellcreek, 0x00, HR_FDBMAX); in hellcreek_fdb_dump()
927 dev_dbg(hellcreek->dev, "FDB dump for port %d, entries=%d!\n", port, entries); in hellcreek_fdb_dump()
930 for (i = 0; i < hellcreek->fdb_entries; ++i) { in hellcreek_fdb_dump()
934 hellcreek_populate_fdb_entry(hellcreek, &entry, i); in hellcreek_fdb_dump()
937 hellcreek_write(hellcreek, 0x00, HR_FDBRDH); in hellcreek_fdb_dump()
952 mutex_unlock(&hellcreek->reg_lock); in hellcreek_fdb_dump()
961 struct hellcreek *hellcreek = ds->priv; in hellcreek_vlan_filtering() local
963 dev_dbg(hellcreek->dev, "%s VLAN filtering on port %d\n", in hellcreek_vlan_filtering()
967 hellcreek_setup_ingressflt(hellcreek, port, vlan_filtering); in hellcreek_vlan_filtering()
972 hellcreek_setup_vlan_awareness(hellcreek, vlan_filtering); in hellcreek_vlan_filtering()
977 static int hellcreek_enable_ip_core(struct hellcreek *hellcreek) in hellcreek_enable_ip_core() argument
982 mutex_lock(&hellcreek->reg_lock); in hellcreek_enable_ip_core()
984 val = hellcreek_read(hellcreek, HR_CTRL_C); in hellcreek_enable_ip_core()
986 hellcreek_write(hellcreek, val, HR_CTRL_C); in hellcreek_enable_ip_core()
987 ret = hellcreek_wait_until_transitioned(hellcreek); in hellcreek_enable_ip_core()
989 mutex_unlock(&hellcreek->reg_lock); in hellcreek_enable_ip_core()
994 static void hellcreek_setup_cpu_and_tunnel_port(struct hellcreek *hellcreek) in hellcreek_setup_cpu_and_tunnel_port() argument
996 struct hellcreek_port *tunnel_port = &hellcreek->ports[TUNNEL_PORT]; in hellcreek_setup_cpu_and_tunnel_port()
997 struct hellcreek_port *cpu_port = &hellcreek->ports[CPU_PORT]; in hellcreek_setup_cpu_and_tunnel_port()
1002 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_cpu_and_tunnel_port()
1004 hellcreek_select_port(hellcreek, CPU_PORT); in hellcreek_setup_cpu_and_tunnel_port()
1005 hellcreek_write(hellcreek, ptcfg, HR_PTCFG); in hellcreek_setup_cpu_and_tunnel_port()
1007 hellcreek_select_port(hellcreek, TUNNEL_PORT); in hellcreek_setup_cpu_and_tunnel_port()
1008 hellcreek_write(hellcreek, ptcfg, HR_PTCFG); in hellcreek_setup_cpu_and_tunnel_port()
1013 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_cpu_and_tunnel_port()
1016 static void hellcreek_setup_tc_identity_mapping(struct hellcreek *hellcreek) in hellcreek_setup_tc_identity_mapping() argument
1039 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_tc_identity_mapping()
1041 hellcreek_select_prio(hellcreek, i); in hellcreek_setup_tc_identity_mapping()
1042 hellcreek_write(hellcreek, in hellcreek_setup_tc_identity_mapping()
1046 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_tc_identity_mapping()
1050 static int hellcreek_setup_fdb(struct hellcreek *hellcreek) in hellcreek_setup_fdb() argument
1076 mutex_lock(&hellcreek->reg_lock); in hellcreek_setup_fdb()
1077 ret = __hellcreek_fdb_add(hellcreek, &ptp); in hellcreek_setup_fdb()
1080 ret = __hellcreek_fdb_add(hellcreek, &p2p); in hellcreek_setup_fdb()
1082 mutex_unlock(&hellcreek->reg_lock); in hellcreek_setup_fdb()
1091 struct hellcreek *hellcreek = ds->priv; in hellcreek_devlink_info_get() local
1094 ret = devlink_info_driver_name_put(req, "hellcreek"); in hellcreek_devlink_info_get()
1100 hellcreek->pdata->name); in hellcreek_devlink_info_get()
1105 struct hellcreek *hellcreek = priv; in hellcreek_devlink_vlan_table_get() local
1109 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_vlan_table_get()
1111 if (hellcreek->vidmbrcfg[i]) in hellcreek_devlink_vlan_table_get()
1113 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_vlan_table_get()
1120 struct hellcreek *hellcreek = priv; in hellcreek_devlink_fdb_table_get() local
1126 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_fdb_table_get()
1127 count = hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_devlink_fdb_table_get()
1128 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_fdb_table_get()
1137 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup_devlink_resources() local
1145 hellcreek->fdb_entries, in hellcreek_setup_devlink_resources()
1146 hellcreek->fdb_entries, in hellcreek_setup_devlink_resources()
1156 err = dsa_devlink_resource_register(ds, "FDB", hellcreek->fdb_entries, in hellcreek_setup_devlink_resources()
1166 hellcreek); in hellcreek_setup_devlink_resources()
1171 hellcreek); in hellcreek_setup_devlink_resources()
1188 struct hellcreek *hellcreek = ds->priv; in hellcreek_devlink_region_vlan_snapshot() local
1197 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_region_vlan_snapshot()
1199 entry->member = hellcreek->vidmbrcfg[i]; in hellcreek_devlink_region_vlan_snapshot()
1202 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_region_vlan_snapshot()
1216 struct hellcreek *hellcreek = ds->priv; in hellcreek_devlink_region_fdb_snapshot() local
1219 table = kcalloc(hellcreek->fdb_entries, sizeof(*entry), GFP_KERNEL); in hellcreek_devlink_region_fdb_snapshot()
1225 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_region_fdb_snapshot()
1228 hellcreek_read(hellcreek, HR_FDBMAX); in hellcreek_devlink_region_fdb_snapshot()
1229 hellcreek_write(hellcreek, 0x00, HR_FDBMAX); in hellcreek_devlink_region_fdb_snapshot()
1231 for (i = 0; i < hellcreek->fdb_entries; ++i, ++entry) { in hellcreek_devlink_region_fdb_snapshot()
1233 hellcreek_populate_fdb_entry(hellcreek, entry, i); in hellcreek_devlink_region_fdb_snapshot()
1236 hellcreek_write(hellcreek, 0x00, HR_FDBRDH); in hellcreek_devlink_region_fdb_snapshot()
1239 mutex_unlock(&hellcreek->reg_lock); in hellcreek_devlink_region_fdb_snapshot()
1260 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup_devlink_regions() local
1274 hellcreek->vlan_region = region; in hellcreek_setup_devlink_regions()
1277 size = hellcreek->fdb_entries * sizeof(struct hellcreek_fdb_entry); in hellcreek_setup_devlink_regions()
1286 hellcreek->fdb_region = region; in hellcreek_setup_devlink_regions()
1291 dsa_devlink_region_destroy(hellcreek->vlan_region); in hellcreek_setup_devlink_regions()
1298 struct hellcreek *hellcreek = ds->priv; in hellcreek_teardown_devlink_regions() local
1300 dsa_devlink_region_destroy(hellcreek->fdb_region); in hellcreek_teardown_devlink_regions()
1301 dsa_devlink_region_destroy(hellcreek->vlan_region); in hellcreek_teardown_devlink_regions()
1306 struct hellcreek *hellcreek = ds->priv; in hellcreek_setup() local
1310 dev_dbg(hellcreek->dev, "Set up the switch\n"); in hellcreek_setup()
1313 ret = hellcreek_enable_ip_core(hellcreek); in hellcreek_setup()
1315 dev_err(hellcreek->dev, "Failed to enable IP core!\n"); in hellcreek_setup()
1320 hellcreek_setup_cpu_and_tunnel_port(hellcreek); in hellcreek_setup()
1330 hellcreek->swcfg = swcfg; in hellcreek_setup()
1331 hellcreek_write(hellcreek, swcfg, HR_SWCFG); in hellcreek_setup()
1342 hellcreek_setup_tc_identity_mapping(hellcreek); in hellcreek_setup()
1351 ret = hellcreek_setup_fdb(hellcreek); in hellcreek_setup()
1353 dev_err(hellcreek->dev, in hellcreek_setup()
1361 dev_err(hellcreek->dev, in hellcreek_setup()
1368 dev_err(hellcreek->dev, in hellcreek_setup()
1392 struct hellcreek *hellcreek = ds->priv; in hellcreek_phylink_validate() local
1394 dev_dbg(hellcreek->dev, "Phylink validate for port %d\n", port); in hellcreek_phylink_validate()
1401 if (hellcreek->pdata->is_100_mbits) in hellcreek_phylink_validate()
1416 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_prechangeupper() local
1422 dev_dbg(hellcreek->dev, "Pre change upper for port %d\n", port); in hellcreek_port_prechangeupper()
1438 mutex_lock(&hellcreek->vlan_lock); in hellcreek_port_prechangeupper()
1439 for (i = 0; i < hellcreek->pdata->num_ports; ++i) { in hellcreek_port_prechangeupper()
1446 used = used && test_bit(vid, hellcreek->ports[i].vlan_dev_bitmap); in hellcreek_port_prechangeupper()
1453 set_bit(vid, hellcreek->ports[port].vlan_dev_bitmap); in hellcreek_port_prechangeupper()
1458 mutex_unlock(&hellcreek->vlan_lock); in hellcreek_port_prechangeupper()
1463 static void hellcreek_setup_gcl(struct hellcreek *hellcreek, int port, in hellcreek_setup_gcl() argument
1489 hellcreek_write(hellcreek, data, TR_GCLDAT); in hellcreek_setup_gcl()
1492 hellcreek_write(hellcreek, in hellcreek_setup_gcl()
1495 hellcreek_write(hellcreek, in hellcreek_setup_gcl()
1503 hellcreek_write(hellcreek, data, TR_GCLCMD); in hellcreek_setup_gcl()
1510 static void hellcreek_set_cycle_time(struct hellcreek *hellcreek, in hellcreek_set_cycle_time() argument
1515 hellcreek_write(hellcreek, cycle_time & 0x0000ffff, TR_CTWRL); in hellcreek_set_cycle_time()
1516 hellcreek_write(hellcreek, (cycle_time & 0xffff0000) >> 16, TR_CTWRH); in hellcreek_set_cycle_time()
1519 static void hellcreek_switch_schedule(struct hellcreek *hellcreek, in hellcreek_switch_schedule() argument
1525 hellcreek_write(hellcreek, ts.tv_nsec & 0x0000ffff, TR_ESTWRL); in hellcreek_switch_schedule()
1526 hellcreek_write(hellcreek, (ts.tv_nsec & 0xffff0000) >> 16, TR_ESTWRH); in hellcreek_switch_schedule()
1529 hellcreek_write(hellcreek, TR_ESTCMD_ESTARM | TR_ESTCMD_ESTSWCFG | in hellcreek_switch_schedule()
1534 static bool hellcreek_schedule_startable(struct hellcreek *hellcreek, int port) in hellcreek_schedule_startable() argument
1536 struct hellcreek_port *hellcreek_port = &hellcreek->ports[port]; in hellcreek_schedule_startable()
1547 mutex_lock(&hellcreek->ptp_lock); in hellcreek_schedule_startable()
1548 current_ns = hellcreek->seconds * NSEC_PER_SEC + hellcreek->last_ts; in hellcreek_schedule_startable()
1549 mutex_unlock(&hellcreek->ptp_lock); in hellcreek_schedule_startable()
1557 static void hellcreek_start_schedule(struct hellcreek *hellcreek, int port) in hellcreek_start_schedule() argument
1559 struct hellcreek_port *hellcreek_port = &hellcreek->ports[port]; in hellcreek_start_schedule()
1565 hellcreek_select_tgd(hellcreek, port); in hellcreek_start_schedule()
1568 mutex_lock(&hellcreek->ptp_lock); in hellcreek_start_schedule()
1569 current_ns = hellcreek->seconds * NSEC_PER_SEC + hellcreek->last_ts; in hellcreek_start_schedule()
1570 mutex_unlock(&hellcreek->ptp_lock); in hellcreek_start_schedule()
1585 hellcreek_switch_schedule(hellcreek, base_time); in hellcreek_start_schedule()
1590 dev_dbg(hellcreek->dev, "Armed EST timer for port %d\n", in hellcreek_start_schedule()
1598 struct hellcreek *hellcreek; in hellcreek_check_schedule() local
1602 hellcreek = hellcreek_port->hellcreek; in hellcreek_check_schedule()
1604 mutex_lock(&hellcreek->reg_lock); in hellcreek_check_schedule()
1607 startable = hellcreek_schedule_startable(hellcreek, in hellcreek_check_schedule()
1610 hellcreek_start_schedule(hellcreek, hellcreek_port->port); in hellcreek_check_schedule()
1611 mutex_unlock(&hellcreek->reg_lock); in hellcreek_check_schedule()
1615 mutex_unlock(&hellcreek->reg_lock); in hellcreek_check_schedule()
1625 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_set_schedule() local
1630 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_set_schedule()
1632 dev_dbg(hellcreek->dev, "Configure traffic schedule on port %d\n", in hellcreek_port_set_schedule()
1638 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1647 hellcreek_select_tgd(hellcreek, port); in hellcreek_port_set_schedule()
1651 hellcreek_write(hellcreek, ctrl, TR_TGDCTRL); in hellcreek_port_set_schedule()
1654 hellcreek_write(hellcreek, 0x00, TR_ESTCMD); in hellcreek_port_set_schedule()
1657 hellcreek_setup_gcl(hellcreek, port, hellcreek_port->current_schedule); in hellcreek_port_set_schedule()
1660 hellcreek_set_cycle_time(hellcreek, hellcreek_port->current_schedule); in hellcreek_port_set_schedule()
1663 startable = hellcreek_schedule_startable(hellcreek, port); in hellcreek_port_set_schedule()
1665 hellcreek_start_schedule(hellcreek, port); in hellcreek_port_set_schedule()
1666 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1670 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1681 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_del_schedule() local
1684 hellcreek_port = &hellcreek->ports[port]; in hellcreek_port_del_schedule()
1686 dev_dbg(hellcreek->dev, "Remove traffic schedule on port %d\n", port); in hellcreek_port_del_schedule()
1691 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_del_schedule()
1699 hellcreek_select_tgd(hellcreek, port); in hellcreek_port_del_schedule()
1702 hellcreek_write(hellcreek, 0xff << TR_TGDCTRL_ADMINGATESTATES_SHIFT, in hellcreek_port_del_schedule()
1705 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_del_schedule()
1710 static bool hellcreek_validate_schedule(struct hellcreek *hellcreek, in hellcreek_validate_schedule() argument
1715 /* Does this hellcreek version support Qbv in hardware? */ in hellcreek_validate_schedule()
1716 if (!hellcreek->pdata->qbv_support) in hellcreek_validate_schedule()
1739 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_setup_tc() local
1744 if (!hellcreek_validate_schedule(hellcreek, taprio)) in hellcreek_port_setup_tc()
1787 struct hellcreek *hellcreek; in hellcreek_probe() local
1791 hellcreek = devm_kzalloc(dev, sizeof(*hellcreek), GFP_KERNEL); in hellcreek_probe()
1792 if (!hellcreek) in hellcreek_probe()
1795 hellcreek->vidmbrcfg = devm_kcalloc(dev, VLAN_N_VID, in hellcreek_probe()
1796 sizeof(*hellcreek->vidmbrcfg), in hellcreek_probe()
1798 if (!hellcreek->vidmbrcfg) in hellcreek_probe()
1801 hellcreek->pdata = of_device_get_match_data(dev); in hellcreek_probe()
1803 hellcreek->ports = devm_kcalloc(dev, hellcreek->pdata->num_ports, in hellcreek_probe()
1804 sizeof(*hellcreek->ports), in hellcreek_probe()
1806 if (!hellcreek->ports) in hellcreek_probe()
1809 for (i = 0; i < hellcreek->pdata->num_ports; ++i) { in hellcreek_probe()
1810 struct hellcreek_port *port = &hellcreek->ports[i]; in hellcreek_probe()
1828 port->hellcreek = hellcreek; in hellcreek_probe()
1835 mutex_init(&hellcreek->reg_lock); in hellcreek_probe()
1836 mutex_init(&hellcreek->vlan_lock); in hellcreek_probe()
1837 mutex_init(&hellcreek->ptp_lock); in hellcreek_probe()
1839 hellcreek->dev = dev; in hellcreek_probe()
1847 hellcreek->base = devm_ioremap_resource(dev, res); in hellcreek_probe()
1848 if (IS_ERR(hellcreek->base)) in hellcreek_probe()
1849 return PTR_ERR(hellcreek->base); in hellcreek_probe()
1857 hellcreek->ptp_base = devm_ioremap_resource(dev, res); in hellcreek_probe()
1858 if (IS_ERR(hellcreek->ptp_base)) in hellcreek_probe()
1859 return PTR_ERR(hellcreek->ptp_base); in hellcreek_probe()
1861 ret = hellcreek_detect(hellcreek); in hellcreek_probe()
1867 ret = hellcreek_wait_until_ready(hellcreek); in hellcreek_probe()
1873 hellcreek_feature_detect(hellcreek); in hellcreek_probe()
1875 hellcreek->ds = devm_kzalloc(dev, sizeof(*hellcreek->ds), GFP_KERNEL); in hellcreek_probe()
1876 if (!hellcreek->ds) in hellcreek_probe()
1879 hellcreek->ds->dev = dev; in hellcreek_probe()
1880 hellcreek->ds->priv = hellcreek; in hellcreek_probe()
1881 hellcreek->ds->ops = &hellcreek_ds_ops; in hellcreek_probe()
1882 hellcreek->ds->num_ports = hellcreek->pdata->num_ports; in hellcreek_probe()
1883 hellcreek->ds->num_tx_queues = HELLCREEK_NUM_EGRESS_QUEUES; in hellcreek_probe()
1885 ret = dsa_register_switch(hellcreek->ds); in hellcreek_probe()
1891 ret = hellcreek_ptp_setup(hellcreek); in hellcreek_probe()
1897 ret = hellcreek_hwtstamp_setup(hellcreek); in hellcreek_probe()
1903 platform_set_drvdata(pdev, hellcreek); in hellcreek_probe()
1908 hellcreek_ptp_free(hellcreek); in hellcreek_probe()
1910 dsa_unregister_switch(hellcreek->ds); in hellcreek_probe()
1917 struct hellcreek *hellcreek = platform_get_drvdata(pdev); in hellcreek_remove() local
1919 if (!hellcreek) in hellcreek_remove()
1922 hellcreek_hwtstamp_free(hellcreek); in hellcreek_remove()
1923 hellcreek_ptp_free(hellcreek); in hellcreek_remove()
1924 dsa_unregister_switch(hellcreek->ds); in hellcreek_remove()
1932 struct hellcreek *hellcreek = platform_get_drvdata(pdev); in hellcreek_shutdown() local
1934 if (!hellcreek) in hellcreek_shutdown()
1937 dsa_switch_shutdown(hellcreek->ds); in hellcreek_shutdown()
1954 .compatible = "hirschmann,hellcreek-de1soc-r1",
1966 .name = "hellcreek",
1973 MODULE_DESCRIPTION("Hirschmann Hellcreek driver");