Skip to content

Commit 732f2ab

Browse files
tlendackydavem330
authored andcommitted
amd-xgbe: Add support for MDIO attached PHYs
Use the phylib support in the kernel to communicate with and control an MDIO attached PHY. Use the hardware's MDIO communication mechanism to communicate with the PHY. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent abf0a1c commit 732f2ab

File tree

6 files changed

+557
-11
lines changed

6 files changed

+557
-11
lines changed

drivers/net/ethernet/amd/xgbe/xgbe-common.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,11 @@
311311
#define MAC_HWF0R 0x011c
312312
#define MAC_HWF1R 0x0120
313313
#define MAC_HWF2R 0x0124
314+
#define MAC_MDIOSCAR 0x0200
315+
#define MAC_MDIOSCCDR 0x0204
316+
#define MAC_MDIOISR 0x0214
317+
#define MAC_MDIOIER 0x0218
318+
#define MAC_MDIOCL22R 0x0220
314319
#define MAC_GPIOCR 0x0278
315320
#define MAC_GPIOSR 0x027c
316321
#define MAC_MACA0HR 0x0300
@@ -411,10 +416,34 @@
411416
#define MAC_ISR_MMCTXIS_WIDTH 1
412417
#define MAC_ISR_PMTIS_INDEX 4
413418
#define MAC_ISR_PMTIS_WIDTH 1
419+
#define MAC_ISR_SMI_INDEX 1
420+
#define MAC_ISR_SMI_WIDTH 1
414421
#define MAC_ISR_TSIS_INDEX 12
415422
#define MAC_ISR_TSIS_WIDTH 1
416423
#define MAC_MACA1HR_AE_INDEX 31
417424
#define MAC_MACA1HR_AE_WIDTH 1
425+
#define MAC_MDIOIER_SNGLCOMPIE_INDEX 12
426+
#define MAC_MDIOIER_SNGLCOMPIE_WIDTH 1
427+
#define MAC_MDIOISR_SNGLCOMPINT_INDEX 12
428+
#define MAC_MDIOISR_SNGLCOMPINT_WIDTH 1
429+
#define MAC_MDIOSCAR_DA_INDEX 21
430+
#define MAC_MDIOSCAR_DA_WIDTH 5
431+
#define MAC_MDIOSCAR_PA_INDEX 16
432+
#define MAC_MDIOSCAR_PA_WIDTH 5
433+
#define MAC_MDIOSCAR_RA_INDEX 0
434+
#define MAC_MDIOSCAR_RA_WIDTH 16
435+
#define MAC_MDIOSCAR_REG_INDEX 0
436+
#define MAC_MDIOSCAR_REG_WIDTH 21
437+
#define MAC_MDIOSCCDR_BUSY_INDEX 22
438+
#define MAC_MDIOSCCDR_BUSY_WIDTH 1
439+
#define MAC_MDIOSCCDR_CMD_INDEX 16
440+
#define MAC_MDIOSCCDR_CMD_WIDTH 2
441+
#define MAC_MDIOSCCDR_CR_INDEX 19
442+
#define MAC_MDIOSCCDR_CR_WIDTH 3
443+
#define MAC_MDIOSCCDR_DATA_INDEX 0
444+
#define MAC_MDIOSCCDR_DATA_WIDTH 16
445+
#define MAC_MDIOSCCDR_SADDR_INDEX 18
446+
#define MAC_MDIOSCCDR_SADDR_WIDTH 1
418447
#define MAC_PFR_HMC_INDEX 2
419448
#define MAC_PFR_HMC_WIDTH 1
420449
#define MAC_PFR_HPF_INDEX 10
@@ -1019,6 +1048,14 @@
10191048
#define XP_PROP_3_GPIO_TX_FAULT_WIDTH 4
10201049
#define XP_PROP_3_GPIO_ADDR_INDEX 8
10211050
#define XP_PROP_3_GPIO_ADDR_WIDTH 3
1051+
#define XP_PROP_3_MDIO_RESET_INDEX 0
1052+
#define XP_PROP_3_MDIO_RESET_WIDTH 2
1053+
#define XP_PROP_3_MDIO_RESET_I2C_ADDR_INDEX 8
1054+
#define XP_PROP_3_MDIO_RESET_I2C_ADDR_WIDTH 3
1055+
#define XP_PROP_3_MDIO_RESET_I2C_GPIO_INDEX 12
1056+
#define XP_PROP_3_MDIO_RESET_I2C_GPIO_WIDTH 4
1057+
#define XP_PROP_3_MDIO_RESET_INT_GPIO_INDEX 4
1058+
#define XP_PROP_3_MDIO_RESET_INT_GPIO_WIDTH 2
10221059
#define XP_PROP_4_MUX_ADDR_HI_INDEX 8
10231060
#define XP_PROP_4_MUX_ADDR_HI_WIDTH 5
10241061
#define XP_PROP_4_MUX_ADDR_LO_INDEX 0

