Lines Matching +full:cpsw +full:- +full:switch
1 // SPDX-License-Identifier: GPL-2.0
3 * Texas Instruments N-Port Ethernet Switch Address Lookup Engine
23 #define BITMASK(bits) (BIT(bits) - 1)
41 /* ALE NetCP NU switch specific Registers */
54 * struct ale_entry_fld - The ALE tbl entry field description
73 * struct ale_dev_id - The ALE version/SoC specific configuration
78 * @nu_switch_ale: NU Switch ALE
110 start -= idx * 32; in cpsw_ale_get_field()
111 idx = 2 - idx; /* flip */ in cpsw_ale_get_field()
122 start -= idx * 32; in cpsw_ale_set_field()
123 idx = 2 - idx; /* flip */ in cpsw_ale_set_field()
224 return -EINVAL; in cpsw_ale_entry_get_fld()
227 if (!(entry_fld->flags & ALE_FLD_ALLOWED)) { in cpsw_ale_entry_get_fld()
228 dev_err(ale->params.dev, "get: wrong ale fld id %d\n", fld_id); in cpsw_ale_entry_get_fld()
229 return -ENOENT; in cpsw_ale_entry_get_fld()
232 bits = entry_fld->num_bits; in cpsw_ale_entry_get_fld()
233 if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS) in cpsw_ale_entry_get_fld()
234 bits = ale->port_mask_bits; in cpsw_ale_entry_get_fld()
236 return cpsw_ale_get_field(ale_entry, entry_fld->start_bit, bits); in cpsw_ale_entry_get_fld()
252 if (!(entry_fld->flags & ALE_FLD_ALLOWED)) { in cpsw_ale_entry_set_fld()
253 dev_err(ale->params.dev, "set: wrong ale fld id %d\n", fld_id); in cpsw_ale_entry_set_fld()
257 bits = entry_fld->num_bits; in cpsw_ale_entry_set_fld()
258 if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS) in cpsw_ale_entry_set_fld()
259 bits = ale->port_mask_bits; in cpsw_ale_entry_set_fld()
261 cpsw_ale_set_field(ale_entry, entry_fld->start_bit, bits, value); in cpsw_ale_entry_set_fld()
269 ale->vlan_entry_tbl, fld_id); in cpsw_ale_vlan_get_fld()
278 ale->vlan_entry_tbl, fld_id, value); in cpsw_ale_vlan_set_fld()
287 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8); in cpsw_ale_get_addr()
295 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]); in cpsw_ale_set_addr()
302 WARN_ON(idx > ale->params.ale_entries); in cpsw_ale_read()
304 writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL); in cpsw_ale_read()
307 ale_entry[i] = readl_relaxed(ale->params.ale_regs + in cpsw_ale_read()
317 WARN_ON(idx > ale->params.ale_entries); in cpsw_ale_write()
320 writel_relaxed(ale_entry[i], ale->params.ale_regs + in cpsw_ale_write()
323 writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs + in cpsw_ale_write()
334 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_match_addr()
347 return -ENOENT; in cpsw_ale_match_addr()
355 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_match_vlan()
363 return -ENOENT; in cpsw_ale_match_vlan()
371 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_match_free()
377 return -ENOENT; in cpsw_ale_match_free()
385 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_find_ageable()
397 return -ENOENT; in cpsw_ale_find_ageable()
406 ale->port_mask_bits); in cpsw_ale_flush_mcast()
414 ale->port_mask_bits); in cpsw_ale_flush_mcast()
424 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_flush_multicast()
430 /* if vid passed is -1 then remove all multicast entry from in cpsw_ale_flush_multicast()
435 if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid) in cpsw_ale_flush_multicast()
477 cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits); in cpsw_ale_add_ucast()
485 return -ENOMEM; in cpsw_ale_add_ucast()
499 return -ENOENT; in cpsw_ale_del_ucast()
523 ale->port_mask_bits); in cpsw_ale_add_mcast()
526 ale->port_mask_bits); in cpsw_ale_add_mcast()
533 return -ENOMEM; in cpsw_ale_add_mcast()
548 return -ENOENT; in cpsw_ale_del_mcast()
554 ale->port_mask_bits); in cpsw_ale_del_mcast()
560 ale->port_mask_bits); in cpsw_ale_del_mcast()
568 /* ALE NetCP NU switch specific vlan functions */
577 writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx)); in cpsw_ale_set_vlan_mcast()
582 writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx)); in cpsw_ale_set_vlan_mcast()
592 bitmap_set(ale->p0_untag_vid_mask, vid, 1); in cpsw_ale_set_vlan_untag()
594 bitmap_clear(ale->p0_untag_vid_mask, vid, 1); in cpsw_ale_set_vlan_untag()
611 if (!ale->params.nu_switch_ale) { in cpsw_ale_add_vlan()
631 return -ENOMEM; in cpsw_ale_add_vlan()
663 if (!ale->params.nu_switch_ale) { in cpsw_ale_del_vlan_modify()
683 return -ENOENT; in cpsw_ale_del_vlan()
729 dev_err(ale->params.dev, "Unable to add vlan\n"); in cpsw_ale_vlan_add_modify()
732 dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members, in cpsw_ale_vlan_add_modify()
745 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_set_unreg_mcast()
791 unreg_mcast = readl(ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx)); in cpsw_ale_vlan_set_unreg_mcast_idx()
798 writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx)); in cpsw_ale_vlan_set_unreg_mcast_idx()
806 for (idx = 0; idx < ale->params.ale_entries; idx++) { in cpsw_ale_set_allmulti()
817 if (port != -1 && !(vlan_members & BIT(port))) in cpsw_ale_set_allmulti()
820 if (!ale->params.nu_switch_ale) in cpsw_ale_set_allmulti()
1064 return -EINVAL; in cpsw_ale_control_set()
1067 if (info->port_offset == 0 && info->port_shift == 0) in cpsw_ale_control_set()
1070 if (port < 0 || port >= ale->params.ale_ports) in cpsw_ale_control_set()
1071 return -EINVAL; in cpsw_ale_control_set()
1073 mask = BITMASK(info->bits); in cpsw_ale_control_set()
1075 return -EINVAL; in cpsw_ale_control_set()
1077 offset = info->offset + (port * info->port_offset); in cpsw_ale_control_set()
1078 shift = info->shift + (port * info->port_shift); in cpsw_ale_control_set()
1080 tmp = readl_relaxed(ale->params.ale_regs + offset); in cpsw_ale_control_set()
1082 writel_relaxed(tmp, ale->params.ale_regs + offset); in cpsw_ale_control_set()
1094 return -EINVAL; in cpsw_ale_control_get()
1097 if (info->port_offset == 0 && info->port_shift == 0) in cpsw_ale_control_get()
1100 if (port < 0 || port >= ale->params.ale_ports) in cpsw_ale_control_get()
1101 return -EINVAL; in cpsw_ale_control_get()
1103 offset = info->offset + (port * info->port_offset); in cpsw_ale_control_get()
1104 shift = info->shift + (port * info->port_shift); in cpsw_ale_control_get()
1106 tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift; in cpsw_ale_control_get()
1107 return tmp & BITMASK(info->bits); in cpsw_ale_control_get()
1116 if (ale->ageout) { in cpsw_ale_timer()
1117 ale->timer.expires = jiffies + ale->ageout; in cpsw_ale_timer()
1118 add_timer(&ale->timer); in cpsw_ale_timer()
1126 aging_timer = ale->params.bus_freq / 1000000; in cpsw_ale_hw_aging_timer_start()
1127 aging_timer *= ale->params.ale_ageout; in cpsw_ale_hw_aging_timer_start()
1131 dev_warn(ale->params.dev, in cpsw_ale_hw_aging_timer_start()
1135 writel(aging_timer, ale->params.ale_regs + ALE_AGING_TIMER); in cpsw_ale_hw_aging_timer_start()
1140 writel(0, ale->params.ale_regs + ALE_AGING_TIMER); in cpsw_ale_hw_aging_timer_stop()
1145 if (!ale->params.ale_ageout) in cpsw_ale_aging_start()
1148 if (ale->features & CPSW_ALE_F_HW_AUTOAGING) { in cpsw_ale_aging_start()
1153 timer_setup(&ale->timer, cpsw_ale_timer, 0); in cpsw_ale_aging_start()
1154 ale->timer.expires = jiffies + ale->ageout; in cpsw_ale_aging_start()
1155 add_timer(&ale->timer); in cpsw_ale_aging_start()
1160 if (!ale->params.ale_ageout) in cpsw_ale_aging_stop()
1163 if (ale->features & CPSW_ALE_F_HW_AUTOAGING) { in cpsw_ale_aging_stop()
1168 del_timer_sync(&ale->timer); in cpsw_ale_aging_stop()
1188 /* am3/4/5, dra7. dm814x, 66ak2hk-gbe */
1189 .dev_id = "cpsw",
1196 .dev_id = "66ak2h-xgbe",
1217 .dev_id = "am65x-cpsw2g",
1225 .dev_id = "j721e-cpswxg",
1240 while (id->dev_id) { in cpsw_ale_match_id()
1241 if (strcmp(dev_id, id->dev_id) == 0) in cpsw_ale_match_id()
1254 ale_dev_id = cpsw_ale_match_id(cpsw_ale_id_match, params->dev_id); in cpsw_ale_create()
1256 return ERR_PTR(-EINVAL); in cpsw_ale_create()
1258 params->ale_entries = ale_dev_id->tbl_entries; in cpsw_ale_create()
1259 params->major_ver_mask = ale_dev_id->major_ver_mask; in cpsw_ale_create()
1260 params->nu_switch_ale = ale_dev_id->nu_switch_ale; in cpsw_ale_create()
1262 ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL); in cpsw_ale_create()
1264 return ERR_PTR(-ENOMEM); in cpsw_ale_create()
1266 ale->p0_untag_vid_mask = in cpsw_ale_create()
1267 devm_kmalloc_array(params->dev, BITS_TO_LONGS(VLAN_N_VID), in cpsw_ale_create()
1270 if (!ale->p0_untag_vid_mask) in cpsw_ale_create()
1271 return ERR_PTR(-ENOMEM); in cpsw_ale_create()
1273 ale->params = *params; in cpsw_ale_create()
1274 ale->ageout = ale->params.ale_ageout * HZ; in cpsw_ale_create()
1275 ale->features = ale_dev_id->features; in cpsw_ale_create()
1276 ale->vlan_entry_tbl = ale_dev_id->vlan_entry_tbl; in cpsw_ale_create()
1278 rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER); in cpsw_ale_create()
1279 ale->version = in cpsw_ale_create()
1280 (ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) | in cpsw_ale_create()
1282 dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n", in cpsw_ale_create()
1283 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask), in cpsw_ale_create()
1286 if (ale->features & CPSW_ALE_F_STATUS_REG && in cpsw_ale_create()
1287 !ale->params.ale_entries) { in cpsw_ale_create()
1289 readl_relaxed(ale->params.ale_regs + ALE_STATUS) & in cpsw_ale_create()
1299 return ERR_PTR(-EINVAL); in cpsw_ale_create()
1302 ale->params.ale_entries = ale_entries; in cpsw_ale_create()
1304 dev_info(ale->params.dev, in cpsw_ale_create()
1305 "ALE Table size %ld\n", ale->params.ale_entries); in cpsw_ale_create()
1308 ale->port_mask_bits = ale->params.ale_ports; in cpsw_ale_create()
1309 ale->port_num_bits = order_base_2(ale->params.ale_ports); in cpsw_ale_create()
1310 ale->vlan_field_bits = ale->params.ale_ports; in cpsw_ale_create()
1312 /* Set defaults override for ALE on NetCP NU switch and for version in cpsw_ale_create()
1315 if (ale->params.nu_switch_ale) { in cpsw_ale_create()
1321 ale->params.ale_ports; in cpsw_ale_create()
1325 ale->params.ale_ports; in cpsw_ale_create()
1330 ale->params.ale_ports; in cpsw_ale_create()
1335 ale->params.ale_ports; in cpsw_ale_create()
1349 for (i = 0; i < ale->params.ale_entries; i++) { in cpsw_ale_dump()
1357 return ale ? ale->params.ale_entries : 0; in cpsw_ale_get_num_entries()