1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
3 * Copyright(c) 2018 Synopsys, Inc. All rights reserved.
6 #include "axgbe_ethdev.h"
7 #include "axgbe_common.h"
11 static int mdio_complete(struct axgbe_port *pdata)
13 if (!AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, BUSY))
19 static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata, int addr,
22 unsigned int mdio_sca, mdio_sccd;
26 AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
27 AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
28 AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
31 AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val);
32 AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1);
33 AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
34 AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
36 timeout = rte_get_timer_cycles() + rte_get_timer_hz();
37 while (time_before(rte_get_timer_cycles(), timeout)) {
39 if (mdio_complete(pdata))
43 PMD_DRV_LOG(ERR, "Mdio write operation timed out\n");
47 static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata, int addr,
50 unsigned int mdio_sca, mdio_sccd;
54 AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
55 AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
56 AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
59 AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3);
60 AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
61 AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
63 timeout = rte_get_timer_cycles() + rte_get_timer_hz();
65 while (time_before(rte_get_timer_cycles(), timeout)) {
67 if (mdio_complete(pdata))
71 PMD_DRV_LOG(ERR, "Mdio read operation timed out\n");
75 return AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
78 static int axgbe_set_ext_mii_mode(struct axgbe_port *pdata, unsigned int port,
79 enum axgbe_mdio_mode mode)
81 unsigned int reg_val = 0;
84 case AXGBE_MDIO_MODE_CL22:
85 if (port > AXGMAC_MAX_C22_PORT)
87 reg_val |= (1 << port);
89 case AXGBE_MDIO_MODE_CL45:
94 AXGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val);
99 static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata,
100 int prtad __rte_unused, int mmd_reg)
102 unsigned int mmd_address, index, offset;
105 if (mmd_reg & MII_ADDR_C45)
106 mmd_address = mmd_reg & ~MII_ADDR_C45;
108 mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
110 /* The PCS registers are accessed using mmio. The underlying
111 * management interface uses indirect addressing to access the MMD
112 * register sets. This requires accessing of the PCS register in two
113 * phases, an address phase and a data phase.
115 * The mmio interface is based on 16-bit offsets and values. All
116 * register offsets must therefore be adjusted by left shifting the
117 * offset 1 bit and reading 16 bits of data.
120 index = mmd_address & ~pdata->xpcs_window_mask;
121 offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
123 pthread_mutex_lock(&pdata->xpcs_mutex);
125 XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
126 mmd_data = XPCS16_IOREAD(pdata, offset);
128 pthread_mutex_unlock(&pdata->xpcs_mutex);
133 static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata,
134 int prtad __rte_unused,
135 int mmd_reg, int mmd_data)
137 unsigned int mmd_address, index, offset;
139 if (mmd_reg & MII_ADDR_C45)
140 mmd_address = mmd_reg & ~MII_ADDR_C45;
142 mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
144 /* The PCS registers are accessed using mmio. The underlying
145 * management interface uses indirect addressing to access the MMD
146 * register sets. This requires accessing of the PCS register in two
147 * phases, an address phase and a data phase.
149 * The mmio interface is based on 16-bit offsets and values. All
150 * register offsets must therefore be adjusted by left shifting the
151 * offset 1 bit and writing 16 bits of data.
154 index = mmd_address & ~pdata->xpcs_window_mask;
155 offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
157 pthread_mutex_lock(&pdata->xpcs_mutex);
159 XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
160 XPCS16_IOWRITE(pdata, offset, mmd_data);
162 pthread_mutex_unlock(&pdata->xpcs_mutex);
165 static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad,
168 switch (pdata->vdata->xpcs_access) {
169 case AXGBE_XPCS_ACCESS_V1:
170 PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported\n");
172 case AXGBE_XPCS_ACCESS_V2:
174 return axgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg);
178 static void axgbe_write_mmd_regs(struct axgbe_port *pdata, int prtad,
179 int mmd_reg, int mmd_data)
181 switch (pdata->vdata->xpcs_access) {
182 case AXGBE_XPCS_ACCESS_V1:
183 PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported\n");
185 case AXGBE_XPCS_ACCESS_V2:
187 return axgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data);
191 static int axgbe_set_speed(struct axgbe_port *pdata, int speed)
209 if (AXGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss)
210 AXGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss);
215 static int __axgbe_exit(struct axgbe_port *pdata)
217 unsigned int count = 2000;
219 /* Issue a software reset */
220 AXGMAC_IOWRITE_BITS(pdata, DMA_MR, SWR, 1);
223 /* Poll Until Poll Condition */
224 while (--count && AXGMAC_IOREAD_BITS(pdata, DMA_MR, SWR))
233 static int axgbe_exit(struct axgbe_port *pdata)
237 /* To guard against possible incorrectly generated interrupts,
238 * issue the software reset twice.
240 ret = __axgbe_exit(pdata);
244 return __axgbe_exit(pdata);
247 void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if)
249 hw_if->exit = axgbe_exit;
252 hw_if->read_mmd_regs = axgbe_read_mmd_regs;
253 hw_if->write_mmd_regs = axgbe_write_mmd_regs;
255 hw_if->set_speed = axgbe_set_speed;
257 hw_if->set_ext_mii_mode = axgbe_set_ext_mii_mode;
258 hw_if->read_ext_mii_regs = axgbe_read_ext_mii_regs;
259 hw_if->write_ext_mii_regs = axgbe_write_ext_mii_regs;