drivers/net/ethernet/amd/xgbe/xgbe-dev.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,9 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata)
722722
/* Enable all counter interrupts */
723723
XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xffffffff);
724724
XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
725+
726+
/* Enable MDIO single command completion interrupt */
727+
XGMAC_IOWRITE_BITS(pdata, MAC_MDIOIER, SNGLCOMPIE, 1);
725728
}
726729

727730
static void xgbe_enable_ecc_interrupts(struct xgbe_prv_data *pdata)
@@ -1092,6 +1095,36 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata)
10921095
return 0;
10931096
}
10941097

1098+
static int xgbe_clr_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
1099+
{
1100+
unsigned int reg;
1101+
1102+
if (gpio > 16)
1103+
return -EINVAL;
1104+
1105+
reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
1106+
1107+
reg &= ~(1 << (gpio + 16));
1108+
XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
1109+
1110+
return 0;
1111+
}
1112+
1113+
static int xgbe_set_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
1114+
{
1115+
unsigned int reg;
1116+
1117+
if (gpio > 16)
1118+
return -EINVAL;
1119+
1120+
reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
1121+
1122+
reg |= (1 << (gpio + 16));
1123+
XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
1124+
1125+
return 0;
1126+
}
1127+
10951128
static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
10961129
int mmd_reg)
10971130
{
@@ -1236,6 +1269,79 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
12361269
}
12371270
}
12381271

1272+
static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
1273+
int reg, u16 val)
1274+
{
1275+
unsigned int mdio_sca, mdio_sccd;
1276+
1277+
reinit_completion(&pdata->mdio_complete);
1278+
1279+
mdio_sca = 0;
1280+
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
1281+
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
1282+
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
1283+
1284+
mdio_sccd = 0;
1285+
XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val);
1286+
XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1);
1287+
XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
1288+
XGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
1289+
1290+
if (!wait_for_completion_timeout(&pdata->mdio_complete, HZ)) {
1291+
netdev_err(pdata->netdev, "mdio write operation timed out\n");
1292+
return -ETIMEDOUT;
1293+
}
1294+
1295+
return 0;
1296+
}
1297+
1298+
static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
1299+
int reg)
1300+
{
1301+
unsigned int mdio_sca, mdio_sccd;
1302+
1303+
reinit_completion(&pdata->mdio_complete);
1304+
1305+
mdio_sca = 0;
1306+
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
1307+
XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
1308+
XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
1309+
1310+
mdio_sccd = 0;
1311+
XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3);
1312+
XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
1313+
XGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
1314+
1315+
if (!wait_for_completion_timeout(&pdata->mdio_complete, HZ)) {
1316+
netdev_err(pdata->netdev, "mdio read operation timed out\n");
1317+
return -ETIMEDOUT;
1318+
}
1319+
1320+
return XGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
1321+
}
1322+
1323+
static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int port,
1324+
enum xgbe_mdio_mode mode)
1325+
{
1326+
unsigned int reg_val = 0;
1327+
1328+
switch (mode) {
1329+
case XGBE_MDIO_MODE_CL22:
1330+
if (port > XGMAC_MAX_C22_PORT)
1331+
return -EINVAL;
1332+
reg_val |= (1 << port);
1333+
break;
1334+
case XGBE_MDIO_MODE_CL45:
1335+
break;
1336+
default:
1337+
return -EINVAL;
1338+
}
1339+
1340+
XGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val);
1341+
1342+
return 0;
1343+
}
1344+
12391345
static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc)
12401346
{
12411347
return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN);
@@ -3386,6 +3492,13 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
33863492

