• Home
  • Raw
  • Download

Lines Matching +full:rzn1 +full:- +full:a5psw

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2022 Schneider-Electric
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()
224 unsigned long *intf = config->supported_interfaces; in a5psw_phylink_get_caps()
226 config->mac_capabilities = MAC_1000FD; in a5psw_phylink_get_caps()
230 * using 1000Mbps Full-Duplex mode only (cf ethernet manual) in a5psw_phylink_get_caps()
234 config->mac_capabilities |= MAC_100 | MAC_10; in a5psw_phylink_get_caps()
246 struct a5psw *a5psw = ds->priv; in a5psw_phylink_mac_select_pcs() local
248 if (!dsa_port_is_cpu(dp) && a5psw->pcs[port]) in a5psw_phylink_mac_select_pcs()
249 return a5psw->pcs[port]; in a5psw_phylink_mac_select_pcs()
258 struct a5psw *a5psw = ds->priv; in a5psw_phylink_mac_link_down() local
261 cmd_cfg = a5psw_reg_readl(a5psw, A5PSW_CMD_CFG(port)); in a5psw_phylink_mac_link_down()
263 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port), cmd_cfg); in a5psw_phylink_mac_link_down()
274 struct a5psw *a5psw = ds->priv; in a5psw_phylink_mac_link_up() local
287 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port), cmd_cfg); in a5psw_phylink_mac_link_up()
292 struct a5psw *a5psw = ds->priv; in a5psw_set_ageing_time() local
297 rate = clk_get_rate(a5psw->clk); in a5psw_set_ageing_time()
301 return -EINVAL; in a5psw_set_ageing_time()
306 a5psw_reg_writel(a5psw, A5PSW_LK_AGETIME, agetime); in a5psw_set_ageing_time()
311 static void a5psw_port_learning_set(struct a5psw *a5psw, int port, bool learn) in a5psw_port_learning_set() argument
316 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg); in a5psw_port_learning_set()
319 static void a5psw_port_rx_block_set(struct a5psw *a5psw, int port, bool block) in a5psw_port_rx_block_set() argument
324 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg); in a5psw_port_rx_block_set()
327 static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port, in a5psw_flooding_set_resolution() argument
335 a5psw_reg_rmw(a5psw, offsets[i], BIT(port), in a5psw_flooding_set_resolution()
339 static void a5psw_port_set_standalone(struct a5psw *a5psw, int port, in a5psw_port_set_standalone() argument
342 a5psw_port_learning_set(a5psw, port, !standalone); in a5psw_port_set_standalone()
343 a5psw_flooding_set_resolution(a5psw, port, !standalone); in a5psw_port_set_standalone()
344 a5psw_port_mgmtfwd_set(a5psw, port, standalone); in a5psw_port_set_standalone()
352 struct a5psw *a5psw = ds->priv; in a5psw_port_bridge_join() local
355 if (a5psw->br_dev && bridge.dev != a5psw->br_dev) { in a5psw_port_bridge_join()
358 return -EOPNOTSUPP; in a5psw_port_bridge_join()
361 a5psw->br_dev = bridge.dev; in a5psw_port_bridge_join()
362 a5psw_port_set_standalone(a5psw, port, false); in a5psw_port_bridge_join()
364 a5psw->bridged_ports |= BIT(port); in a5psw_port_bridge_join()
372 struct a5psw *a5psw = ds->priv; in a5psw_port_bridge_leave() local
374 a5psw->bridged_ports &= ~BIT(port); in a5psw_port_bridge_leave()
376 a5psw_port_set_standalone(a5psw, port, true); in a5psw_port_bridge_leave()
379 if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT)) in a5psw_port_bridge_leave()
380 a5psw->br_dev = NULL; in a5psw_port_bridge_leave()
389 return -EINVAL; in a5psw_port_pre_bridge_flags()
399 struct a5psw *a5psw = ds->priv; in a5psw_port_bridge_flags() local
409 if (!(a5psw->bridged_ports & BIT(port))) in a5psw_port_bridge_flags()
414 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, in a5psw_port_bridge_flags()
420 a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val); in a5psw_port_bridge_flags()
425 a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val); in a5psw_port_bridge_flags()
430 a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val); in a5psw_port_bridge_flags()
440 struct a5psw *a5psw = ds->priv; in a5psw_port_stp_state_set() local
453 learning_enabled = dp->learning; in a5psw_port_stp_state_set()
458 learning_enabled = dp->learning; in a5psw_port_stp_state_set()
461 dev_err(ds->dev, "invalid STP state: %d\n", state); in a5psw_port_stp_state_set()
465 a5psw_port_learning_set(a5psw, port, learning_enabled); in a5psw_port_stp_state_set()
466 a5psw_port_rx_block_set(a5psw, port, !rx_enabled); in a5psw_port_stp_state_set()
467 a5psw_port_tx_enable(a5psw, port, tx_enabled); in a5psw_port_stp_state_set()
472 struct a5psw *a5psw = ds->priv; in a5psw_port_fast_age() local
474 a5psw_port_fdb_flush(a5psw, port); in a5psw_port_fast_age()
477 static int a5psw_lk_execute_lookup(struct a5psw *a5psw, union lk_data *lk_data, in a5psw_lk_execute_lookup() argument
483 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_LO, lk_data->lo); in a5psw_lk_execute_lookup()
484 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data->hi); in a5psw_lk_execute_lookup()
487 ret = a5psw_lk_execute_ctrl(a5psw, &ctrl); in a5psw_lk_execute_lookup()
500 struct a5psw *a5psw = ds->priv; in a5psw_port_fdb_add() local
510 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_add()
513 ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry); in a5psw_port_fdb_add()
517 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI); in a5psw_port_fdb_add()
529 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi); in a5psw_port_fdb_add()
532 ret = a5psw_lk_execute_ctrl(a5psw, &reg); in a5psw_port_fdb_add()
538 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg); in a5psw_port_fdb_add()
542 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_add()
551 struct a5psw *a5psw = ds->priv; in a5psw_port_fdb_del() local
560 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_del()
562 ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry); in a5psw_port_fdb_del()
566 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI); in a5psw_port_fdb_del()
582 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi); in a5psw_port_fdb_del()
590 ret = a5psw_lk_execute_ctrl(a5psw, &reg); in a5psw_port_fdb_del()
597 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg); in a5psw_port_fdb_del()
601 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_del()
609 struct a5psw *a5psw = ds->priv; in a5psw_port_fdb_dump() local
614 mutex_lock(&a5psw->lk_lock); in a5psw_port_fdb_dump()
619 ret = a5psw_lk_execute_ctrl(a5psw, &reg); in a5psw_port_fdb_dump()
623 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI); in a5psw_port_fdb_dump()
629 lk_data.lo = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_LO); in a5psw_port_fdb_dump()
637 mutex_unlock(&a5psw->lk_lock); in a5psw_port_fdb_dump()
649 struct a5psw *a5psw = ds->priv; in a5psw_port_vlan_filtering() local
652 a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE_ENA, BIT(port), in a5psw_port_vlan_filtering()
656 a5psw_reg_rmw(a5psw, A5PSW_VLAN_VERIFY, mask, val); in a5psw_port_vlan_filtering()
661 static int a5psw_find_vlan_entry(struct a5psw *a5psw, u16 vid) in a5psw_find_vlan_entry() argument
668 vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i)); in a5psw_find_vlan_entry()
673 return -1; in a5psw_find_vlan_entry()
676 static int a5psw_new_vlan_res_entry(struct a5psw *a5psw, u16 newvid) in a5psw_new_vlan_res_entry() argument
683 vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i)); in a5psw_new_vlan_res_entry()
686 a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(i), vlan_res); in a5psw_new_vlan_res_entry()
691 return -1; in a5psw_new_vlan_res_entry()
694 static void a5psw_port_vlan_tagged_cfg(struct a5psw *a5psw, in a5psw_port_vlan_tagged_cfg() argument
707 a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK); in a5psw_port_vlan_tagged_cfg()
708 reg = a5psw_reg_readl(a5psw, vlan_res_off); in a5psw_port_vlan_tagged_cfg()
709 a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK); in a5psw_port_vlan_tagged_cfg()
713 a5psw_reg_writel(a5psw, vlan_res_off, reg); in a5psw_port_vlan_tagged_cfg()
716 static void a5psw_port_vlan_cfg(struct a5psw *a5psw, unsigned int vlan_res_id, in a5psw_port_vlan_cfg() argument
725 a5psw_reg_rmw(a5psw, A5PSW_VLAN_RES(vlan_res_id), mask, reg); in a5psw_port_vlan_cfg()
732 bool tagged = !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); in a5psw_port_vlan_add()
733 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; in a5psw_port_vlan_add()
734 struct a5psw *a5psw = ds->priv; in a5psw_port_vlan_add() local
735 u16 vid = vlan->vid; in a5psw_port_vlan_add()
738 vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); in a5psw_port_vlan_add()
740 vlan_res_id = a5psw_new_vlan_res_entry(a5psw, vid); in a5psw_port_vlan_add()
742 return -ENOSPC; in a5psw_port_vlan_add()
745 a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, true); in a5psw_port_vlan_add()
747 a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, true); in a5psw_port_vlan_add()
754 a5psw_reg_writel(a5psw, A5PSW_SYSTEM_TAGINFO(port), vid); in a5psw_port_vlan_add()
762 struct a5psw *a5psw = ds->priv; in a5psw_port_vlan_del() local
763 u16 vid = vlan->vid; in a5psw_port_vlan_del()
766 vlan_res_id = a5psw_find_vlan_entry(a5psw, vid); in a5psw_port_vlan_del()
768 return -EINVAL; in a5psw_port_vlan_del()
770 a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, false); in a5psw_port_vlan_del()
771 a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, false); in a5psw_port_vlan_del()
776 static u64 a5psw_read_stat(struct a5psw *a5psw, u32 offset, int port) in a5psw_read_stat() argument
780 reg_lo = a5psw_reg_readl(a5psw, offset + A5PSW_PORT_OFFSET(port)); in a5psw_read_stat()
782 reg_hi = a5psw_reg_readl(a5psw, A5PSW_STATS_HIWORD); in a5psw_read_stat()
804 struct a5psw *a5psw = ds->priv; in a5psw_get_ethtool_stats() local
808 data[u] = a5psw_read_stat(a5psw, a5psw_stats[u].offset, port); in a5psw_get_ethtool_stats()
822 struct a5psw *a5psw = ds->priv; in a5psw_get_eth_mac_stats() local
824 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port) in a5psw_get_eth_mac_stats()
825 mac_stats->FramesTransmittedOK = RD(aFramesTransmittedOK); in a5psw_get_eth_mac_stats()
826 mac_stats->SingleCollisionFrames = RD(aSingleCollisions); in a5psw_get_eth_mac_stats()
827 mac_stats->MultipleCollisionFrames = RD(aMultipleCollisions); in a5psw_get_eth_mac_stats()
828 mac_stats->FramesReceivedOK = RD(aFramesReceivedOK); in a5psw_get_eth_mac_stats()
829 mac_stats->FrameCheckSequenceErrors = RD(aFrameCheckSequenceErrors); in a5psw_get_eth_mac_stats()
830 mac_stats->AlignmentErrors = RD(aAlignmentErrors); in a5psw_get_eth_mac_stats()
831 mac_stats->OctetsTransmittedOK = RD(aOctetsTransmittedOK); in a5psw_get_eth_mac_stats()
832 mac_stats->FramesWithDeferredXmissions = RD(aDeferred); in a5psw_get_eth_mac_stats()
833 mac_stats->LateCollisions = RD(aLateCollisions); in a5psw_get_eth_mac_stats()
834 mac_stats->FramesAbortedDueToXSColls = RD(aExcessiveCollisions); in a5psw_get_eth_mac_stats()
835 mac_stats->FramesLostDueToIntMACXmitError = RD(ifOutErrors); in a5psw_get_eth_mac_stats()
836 mac_stats->CarrierSenseErrors = RD(aCarrierSenseErrors); in a5psw_get_eth_mac_stats()
837 mac_stats->OctetsReceivedOK = RD(aOctetsReceivedOK); in a5psw_get_eth_mac_stats()
838 mac_stats->FramesLostDueToIntMACRcvError = RD(ifInErrors); in a5psw_get_eth_mac_stats()
839 mac_stats->MulticastFramesXmittedOK = RD(ifOutMulticastPkts); in a5psw_get_eth_mac_stats()
840 mac_stats->BroadcastFramesXmittedOK = RD(ifOutBroadcastPkts); in a5psw_get_eth_mac_stats()
841 mac_stats->FramesWithExcessiveDeferral = RD(aDeferred); in a5psw_get_eth_mac_stats()
842 mac_stats->MulticastFramesReceivedOK = RD(ifInMulticastPkts); in a5psw_get_eth_mac_stats()
843 mac_stats->BroadcastFramesReceivedOK = RD(ifInBroadcastPkts); in a5psw_get_eth_mac_stats()
862 struct a5psw *a5psw = ds->priv; in a5psw_get_rmon_stats() local
864 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port) in a5psw_get_rmon_stats()
865 rmon_stats->undersize_pkts = RD(etherStatsUndersizePkts); in a5psw_get_rmon_stats()
866 rmon_stats->oversize_pkts = RD(etherStatsOversizePkts); in a5psw_get_rmon_stats()
867 rmon_stats->fragments = RD(etherStatsFragments); in a5psw_get_rmon_stats()
868 rmon_stats->jabbers = RD(etherStatsJabbers); in a5psw_get_rmon_stats()
869 rmon_stats->hist[0] = RD(etherStatsPkts64Octets); in a5psw_get_rmon_stats()
870 rmon_stats->hist[1] = RD(etherStatsPkts65to127Octets); in a5psw_get_rmon_stats()
871 rmon_stats->hist[2] = RD(etherStatsPkts128to255Octets); in a5psw_get_rmon_stats()
872 rmon_stats->hist[3] = RD(etherStatsPkts256to511Octets); in a5psw_get_rmon_stats()
873 rmon_stats->hist[4] = RD(etherStatsPkts512to1023Octets); in a5psw_get_rmon_stats()
874 rmon_stats->hist[5] = RD(etherStatsPkts1024to1518Octets); in a5psw_get_rmon_stats()
875 rmon_stats->hist[6] = RD(etherStatsPkts1519toXOctets); in a5psw_get_rmon_stats()
884 struct a5psw *a5psw = ds->priv; in a5psw_get_eth_ctrl_stats() local
887 stat = a5psw_read_stat(a5psw, A5PSW_aTxPAUSEMACCtrlFrames, port); in a5psw_get_eth_ctrl_stats()
888 ctrl_stats->MACControlFramesTransmitted = stat; in a5psw_get_eth_ctrl_stats()
889 stat = a5psw_read_stat(a5psw, A5PSW_aRxPAUSEMACCtrlFrames, port); in a5psw_get_eth_ctrl_stats()
890 ctrl_stats->MACControlFramesReceived = stat; in a5psw_get_eth_ctrl_stats()
893 static void a5psw_vlan_setup(struct a5psw *a5psw, int port) in a5psw_vlan_setup() argument
902 a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE, A5PSW_VLAN_IN_MODE_PORT(port), in a5psw_vlan_setup()
910 a5psw_reg_rmw(a5psw, A5PSW_VLAN_OUT_MODE, in a5psw_vlan_setup()
916 struct a5psw *a5psw = ds->priv; in a5psw_setup() local
923 if (dp->index != A5PSW_CPU_PORT) { in a5psw_setup()
924 dev_err(a5psw->dev, "Invalid CPU port\n"); in a5psw_setup()
925 return -EINVAL; in a5psw_setup()
931 a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg); in a5psw_setup()
934 a5psw_reg_writel(a5psw, A5PSW_PATTERN_CTRL(A5PSW_PATTERN_MGMTFWD), in a5psw_setup()
940 a5psw_reg_writel(a5psw, A5PSW_MGMT_TAG_CFG, reg); in a5psw_setup()
946 a5psw_reg_writel(a5psw, A5PSW_LK_CTRL, reg); in a5psw_setup()
948 ret = readl_poll_timeout(a5psw->base + A5PSW_LK_CTRL, reg, in a5psw_setup()
952 dev_err(a5psw->dev, "Failed to clear lookup table\n"); in a5psw_setup()
958 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg); in a5psw_setup()
963 a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(vlan), reg); in a5psw_setup()
967 port = dp->index; in a5psw_setup()
970 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port), in a5psw_setup()
974 a5psw_port_enable_set(a5psw, port, dsa_port_is_cpu(dp)); in a5psw_setup()
981 a5psw_flooding_set_resolution(a5psw, port, true); in a5psw_setup()
982 a5psw_port_learning_set(a5psw, port, true); in a5psw_setup()
987 a5psw_port_set_standalone(a5psw, port, true); in a5psw_setup()
989 a5psw_vlan_setup(a5psw, port); in a5psw_setup()
1027 static int a5psw_mdio_wait_busy(struct a5psw *a5psw) in a5psw_mdio_wait_busy() argument
1032 err = readl_poll_timeout(a5psw->base + A5PSW_MDIO_CFG_STATUS, status, in a5psw_mdio_wait_busy()
1036 dev_err(a5psw->dev, "MDIO command timeout\n"); in a5psw_mdio_wait_busy()
1043 struct a5psw *a5psw = bus->priv; in a5psw_mdio_read() local
1051 a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd); in a5psw_mdio_read()
1053 ret = a5psw_mdio_wait_busy(a5psw); in a5psw_mdio_read()
1057 ret = a5psw_reg_readl(a5psw, A5PSW_MDIO_DATA) & A5PSW_MDIO_DATA_MASK; in a5psw_mdio_read()
1059 status = a5psw_reg_readl(a5psw, A5PSW_MDIO_CFG_STATUS); in a5psw_mdio_read()
1061 return -EIO; in a5psw_mdio_read()
1069 struct a5psw *a5psw = bus->priv; in a5psw_mdio_write() local
1075 a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd); in a5psw_mdio_write()
1076 a5psw_reg_writel(a5psw, A5PSW_MDIO_DATA, phy_data); in a5psw_mdio_write()
1078 return a5psw_mdio_wait_busy(a5psw); in a5psw_mdio_write()
1081 static int a5psw_mdio_config(struct a5psw *a5psw, u32 mdio_freq) in a5psw_mdio_config() argument
1087 rate = clk_get_rate(a5psw->hclk); in a5psw_mdio_config()
1091 dev_err(a5psw->dev, "MDIO clock div %ld out of range\n", div); in a5psw_mdio_config()
1092 return -ERANGE; in a5psw_mdio_config()
1097 a5psw_reg_writel(a5psw, A5PSW_MDIO_CFG_STATUS, cfgstatus); in a5psw_mdio_config()
1102 static int a5psw_probe_mdio(struct a5psw *a5psw, struct device_node *node) in a5psw_probe_mdio() argument
1104 struct device *dev = a5psw->dev; in a5psw_probe_mdio()
1109 if (of_property_read_u32(node, "clock-frequency", &mdio_freq)) in a5psw_probe_mdio()
1112 ret = a5psw_mdio_config(a5psw, mdio_freq); in a5psw_probe_mdio()
1118 return -ENOMEM; in a5psw_probe_mdio()
1120 bus->name = "a5psw_mdio"; in a5psw_probe_mdio()
1121 bus->read = a5psw_mdio_read; in a5psw_probe_mdio()
1122 bus->write = a5psw_mdio_write; in a5psw_probe_mdio()
1123 bus->priv = a5psw; in a5psw_probe_mdio()
1124 bus->parent = dev; in a5psw_probe_mdio()
1125 snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); in a5psw_probe_mdio()
1127 a5psw->mii_bus = bus; in a5psw_probe_mdio()
1132 static void a5psw_pcs_free(struct a5psw *a5psw) in a5psw_pcs_free() argument
1136 for (i = 0; i < ARRAY_SIZE(a5psw->pcs); i++) { in a5psw_pcs_free()
1137 if (a5psw->pcs[i]) in a5psw_pcs_free()
1138 miic_destroy(a5psw->pcs[i]); in a5psw_pcs_free()
1142 static int a5psw_pcs_get(struct a5psw *a5psw) in a5psw_pcs_get() argument
1149 ports = of_get_child_by_name(a5psw->dev->of_node, "ethernet-ports"); in a5psw_pcs_get()
1151 return -EINVAL; in a5psw_pcs_get()
1154 pcs_node = of_parse_phandle(port, "pcs-handle", 0); in a5psw_pcs_get()
1159 ret = -EINVAL; in a5psw_pcs_get()
1163 if (reg >= ARRAY_SIZE(a5psw->pcs)) { in a5psw_pcs_get()
1164 ret = -ENODEV; in a5psw_pcs_get()
1168 pcs = miic_create(a5psw->dev, pcs_node); in a5psw_pcs_get()
1170 dev_err(a5psw->dev, "Failed to create PCS for port %d\n", in a5psw_pcs_get()
1176 a5psw->pcs[reg] = pcs; in a5psw_pcs_get()
1187 a5psw_pcs_free(a5psw); in a5psw_pcs_get()
1194 struct device *dev = &pdev->dev; in a5psw_probe()
1197 struct a5psw *a5psw; in a5psw_probe() local
1200 a5psw = devm_kzalloc(dev, sizeof(*a5psw), GFP_KERNEL); in a5psw_probe()
1201 if (!a5psw) in a5psw_probe()
1202 return -ENOMEM; in a5psw_probe()
1204 a5psw->dev = dev; in a5psw_probe()
1205 mutex_init(&a5psw->lk_lock); in a5psw_probe()
1206 spin_lock_init(&a5psw->reg_lock); in a5psw_probe()
1207 a5psw->base = devm_platform_ioremap_resource(pdev, 0); in a5psw_probe()
1208 if (IS_ERR(a5psw->base)) in a5psw_probe()
1209 return PTR_ERR(a5psw->base); in a5psw_probe()
1211 a5psw->bridged_ports = BIT(A5PSW_CPU_PORT); in a5psw_probe()
1213 ret = a5psw_pcs_get(a5psw); in a5psw_probe()
1217 a5psw->hclk = devm_clk_get(dev, "hclk"); in a5psw_probe()
1218 if (IS_ERR(a5psw->hclk)) { in a5psw_probe()
1220 ret = PTR_ERR(a5psw->hclk); in a5psw_probe()
1224 a5psw->clk = devm_clk_get(dev, "clk"); in a5psw_probe()
1225 if (IS_ERR(a5psw->clk)) { in a5psw_probe()
1227 ret = PTR_ERR(a5psw->clk); in a5psw_probe()
1231 ret = clk_prepare_enable(a5psw->clk); in a5psw_probe()
1235 ret = clk_prepare_enable(a5psw->hclk); in a5psw_probe()
1239 mdio = of_get_child_by_name(dev->of_node, "mdio"); in a5psw_probe()
1241 ret = a5psw_probe_mdio(a5psw, mdio); in a5psw_probe()
1251 ds = &a5psw->ds; in a5psw_probe()
1252 ds->dev = dev; in a5psw_probe()
1253 ds->num_ports = A5PSW_PORTS_NUM; in a5psw_probe()
1254 ds->ops = &a5psw_switch_ops; in a5psw_probe()
1255 ds->priv = a5psw; in a5psw_probe()
1266 clk_disable_unprepare(a5psw->hclk); in a5psw_probe()
1268 clk_disable_unprepare(a5psw->clk); in a5psw_probe()
1270 a5psw_pcs_free(a5psw); in a5psw_probe()
1277 struct a5psw *a5psw = platform_get_drvdata(pdev); in a5psw_remove() local
1279 if (!a5psw) in a5psw_remove()
1282 dsa_unregister_switch(&a5psw->ds); in a5psw_remove()
1283 a5psw_pcs_free(a5psw); in a5psw_remove()
1284 clk_disable_unprepare(a5psw->hclk); in a5psw_remove()
1285 clk_disable_unprepare(a5psw->clk); in a5psw_remove()
1292 struct a5psw *a5psw = platform_get_drvdata(pdev); in a5psw_shutdown() local
1294 if (!a5psw) in a5psw_shutdown()
1297 dsa_switch_shutdown(&a5psw->ds); in a5psw_shutdown()
1303 { .compatible = "renesas,rzn1-a5psw", },
1320 MODULE_DESCRIPTION("Renesas RZ/N1 Advanced 5-port Switch driver");