xref: /openbmc/linux/drivers/net/ethernet/sfc/mcdi_port.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
243f775b2SBen Hutchings /****************************************************************************
3f7a6d2c4SBen Hutchings  * Driver for Solarflare network controllers and boards
4f7a6d2c4SBen Hutchings  * Copyright 2009-2013 Solarflare Communications Inc.
543f775b2SBen Hutchings  */
643f775b2SBen Hutchings 
743f775b2SBen Hutchings /*
843f775b2SBen Hutchings  * Driver for PHY related operations via MCDI.
943f775b2SBen Hutchings  */
1043f775b2SBen Hutchings 
1143f775b2SBen Hutchings #include <linux/slab.h>
1243f775b2SBen Hutchings #include "efx.h"
1383d00531SEdward Cree #include "mcdi_port.h"
1443f775b2SBen Hutchings #include "mcdi.h"
1543f775b2SBen Hutchings #include "mcdi_pcol.h"
1643f775b2SBen Hutchings #include "nic.h"
1743f775b2SBen Hutchings #include "selftest.h"
18e1253f39SAlex Maftei (amaftei) #include "mcdi_port_common.h"
1943f775b2SBen Hutchings 
efx_mcdi_mdio_read(struct net_device * net_dev,int prtad,int devad,u16 addr)2043f775b2SBen Hutchings static int efx_mcdi_mdio_read(struct net_device *net_dev,
2143f775b2SBen Hutchings 			      int prtad, int devad, u16 addr)
2243f775b2SBen Hutchings {
23*8cb03f4eSJonathan Cooper 	struct efx_nic *efx = efx_netdev_priv(net_dev);
2443f775b2SBen Hutchings 	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
2543f775b2SBen Hutchings 	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
2643f775b2SBen Hutchings 	size_t outlen;
2743f775b2SBen Hutchings 	int rc;
2843f775b2SBen Hutchings 
2943f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
3043f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
3143f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
3243f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
3343f775b2SBen Hutchings 
3443f775b2SBen Hutchings 	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
3543f775b2SBen Hutchings 			  outbuf, sizeof(outbuf), &outlen);
3643f775b2SBen Hutchings 	if (rc)
371e0b8120SEdward Cree 		return rc;
3843f775b2SBen Hutchings 
3943f775b2SBen Hutchings 	if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
4043f775b2SBen Hutchings 	    MC_CMD_MDIO_STATUS_GOOD)
4143f775b2SBen Hutchings 		return -EIO;
4243f775b2SBen Hutchings 
4343f775b2SBen Hutchings 	return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
4443f775b2SBen Hutchings }
4543f775b2SBen Hutchings 
efx_mcdi_mdio_write(struct net_device * net_dev,int prtad,int devad,u16 addr,u16 value)4643f775b2SBen Hutchings static int efx_mcdi_mdio_write(struct net_device *net_dev,
4743f775b2SBen Hutchings 			       int prtad, int devad, u16 addr, u16 value)
4843f775b2SBen Hutchings {
49*8cb03f4eSJonathan Cooper 	struct efx_nic *efx = efx_netdev_priv(net_dev);
5043f775b2SBen Hutchings 	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
5143f775b2SBen Hutchings 	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
5243f775b2SBen Hutchings 	size_t outlen;
5343f775b2SBen Hutchings 	int rc;
5443f775b2SBen Hutchings 
5543f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
5643f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
5743f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
5843f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
5943f775b2SBen Hutchings 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
6043f775b2SBen Hutchings 
6143f775b2SBen Hutchings 	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
6243f775b2SBen Hutchings 			  outbuf, sizeof(outbuf), &outlen);
6343f775b2SBen Hutchings 	if (rc)
641e0b8120SEdward Cree 		return rc;
6543f775b2SBen Hutchings 
6643f775b2SBen Hutchings 	if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
6743f775b2SBen Hutchings 	    MC_CMD_MDIO_STATUS_GOOD)
6843f775b2SBen Hutchings 		return -EIO;
6943f775b2SBen Hutchings 
7043f775b2SBen Hutchings 	return 0;
7143f775b2SBen Hutchings }
7243f775b2SBen Hutchings 
efx_mcdi_phy_get_caps(struct efx_nic * efx)738127d661SBen Hutchings u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
748127d661SBen Hutchings {
758127d661SBen Hutchings 	struct efx_mcdi_phy_data *phy_data = efx->phy_data;
768127d661SBen Hutchings 
778127d661SBen Hutchings 	return phy_data->supported_cap;
788127d661SBen Hutchings }
798127d661SBen Hutchings 
efx_mcdi_mac_check_fault(struct efx_nic * efx)8043f775b2SBen Hutchings bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
8143f775b2SBen Hutchings {
8243f775b2SBen Hutchings 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
8343f775b2SBen Hutchings 	size_t outlength;
8443f775b2SBen Hutchings 	int rc;
8543f775b2SBen Hutchings 
8643f775b2SBen Hutchings 	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
8743f775b2SBen Hutchings 
8843f775b2SBen Hutchings 	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
8943f775b2SBen Hutchings 			  outbuf, sizeof(outbuf), &outlength);
901e0b8120SEdward Cree 	if (rc)
9143f775b2SBen Hutchings 		return true;
9243f775b2SBen Hutchings 
9343f775b2SBen Hutchings 	return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
9443f775b2SBen Hutchings }
9543f775b2SBen Hutchings 
efx_mcdi_port_probe(struct efx_nic * efx)9643f775b2SBen Hutchings int efx_mcdi_port_probe(struct efx_nic *efx)
9743f775b2SBen Hutchings {
9843f775b2SBen Hutchings 	int rc;
9943f775b2SBen Hutchings 
10043f775b2SBen Hutchings 	/* Set up MDIO structure for PHY */
10143f775b2SBen Hutchings 	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
10243f775b2SBen Hutchings 	efx->mdio.mdio_read = efx_mcdi_mdio_read;
10343f775b2SBen Hutchings 	efx->mdio.mdio_write = efx_mcdi_mdio_write;
10443f775b2SBen Hutchings 
10543f775b2SBen Hutchings 	/* Fill out MDIO structure, loopback modes, and initial link state */
106c77289b4SEdward Cree 	rc = efx_mcdi_phy_probe(efx);
10743f775b2SBen Hutchings 	if (rc != 0)
10843f775b2SBen Hutchings 		return rc;
10943f775b2SBen Hutchings 
110272e53aaSEdward Cree 	return efx_mcdi_mac_init_stats(efx);
11143f775b2SBen Hutchings }
11243f775b2SBen Hutchings 
efx_mcdi_port_remove(struct efx_nic * efx)11343f775b2SBen Hutchings void efx_mcdi_port_remove(struct efx_nic *efx)
11443f775b2SBen Hutchings {
115c77289b4SEdward Cree 	efx_mcdi_phy_remove(efx);
116272e53aaSEdward Cree 	efx_mcdi_mac_fini_stats(efx);
11743f775b2SBen Hutchings }
118