33873493
hw_if->set_speed = xgbe_set_speed;
33883494

3495+
hw_if->set_ext_mii_mode = xgbe_set_ext_mii_mode;
3496+
hw_if->read_ext_mii_regs = xgbe_read_ext_mii_regs;
3497+
hw_if->write_ext_mii_regs = xgbe_write_ext_mii_regs;
3498+
3499+
hw_if->set_gpio = xgbe_set_gpio;
3500+
hw_if->clr_gpio = xgbe_clr_gpio;
3501+
33893502
hw_if->enable_tx = xgbe_enable_tx;
33903503
hw_if->disable_tx = xgbe_disable_tx;
33913504
hw_if->enable_rx = xgbe_enable_rx;

drivers/net/ethernet/amd/xgbe/xgbe-drv.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ static irqreturn_t xgbe_isr(int irq, void *data)
443443
struct xgbe_hw_if *hw_if = &pdata->hw_if;
444444
struct xgbe_channel *channel;
445445
unsigned int dma_isr, dma_ch_isr;
446-
unsigned int mac_isr, mac_tssr;
446+
unsigned int mac_isr, mac_tssr, mac_mdioisr;
447447
unsigned int i;
448448

449449
/* The DMA interrupt status register also reports MAC and MTL
@@ -503,6 +503,9 @@ static irqreturn_t xgbe_isr(int irq, void *data)
503503
if (XGMAC_GET_BITS(dma_isr, DMA_ISR, MACIS)) {
504504
mac_isr = XGMAC_IOREAD(pdata, MAC_ISR);
505505

506+
netif_dbg(pdata, intr, pdata->netdev, "MAC_ISR=%#010x\n",
507+
mac_isr);
508+
506509
if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCTXIS))
507510
hw_if->tx_mmc_int(pdata);
508511

@@ -512,6 +515,9 @@ static irqreturn_t xgbe_isr(int irq, void *data)
512515
if (XGMAC_GET_BITS(mac_isr, MAC_ISR, TSIS)) {
513516
mac_tssr = XGMAC_IOREAD(pdata, MAC_TSSR);
514517

518+
netif_dbg(pdata, intr, pdata->netdev,
519+
"MAC_TSSR=%#010x\n", mac_tssr);
520+
515521
if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) {
516522
/* Read Tx Timestamp to clear interrupt */
517523
pdata->tx_tstamp =
@@ -520,6 +526,17 @@ static irqreturn_t xgbe_isr(int irq, void *data)
520526
&pdata->tx_tstamp_work);
521527
}
522528
}
529+
530+
if (XGMAC_GET_BITS(mac_isr, MAC_ISR, SMI)) {
531+
mac_mdioisr = XGMAC_IOREAD(pdata, MAC_MDIOISR);
532+
533+
netif_dbg(pdata, intr, pdata->netdev,
534+
"MAC_MDIOISR=%#010x\n", mac_mdioisr);
535+
536+
if (XGMAC_GET_BITS(mac_mdioisr, MAC_MDIOISR,
537+
SNGLCOMPINT))
538+
complete(&pdata->mdio_complete);
539+
}
523540
}
524541

525542
/* If there is not a separate AN irq, handle it here */

drivers/net/ethernet/amd/xgbe/xgbe-main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev)
189189
spin_lock_init(&pdata->tstamp_lock);
190190
mutex_init(&pdata->i2c_mutex);
191191
init_completion(&pdata->i2c_complete);
192+
init_completion(&pdata->mdio_complete);
192193

193194
pdata->msg_enable = netif_msg_init(debug, default_msg_level);
194195

0 commit comments

Comments
 (0)