Lines Matching refs:a5psw

71 static void a5psw_reg_writel(struct a5psw *a5psw, int offset, u32 value)  in a5psw_reg_writel()  argument
73 writel(value, a5psw->base + offset); in a5psw_reg_writel()
76 static u32 a5psw_reg_readl(struct a5psw *a5psw, int offset) in a5psw_reg_readl() argument
78 return readl(a5psw->base + offset); in a5psw_reg_readl()
81 static void a5psw_reg_rmw(struct a5psw *a5psw, int offset, u32 mask, u32 val) in a5psw_reg_rmw() argument
85 spin_lock(&a5psw->reg_lock); in a5psw_reg_rmw()
87 reg = a5psw_reg_readl(a5psw, offset); in a5psw_reg_rmw()
90 a5psw_reg_writel(a5psw, offset, reg); in a5psw_reg_rmw()
92 spin_unlock(&a5psw->reg_lock); in a5psw_reg_rmw()
102 static void a5psw_port_pattern_set(struct a5psw *a5psw, int port, int pattern, in a5psw_port_pattern_set() argument
110 a5psw_reg_rmw(a5psw, A5PSW_RXMATCH_CONFIG(port), in a5psw_port_pattern_set()
114 static void a5psw_port_mgmtfwd_set(struct a5psw *a5psw, int port, bool enable) in a5psw_port_mgmtfwd_set() argument
120 a5psw_port_pattern_set(a5psw, port, A5PSW_PATTERN_MGMTFWD, enable); in a5psw_port_mgmtfwd_set()
123 static void a5psw_port_tx_enable(struct a5psw *a5psw, int port, bool enable) in a5psw_port_tx_enable() argument
136 a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, mask, reg); in a5psw_port_tx_enable()
139 static void a5psw_port_enable_set(struct a5psw *a5psw, int port, bool enable) in a5psw_port_enable_set() argument
146 a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, A5PSW_PORT_ENA_TX_RX(port), in a5psw_port_enable_set()
150 static int a5psw_lk_execute_ctrl(struct a5psw *a5psw, u32 *ctrl) in a5psw_lk_execute_ctrl() argument
154 a5psw_reg_writel(a5psw, A5PSW_LK_ADDR_CTRL, *ctrl); in a5psw_lk_execute_ctrl()
156 ret = readl_poll_timeout(a5psw->base + A5PSW_LK_ADDR_CTRL, *ctrl, in a5psw_lk_execute_ctrl()
160 dev_err(a5psw->dev, "LK_CTRL timeout waiting for BUSY bit\n"); in a5psw_lk_execute_ctrl()
165 static void a5psw_port_fdb_flush(struct a5psw *a5psw, int port) in a5psw_port_fdb_flush() argument
169 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_flush()
170 a5psw_lk_execute_ctrl(a5psw, &ctrl); in a5psw_port_fdb_flush()
171 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_flush()
174 static void a5psw_port_authorize_set(struct a5psw *a5psw, int port, in a5psw_port_authorize_set() argument
177 u32 reg = a5psw_reg_readl(a5psw, A5PSW_AUTH_PORT(port)); in a5psw_port_authorize_set()
184 a5psw_reg_writel(a5psw, A5PSW_AUTH_PORT(port), reg); in a5psw_port_authorize_set()
189 struct a5psw *a5psw = ds->priv; in a5psw_port_disable() local
191 a5psw_port_authorize_set(a5psw, port, false); in a5psw_port_disable()
192 a5psw_port_enable_set(a5psw, port, false); in a5psw_port_disable()
198 struct a5psw *a5psw = ds->priv; in a5psw_port_enable() local
200 a5psw_port_authorize_set(a5psw, port, true); in a5psw_port_enable()
201 a5psw_port_enable_set(a5psw, port, true); in a5psw_port_enable()
208 struct a5psw *a5psw = ds->priv; in a5psw_port_change_mtu() local
211 a5psw_reg_writel(a5psw, A5PSW_FRM_LENGTH(port), new_mtu); in a5psw_port_change_mtu()
246 struct a5psw *a5psw = dp->ds->priv; in a5psw_phylink_mac_select_pcs() local
251 return a5psw->pcs[dp->index]; in a5psw_phylink_mac_select_pcs()
265 struct a5psw *a5psw = dp->ds->priv; in a5psw_phylink_mac_link_down() local
269 cmd_cfg = a5psw_reg_readl(a5psw, A5PSW_CMD_CFG(port)); in a5psw_phylink_mac_link_down()
271 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port), cmd_cfg); in a5psw_phylink_mac_link_down()
284 struct a5psw *a5psw = dp->ds->priv; in a5psw_phylink_mac_link_up() local
297 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(dp->index), cmd_cfg); in a5psw_phylink_mac_link_up()
302 struct a5psw *a5psw = ds->priv; in a5psw_set_ageing_time() local
307 rate = clk_get_rate(a5psw->clk); in a5psw_set_ageing_time()
316 a5psw_reg_writel(a5psw, A5PSW_LK_AGETIME, agetime); in a5psw_set_ageing_time()
321 static void a5psw_port_learning_set(struct a5psw *a5psw, int port, bool learn) in a5psw_port_learning_set() argument
326 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg); in a5psw_port_learning_set()
329 static void a5psw_port_rx_block_set(struct a5psw *a5psw, int port, bool block) in a5psw_port_rx_block_set() argument
334 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg); in a5psw_port_rx_block_set()
337 static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port, in a5psw_flooding_set_resolution() argument
345 a5psw_reg_rmw(a5psw, offsets[i], BIT(port), in a5psw_flooding_set_resolution()
349 static void a5psw_port_set_standalone(struct a5psw *a5psw, int port, in a5psw_port_set_standalone() argument
352 a5psw_port_learning_set(a5psw, port, !standalone); in a5psw_port_set_standalone()
353 a5psw_flooding_set_resolution(a5psw, port, !standalone); in a5psw_port_set_standalone()
354 a5psw_port_mgmtfwd_set(a5psw, port, standalone); in a5psw_port_set_standalone()
362 struct a5psw *a5psw = ds->priv; in a5psw_port_bridge_join() local
365 if (a5psw->br_dev && bridge.dev != a5psw->br_dev) { in a5psw_port_bridge_join()
371 a5psw->br_dev = bridge.dev; in a5psw_port_bridge_join()
372 a5psw_port_set_standalone(a5psw, port, false); in a5psw_port_bridge_join()
374 a5psw->bridged_ports |= BIT(port); in a5psw_port_bridge_join()
382 struct a5psw *a5psw = ds->priv; in a5psw_port_bridge_leave() local
384 a5psw->bridged_ports &= ~BIT(port); in a5psw_port_bridge_leave()
386 a5psw_port_set_standalone(a5psw, port, true); in a5psw_port_bridge_leave()
389 if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT)) in a5psw_port_bridge_leave()
390 a5psw->br_dev = NULL; in a5psw_port_bridge_leave()
409 struct a5psw *a5psw = ds->priv; in a5psw_port_bridge_flags() local
419 if (!(a5psw->bridged_ports & BIT(port))) in a5psw_port_bridge_flags()
424 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, in a5psw_port_bridge_flags()
430 a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val); in a5psw_port_bridge_flags()
435 a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val); in a5psw_port_bridge_flags()
440 a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val); in a5psw_port_bridge_flags()
450 struct a5psw *a5psw = ds->priv; in a5psw_port_stp_state_set() local
475 a5psw_port_learning_set(a5psw, port, learning_enabled); in a5psw_port_stp_state_set()
476 a5psw_port_rx_block_set(a5psw, port, !rx_enabled); in a5psw_port_stp_state_set()
477 a5psw_port_tx_enable(a5psw, port, tx_enabled); in a5psw_port_stp_state_set()
482 struct a5psw *a5psw = ds->priv; in a5psw_port_fast_age() local
484 a5psw_port_fdb_flush(a5psw, port); in a5psw_port_fast_age()
487 static int a5psw_lk_execute_lookup(struct a5psw *a5psw, union lk_data *lk_data, in a5psw_lk_execute_lookup() argument
493 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_LO, lk_data->lo); in a5psw_lk_execute_lookup()
494 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data->hi); in a5psw_lk_execute_lookup()
497 ret = a5psw_lk_execute_ctrl(a5psw, &ctrl); in a5psw_lk_execute_lookup()
510 struct a5psw *a5psw = ds->priv; in a5psw_port_fdb_add() local
520 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_add()
523 ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry); in a5psw_port_fdb_add()
527 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI); in a5psw_port_fdb_add()
539 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi); in a5psw_port_fdb_add()
542 ret = a5psw_lk_execute_ctrl(a5psw, &reg); in a5psw_port_fdb_add()
548 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg); in a5psw_port_fdb_add()
552 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_add()
561 struct a5psw *a5psw = ds->priv; in a5psw_port_fdb_del() local
570 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_del()
572 ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry); in a5psw_port_fdb_del()
576 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI); in a5psw_port_fdb_del()
592 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi); in a5psw_port_fdb_del()
600 ret = a5psw_lk_execute_ctrl(a5psw, &reg); in a5psw_port_fdb_del()
607 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg); in a5psw_port_fdb_del()
611 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_del()
619 struct a5psw *a5psw = ds->priv; in a5psw_port_fdb_dump() local
624 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_dump()
629 ret = a5psw_lk_execute_ctrl(a5psw, &reg); in a5psw_port_fdb_dump()
633 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI); in a5psw_port_fdb_dump()
639 lk_data.lo = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_LO); in a5psw_port_fdb_dump()
647 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_dump()
659 struct a5psw *a5psw = ds->priv; in a5psw_port_vlan_filtering() local
662 a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE_ENA, BIT(port), in a5psw_port_vlan_filtering()
666 a5psw_reg_rmw(a5psw, A5PSW_VLAN_VERIFY, mask, val); in a5psw_port_vlan_filtering()
671 static int a5psw_find_vlan_entry(struct a5psw *a5psw, u16 vid) in a5psw_find_vlan_entry() argument
678 vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i)); in a5psw_find_vlan_entry()
686 static int a5psw_new_vlan_res_entry(struct a5psw *a5psw, u16 newvid) in a5psw_new_vlan_res_entry() argument
693 vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i)); in a5psw_new_vlan_res_entry()
696 a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(i), vlan_res); in a5psw_new_vlan_res_entry()
704 static void a5psw_port_vlan_tagged_cfg(struct a5psw *a5psw, in a5psw_port_vlan_tagged_cfg() argument
717 a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK); in a5psw_port_vlan_tagged_cfg()
718 reg = a5psw_reg_readl(a5psw, vlan_res_off); in a5psw_port_vlan_tagged_cfg()
719 a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK); in a5psw_port_vlan_tagged_cfg()
723 a5psw_reg_writel(a5psw, vlan_res_off, reg); in a5psw_port_vlan_tagged_cfg()
726 static void a5psw_port_vlan_cfg(struct a5psw *a5psw, unsigned int vlan_res_id, in a5psw_port_vlan_cfg() argument
735 a5psw_reg_rmw(a5psw, A5PSW_VLAN_RES(vlan_res_id), mask, reg); in a5psw_port_vlan_cfg()
744 struct a5psw *a5psw = ds->priv; in a5psw_port_vlan_add() local
748 vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); in a5psw_port_vlan_add()
750 vlan_res_id = a5psw_new_vlan_res_entry(a5psw, vid); in a5psw_port_vlan_add()
755 a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, true); in a5psw_port_vlan_add()
757 a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, true); in a5psw_port_vlan_add()
764 a5psw_reg_writel(a5psw, A5PSW_SYSTEM_TAGINFO(port), vid); in a5psw_port_vlan_add()
772 struct a5psw *a5psw = ds->priv; in a5psw_port_vlan_del() local
776 vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); in a5psw_port_vlan_del()
780 a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, false); in a5psw_port_vlan_del()
781 a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, false); in a5psw_port_vlan_del()
786 static u64 a5psw_read_stat(struct a5psw *a5psw, u32 offset, int port) in a5psw_read_stat() argument
790 reg_lo = a5psw_reg_readl(a5psw, offset + A5PSW_PORT_OFFSET(port)); in a5psw_read_stat()
792 reg_hi = a5psw_reg_readl(a5psw, A5PSW_STATS_HIWORD); in a5psw_read_stat()
812 struct a5psw *a5psw = ds->priv; in a5psw_get_ethtool_stats() local
816 data[u] = a5psw_read_stat(a5psw, a5psw_stats[u].offset, port); in a5psw_get_ethtool_stats()
830 struct a5psw *a5psw = ds->priv; in a5psw_get_eth_mac_stats() local
832 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port) in a5psw_get_eth_mac_stats()
870 struct a5psw *a5psw = ds->priv; in a5psw_get_rmon_stats() local
872 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port) in a5psw_get_rmon_stats()
892 struct a5psw *a5psw = ds->priv; in a5psw_get_eth_ctrl_stats() local
895 stat = a5psw_read_stat(a5psw, A5PSW_aTxPAUSEMACCtrlFrames, port); in a5psw_get_eth_ctrl_stats()
897 stat = a5psw_read_stat(a5psw, A5PSW_aRxPAUSEMACCtrlFrames, port); in a5psw_get_eth_ctrl_stats()
901 static void a5psw_vlan_setup(struct a5psw *a5psw, int port) in a5psw_vlan_setup() argument
910 a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE, A5PSW_VLAN_IN_MODE_PORT(port), in a5psw_vlan_setup()
918 a5psw_reg_rmw(a5psw, A5PSW_VLAN_OUT_MODE, in a5psw_vlan_setup()
924 struct a5psw *a5psw = ds->priv; in a5psw_setup() local
932 dev_err(a5psw->dev, "Invalid CPU port\n"); in a5psw_setup()
939 a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg); in a5psw_setup()
942 a5psw_reg_writel(a5psw, A5PSW_PATTERN_CTRL(A5PSW_PATTERN_MGMTFWD), in a5psw_setup()
948 a5psw_reg_writel(a5psw, A5PSW_MGMT_TAG_CFG, reg); in a5psw_setup()
954 a5psw_reg_writel(a5psw, A5PSW_LK_CTRL, reg); in a5psw_setup()
956 ret = readl_poll_timeout(a5psw->base + A5PSW_LK_CTRL, reg, in a5psw_setup()
960 dev_err(a5psw->dev, "Failed to clear lookup table\n"); in a5psw_setup()
966 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg); in a5psw_setup()
971 a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(vlan), reg); in a5psw_setup()
978 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port), in a5psw_setup()
982 a5psw_port_enable_set(a5psw, port, dsa_port_is_cpu(dp)); in a5psw_setup()
989 a5psw_flooding_set_resolution(a5psw, port, true); in a5psw_setup()
990 a5psw_port_learning_set(a5psw, port, true); in a5psw_setup()
995 a5psw_port_set_standalone(a5psw, port, true); in a5psw_setup()
997 a5psw_vlan_setup(a5psw, port); in a5psw_setup()
1039 static int a5psw_mdio_wait_busy(struct a5psw *a5psw) in a5psw_mdio_wait_busy() argument
1044 err = readl_poll_timeout(a5psw->base + A5PSW_MDIO_CFG_STATUS, status, in a5psw_mdio_wait_busy()
1048 dev_err(a5psw->dev, "MDIO command timeout\n"); in a5psw_mdio_wait_busy()
1055 struct a5psw *a5psw = bus->priv; in a5psw_mdio_read() local
1063 a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd); in a5psw_mdio_read()
1065 ret = a5psw_mdio_wait_busy(a5psw); in a5psw_mdio_read()
1069 ret = a5psw_reg_readl(a5psw, A5PSW_MDIO_DATA) & A5PSW_MDIO_DATA_MASK; in a5psw_mdio_read()
1071 status = a5psw_reg_readl(a5psw, A5PSW_MDIO_CFG_STATUS); in a5psw_mdio_read()
1081 struct a5psw *a5psw = bus->priv; in a5psw_mdio_write() local
1087 a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd); in a5psw_mdio_write()
1088 a5psw_reg_writel(a5psw, A5PSW_MDIO_DATA, phy_data); in a5psw_mdio_write()
1090 return a5psw_mdio_wait_busy(a5psw); in a5psw_mdio_write()
1093 static int a5psw_mdio_config(struct a5psw *a5psw, u32 mdio_freq) in a5psw_mdio_config() argument
1099 rate = clk_get_rate(a5psw->hclk); in a5psw_mdio_config()
1103 dev_err(a5psw->dev, "MDIO clock div %ld out of range\n", div); in a5psw_mdio_config()
1109 a5psw_reg_writel(a5psw, A5PSW_MDIO_CFG_STATUS, cfgstatus); in a5psw_mdio_config()
1114 static int a5psw_probe_mdio(struct a5psw *a5psw, struct device_node *node) in a5psw_probe_mdio() argument
1116 struct device *dev = a5psw->dev; in a5psw_probe_mdio()
1124 ret = a5psw_mdio_config(a5psw, mdio_freq); in a5psw_probe_mdio()
1135 bus->priv = a5psw; in a5psw_probe_mdio()
1139 a5psw->mii_bus = bus; in a5psw_probe_mdio()
1144 static void a5psw_pcs_free(struct a5psw *a5psw) in a5psw_pcs_free() argument
1148 for (i = 0; i < ARRAY_SIZE(a5psw->pcs); i++) { in a5psw_pcs_free()
1149 if (a5psw->pcs[i]) in a5psw_pcs_free()
1150 miic_destroy(a5psw->pcs[i]); in a5psw_pcs_free()
1154 static int a5psw_pcs_get(struct a5psw *a5psw) in a5psw_pcs_get() argument
1161 ports = of_get_child_by_name(a5psw->dev->of_node, "ethernet-ports"); in a5psw_pcs_get()
1175 if (reg >= ARRAY_SIZE(a5psw->pcs)) { in a5psw_pcs_get()
1180 pcs = miic_create(a5psw->dev, pcs_node); in a5psw_pcs_get()
1182 dev_err(a5psw->dev, "Failed to create PCS for port %d\n", in a5psw_pcs_get()
1188 a5psw->pcs[reg] = pcs; in a5psw_pcs_get()
1199 a5psw_pcs_free(a5psw); in a5psw_pcs_get()
1209 struct a5psw *a5psw; in a5psw_probe() local
1212 a5psw = devm_kzalloc(dev, sizeof(*a5psw), GFP_KERNEL); in a5psw_probe()
1213 if (!a5psw) in a5psw_probe()
1216 a5psw->dev = dev; in a5psw_probe()
1217 mutex_init(&a5psw->lk_lock); in a5psw_probe()
1218 spin_lock_init(&a5psw->reg_lock); in a5psw_probe()
1219 a5psw->base = devm_platform_ioremap_resource(pdev, 0); in a5psw_probe()
1220 if (IS_ERR(a5psw->base)) in a5psw_probe()
1221 return PTR_ERR(a5psw->base); in a5psw_probe()
1223 a5psw->bridged_ports = BIT(A5PSW_CPU_PORT); in a5psw_probe()
1225 ret = a5psw_pcs_get(a5psw); in a5psw_probe()
1229 a5psw->hclk = devm_clk_get(dev, "hclk"); in a5psw_probe()
1230 if (IS_ERR(a5psw->hclk)) { in a5psw_probe()
1232 ret = PTR_ERR(a5psw->hclk); in a5psw_probe()
1236 a5psw->clk = devm_clk_get(dev, "clk"); in a5psw_probe()
1237 if (IS_ERR(a5psw->clk)) { in a5psw_probe()
1239 ret = PTR_ERR(a5psw->clk); in a5psw_probe()
1243 ret = clk_prepare_enable(a5psw->clk); in a5psw_probe()
1247 ret = clk_prepare_enable(a5psw->hclk); in a5psw_probe()
1253 ret = a5psw_probe_mdio(a5psw, mdio); in a5psw_probe()
1263 ds = &a5psw->ds; in a5psw_probe()
1268 ds->priv = a5psw; in a5psw_probe()
1279 clk_disable_unprepare(a5psw->hclk); in a5psw_probe()
1281 clk_disable_unprepare(a5psw->clk); in a5psw_probe()
1283 a5psw_pcs_free(a5psw); in a5psw_probe()
1290 struct a5psw *a5psw = platform_get_drvdata(pdev); in a5psw_remove() local
1292 if (!a5psw) in a5psw_remove()
1295 dsa_unregister_switch(&a5psw->ds); in a5psw_remove()
1296 a5psw_pcs_free(a5psw); in a5psw_remove()
1297 clk_disable_unprepare(a5psw->hclk); in a5psw_remove()
1298 clk_disable_unprepare(a5psw->clk); in a5psw_remove()
1303 struct a5psw *a5psw = platform_get_drvdata(pdev); in a5psw_shutdown() local
1305 if (!a5psw) in a5psw_shutdown()
1308 dsa_switch_shutdown(&a5psw->ds); in a5psw_shutdown()