1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 * Driver for Solarflare network controllers and boards
4 * Copyright 2009-2013 Solarflare Communications Inc.
8 * Driver for PHY related operations via MCDI.
11 #include <linux/slab.h>
13 #include "mcdi_port.h"
15 #include "mcdi_pcol.h"
18 #include "mcdi_port_common.h"
20 static int efx_mcdi_mdio_read(struct net_device
*net_dev
,
21 int prtad
, int devad
, u16 addr
)
23 struct efx_nic
*efx
= netdev_priv(net_dev
);
24 MCDI_DECLARE_BUF(inbuf
, MC_CMD_MDIO_READ_IN_LEN
);
25 MCDI_DECLARE_BUF(outbuf
, MC_CMD_MDIO_READ_OUT_LEN
);
29 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_BUS
, efx
->mdio_bus
);
30 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_PRTAD
, prtad
);
31 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_DEVAD
, devad
);
32 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_ADDR
, addr
);
34 rc
= efx_siena_mcdi_rpc(efx
, MC_CMD_MDIO_READ
, inbuf
, sizeof(inbuf
),
35 outbuf
, sizeof(outbuf
), &outlen
);
39 if (MCDI_DWORD(outbuf
, MDIO_READ_OUT_STATUS
) !=
40 MC_CMD_MDIO_STATUS_GOOD
)
43 return (u16
)MCDI_DWORD(outbuf
, MDIO_READ_OUT_VALUE
);
46 static int efx_mcdi_mdio_write(struct net_device
*net_dev
,
47 int prtad
, int devad
, u16 addr
, u16 value
)
49 struct efx_nic
*efx
= netdev_priv(net_dev
);
50 MCDI_DECLARE_BUF(inbuf
, MC_CMD_MDIO_WRITE_IN_LEN
);
51 MCDI_DECLARE_BUF(outbuf
, MC_CMD_MDIO_WRITE_OUT_LEN
);
55 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_BUS
, efx
->mdio_bus
);
56 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_PRTAD
, prtad
);
57 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_DEVAD
, devad
);
58 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_ADDR
, addr
);
59 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_VALUE
, value
);
61 rc
= efx_siena_mcdi_rpc(efx
, MC_CMD_MDIO_WRITE
, inbuf
, sizeof(inbuf
),
62 outbuf
, sizeof(outbuf
), &outlen
);
66 if (MCDI_DWORD(outbuf
, MDIO_WRITE_OUT_STATUS
) !=
67 MC_CMD_MDIO_STATUS_GOOD
)
73 bool efx_siena_mcdi_mac_check_fault(struct efx_nic
*efx
)
75 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LINK_OUT_LEN
);
79 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
81 rc
= efx_siena_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
82 outbuf
, sizeof(outbuf
), &outlength
);
86 return MCDI_DWORD(outbuf
, GET_LINK_OUT_MAC_FAULT
) != 0;
89 int efx_siena_mcdi_port_probe(struct efx_nic
*efx
)
93 /* Set up MDIO structure for PHY */
94 efx
->mdio
.mode_support
= MDIO_SUPPORTS_C45
| MDIO_EMULATE_C22
;
95 efx
->mdio
.mdio_read
= efx_mcdi_mdio_read
;
96 efx
->mdio
.mdio_write
= efx_mcdi_mdio_write
;
98 /* Fill out MDIO structure, loopback modes, and initial link state */
99 rc
= efx_siena_mcdi_phy_probe(efx
);
103 return efx_siena_mcdi_mac_init_stats(efx
);
106 void efx_siena_mcdi_port_remove(struct efx_nic
*efx
)
108 efx_siena_mcdi_phy_remove(efx
);
109 efx_siena_mcdi_mac_fini_stats(efx
);