Lines Matching +full:hellcreek +full:- +full:de1soc +full:- +full:r1

1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
4 * Hirschmann Hellcreek TSN switch.
6 * Copyright (C) 2019-2021 Linutronix GmbH
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()
214 return -ENODEV; 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()
261 val = hellcreek_port->ptcfg; in hellcreek_port_enable()
263 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_enable()
264 hellcreek_port->ptcfg = val; 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()
284 val = hellcreek_port->ptcfg; in hellcreek_port_disable()
286 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_disable()
287 hellcreek_port->ptcfg = val; 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()
320 u8 offset = counter->offset + port * 64; 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()
336 hellcreek_port->counter_values[i] += value; in hellcreek_get_ethtool_stats()
337 data[i] = hellcreek_port->counter_values[i]; in hellcreek_get_ethtool_stats()
339 mutex_unlock(&hellcreek->reg_lock); in hellcreek_get_ethtool_stats()
345 return VLAN_N_VID - port + 1; in hellcreek_private_vid()
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()
367 if (vlan->vid == restricted_vid) { in hellcreek_vlan_prepare()
369 return -EBUSY; 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()
459 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; in hellcreek_vlan_add()
460 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; in hellcreek_vlan_add()
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()
469 vlan->vid, port, untagged ? "untagged" : "tagged", 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()
500 val = hellcreek_port->ptcfg; 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()
534 hellcreek_port->ptcfg = val; 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()
550 ptcfg = hellcreek_port->ptcfg; 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()
559 hellcreek_port->ptcfg = 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()
618 val = hellcreek_port->ptcfg; in hellcreek_port_set_ucast_flood()
623 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_set_ucast_flood()
624 hellcreek_port->ptcfg = val; 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()
643 val = hellcreek_port->ptcfg; in hellcreek_port_set_mcast_flood()
648 hellcreek_write(hellcreek, val, HR_PTCFG); in hellcreek_port_set_mcast_flood()
649 hellcreek_port->ptcfg = val; in hellcreek_port_set_mcast_flood()
651 mutex_unlock(&hellcreek->reg_lock); in hellcreek_port_set_mcast_flood()
659 return -EINVAL; in hellcreek_pre_bridge_flags()
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()
691 if (!ds->vlan_filtering) 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()
720 "OBT=%d, PASS_BLOCKED=%d, REPRIO_EN=%d, PRIO=%d\n", entry->mac, in __hellcreek_fdb_add()
721 entry->portmask, entry->is_obt, entry->pass_blocked, in __hellcreek_fdb_add()
722 entry->reprio_en, entry->reprio_tc); 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()
730 meta |= entry->portmask << HR_FDBWRM0_PORTMASK_SHIFT; in __hellcreek_fdb_add()
731 if (entry->is_obt) in __hellcreek_fdb_add()
733 if (entry->pass_blocked) in __hellcreek_fdb_add()
735 if (entry->reprio_en) { in __hellcreek_fdb_add()
737 meta |= entry->reprio_tc << HR_FDBWRM0_REPRIO_TC_SHIFT; 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()
780 memcpy(entry->mac, addr, sizeof(addr)); in hellcreek_populate_fdb_entry()
781 entry->idx = idx; in hellcreek_populate_fdb_entry()
782 entry->portmask = (meta & HR_FDBMDRD_PORTMASK_MASK) >> in hellcreek_populate_fdb_entry()
784 entry->age = (meta & HR_FDBMDRD_AGE_MASK) >> in hellcreek_populate_fdb_entry()
786 entry->is_obt = !!(meta & HR_FDBMDRD_OBT); in hellcreek_populate_fdb_entry()
787 entry->pass_blocked = !!(meta & HR_FDBMDRD_PASS_BLOCKED); in hellcreek_populate_fdb_entry()
788 entry->is_static = !!(meta & HR_FDBMDRD_STATIC); in hellcreek_populate_fdb_entry()
789 entry->reprio_tc = (meta & HR_FDBMDRD_REPRIO_TC_MASK) >> in hellcreek_populate_fdb_entry()
791 entry->reprio_en = !!(meta & HR_FDBMDRD_REPRIO_EN); in hellcreek_populate_fdb_entry()
798 static int hellcreek_fdb_get(struct hellcreek *hellcreek, in hellcreek_fdb_get() argument
804 /* Set read pointer to zero: The read of HR_FDBMAX (read-only register) in hellcreek_fdb_get()
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()
832 return -ENOENT; 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()
932 /* Set read pointer to zero: The read of HR_FDBMAX (read-only register) 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()
982 * ds->vlan_filtering_is_global. 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()
1022 cpu_port->ptcfg = ptcfg; in hellcreek_setup_cpu_and_tunnel_port()
1023 tunnel_port->ptcfg = 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
1037 * The default mapping is (PCP - TC): in hellcreek_setup_tc_identity_mapping()
1038 * 7 - 7 in hellcreek_setup_tc_identity_mapping()
1039 * 6 - 6 in hellcreek_setup_tc_identity_mapping()
1040 * 5 - 5 in hellcreek_setup_tc_identity_mapping()
1041 * 4 - 4 in hellcreek_setup_tc_identity_mapping()
1042 * 3 - 3 in hellcreek_setup_tc_identity_mapping()
1043 * 2 - 1 in hellcreek_setup_tc_identity_mapping()
1044 * 1 - 0 in hellcreek_setup_tc_identity_mapping()
1045 * 0 - 2 in hellcreek_setup_tc_identity_mapping()
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
1065 /* MAC: 01-1B-19-00-00-00 */ in hellcreek_setup_fdb()
1076 /* MAC: 01-00-5E-00-01-81 */ in hellcreek_setup_fdb()
1087 /* MAC: 33-33-00-00-01-81 */ in hellcreek_setup_fdb()
1098 /* MAC: 01-80-C2-00-00-0E */ in hellcreek_setup_fdb()
1109 /* MAC: 01-00-5E-00-00-6B */ in hellcreek_setup_fdb()
1120 /* MAC: 33-33-00-00-00-6B */ in hellcreek_setup_fdb()
1131 /* MAC: 01-80-C2-00-00-00 */ in hellcreek_setup_fdb()
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
1270 return -ENOMEM; in hellcreek_devlink_region_vlan_snapshot()
1274 mutex_lock(&hellcreek->reg_lock); in hellcreek_devlink_region_vlan_snapshot()
1276 entry->member = hellcreek->vidmbrcfg[i]; in hellcreek_devlink_region_vlan_snapshot()
1277 entry->vid = 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()
1298 return -ENOMEM; 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()
1411 for (i = 0; i < ds->num_ports; ++i) { in hellcreek_setup()
1418 /* Configure PCP <-> TC mapping */ in hellcreek_setup()
1419 hellcreek_setup_tc_identity_mapping(hellcreek); in hellcreek_setup()
1424 ds->vlan_filtering_is_global = true; in hellcreek_setup()
1425 ds->needs_standalone_vlan_filtering = true; 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
1469 __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); in hellcreek_phylink_get_caps()
1470 __set_bit(PHY_INTERFACE_MODE_RGMII, config->supported_interfaces); in hellcreek_phylink_get_caps()
1472 /* Include GMII - the hardware does not support this interface in hellcreek_phylink_get_caps()
1476 __set_bit(PHY_INTERFACE_MODE_GMII, config->supported_interfaces); in hellcreek_phylink_get_caps()
1483 if (hellcreek->pdata->is_100_mbits) in hellcreek_phylink_get_caps()
1484 config->mac_capabilities = MAC_100FD; in hellcreek_phylink_get_caps()
1486 config->mac_capabilities = MAC_1000FD; in hellcreek_phylink_get_caps()
1493 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_prechangeupper() local
1495 int ret = -EBUSY; in hellcreek_port_prechangeupper()
1499 dev_dbg(hellcreek->dev, "Pre change upper for port %d\n", port); in hellcreek_port_prechangeupper()
1509 if (!is_vlan_dev(info->upper_dev)) in hellcreek_port_prechangeupper()
1512 vid = vlan_dev_vlan_id(info->upper_dev); 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
1546 u32 max_sdu = schedule->max_sdu[tc] + VLAN_ETH_HLEN - ETH_FCS_LEN; in hellcreek_setup_maxsdu()
1549 if (!schedule->max_sdu[tc]) in hellcreek_setup_maxsdu()
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
1585 cur = initial = &schedule->entries[0]; in hellcreek_setup_gcl()
1588 for (i = 1; i <= schedule->num_entries; ++i) { in hellcreek_setup_gcl()
1592 if (i == schedule->num_entries) in hellcreek_setup_gcl()
1593 gates = initial->gate_mask ^ in hellcreek_setup_gcl()
1594 cur->gate_mask; in hellcreek_setup_gcl()
1596 gates = next->gate_mask ^ in hellcreek_setup_gcl()
1597 cur->gate_mask; in hellcreek_setup_gcl()
1601 if (i == schedule->num_entries) in hellcreek_setup_gcl()
1605 hellcreek_write(hellcreek, data, TR_GCLDAT); in hellcreek_setup_gcl()
1608 hellcreek_write(hellcreek, in hellcreek_setup_gcl()
1609 cur->interval & 0x0000ffff, in hellcreek_setup_gcl()
1611 hellcreek_write(hellcreek, in hellcreek_setup_gcl()
1612 (cur->interval & 0xffff0000) >> 16, in hellcreek_setup_gcl()
1616 data = ((i - 1) << TR_GCLCMD_GCLWRADR_SHIFT) | in hellcreek_setup_gcl()
1617 (initial->gate_mask << 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
1629 u32 cycle_time = schedule->cycle_time; in hellcreek_set_cycle_time()
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()
1668 base_time_ns = ktime_to_ns(hellcreek_port->current_schedule->base_time); in hellcreek_schedule_startable()
1670 return base_time_ns - current_ns < (s64)4 * NSEC_PER_SEC; 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()
1689 base_time = hellcreek_port->current_schedule->base_time; in hellcreek_start_schedule()
1690 cycle_time = hellcreek_port->current_schedule->cycle_time; in hellcreek_start_schedule()
1701 hellcreek_switch_schedule(hellcreek, base_time); in hellcreek_start_schedule()
1703 taprio_offload_free(hellcreek_port->current_schedule); in hellcreek_start_schedule()
1704 hellcreek_port->current_schedule = NULL; in hellcreek_start_schedule()
1706 dev_dbg(hellcreek->dev, "Armed EST timer for port %d\n", in hellcreek_start_schedule()
1707 hellcreek_port->port); 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()
1724 hellcreek_port->port); 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()
1734 schedule_delayed_work(&hellcreek_port->schedule_work, 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()
1752 cancel_delayed_work_sync(&hellcreek_port->schedule_work); in hellcreek_port_set_schedule()
1754 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_set_schedule()
1756 if (hellcreek_port->current_schedule) { in hellcreek_port_set_schedule()
1757 taprio_offload_free(hellcreek_port->current_schedule); in hellcreek_port_set_schedule()
1758 hellcreek_port->current_schedule = NULL; in hellcreek_port_set_schedule()
1760 hellcreek_port->current_schedule = taprio_offload_get(taprio); 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()
1792 schedule_delayed_work(&hellcreek_port->schedule_work, 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()
1808 cancel_delayed_work_sync(&hellcreek_port->schedule_work); in hellcreek_port_del_schedule()
1810 mutex_lock(&hellcreek->reg_lock); in hellcreek_port_del_schedule()
1812 if (hellcreek_port->current_schedule) { in hellcreek_port_del_schedule()
1813 taprio_offload_free(hellcreek_port->current_schedule); in hellcreek_port_del_schedule()
1814 hellcreek_port->current_schedule = NULL; 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()
1842 if (schedule->cycle_time > (u32)-1) in hellcreek_validate_schedule()
1846 if (schedule->cycle_time_extension) in hellcreek_validate_schedule()
1850 for (i = 0; i < schedule->num_entries; ++i) in hellcreek_validate_schedule()
1851 if (schedule->entries[i].command != TC_TAPRIO_CMD_SET_GATES) in hellcreek_validate_schedule()
1859 switch (base->type) { in hellcreek_tc_query_caps()
1861 struct tc_taprio_caps *caps = base->caps; in hellcreek_tc_query_caps()
1863 caps->supports_queue_max_sdu = true; in hellcreek_tc_query_caps()
1868 return -EOPNOTSUPP; in hellcreek_tc_query_caps()
1875 struct hellcreek *hellcreek = ds->priv; in hellcreek_port_setup_tc() local
1883 switch (taprio->cmd) { in hellcreek_port_setup_tc()
1885 if (!hellcreek_validate_schedule(hellcreek, taprio)) in hellcreek_port_setup_tc()
1886 return -EOPNOTSUPP; in hellcreek_port_setup_tc()
1892 return -EOPNOTSUPP; in hellcreek_port_setup_tc()
1896 return -EOPNOTSUPP; in hellcreek_port_setup_tc()
1933 struct device *dev = &pdev->dev; in hellcreek_probe()
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()
1940 return -ENOMEM; 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()
1946 return -ENOMEM; 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()
1954 return -ENOMEM; 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()
1959 port->counter_values = in hellcreek_probe()
1962 sizeof(*port->counter_values), in hellcreek_probe()
1964 if (!port->counter_values) in hellcreek_probe()
1965 return -ENOMEM; in hellcreek_probe()
1967 port->vlan_dev_bitmap = devm_bitmap_zalloc(dev, VLAN_N_VID, in hellcreek_probe()
1969 if (!port->vlan_dev_bitmap) in hellcreek_probe()
1970 return -ENOMEM; in hellcreek_probe()
1972 port->hellcreek = hellcreek; in hellcreek_probe()
1973 port->port = i; in hellcreek_probe()
1975 INIT_DELAYED_WORK(&port->schedule_work, 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()
1988 return -ENODEV; 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()
1998 return -ENODEV; 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()
2021 return -ENOMEM; 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");