xref: /openbmc/linux/drivers/net/ethernet/sfc/siena/mcdi_port.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1d48523cbSMartin Habets // SPDX-License-Identifier: GPL-2.0-only
2d48523cbSMartin Habets /****************************************************************************
3d48523cbSMartin Habets  * Driver for Solarflare network controllers and boards
4d48523cbSMartin Habets  * Copyright 2009-2013 Solarflare Communications Inc.
5d48523cbSMartin Habets  */
6d48523cbSMartin Habets 
7d48523cbSMartin Habets /*
8d48523cbSMartin Habets  * Driver for PHY related operations via MCDI.
9d48523cbSMartin Habets  */
10d48523cbSMartin Habets 
11d48523cbSMartin Habets #include <linux/slab.h>
12d48523cbSMartin Habets #include "efx.h"
13d48523cbSMartin Habets #include "mcdi_port.h"
14d48523cbSMartin Habets #include "mcdi.h"
15d48523cbSMartin Habets #include "mcdi_pcol.h"
16d48523cbSMartin Habets #include "nic.h"
17d48523cbSMartin Habets #include "selftest.h"
18d48523cbSMartin Habets #include "mcdi_port_common.h"
19d48523cbSMartin Habets 
efx_mcdi_mdio_read(struct net_device * net_dev,int prtad,int devad,u16 addr)20d48523cbSMartin Habets static int efx_mcdi_mdio_read(struct net_device *net_dev,
21d48523cbSMartin Habets 			      int prtad, int devad, u16 addr)
22d48523cbSMartin Habets {
23d48523cbSMartin Habets 	struct efx_nic *efx = netdev_priv(net_dev);
24d48523cbSMartin Habets 	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
25d48523cbSMartin Habets 	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
26d48523cbSMartin Habets 	size_t outlen;
27d48523cbSMartin Habets 	int rc;
28d48523cbSMartin Habets 
29d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
30d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
31d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
32d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
33d48523cbSMartin Habets 
34*4d49e5cdSMartin Habets 	rc = efx_siena_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
35d48523cbSMartin Habets 				outbuf, sizeof(outbuf), &outlen);
36d48523cbSMartin Habets 	if (rc)
37d48523cbSMartin Habets 		return rc;
38d48523cbSMartin Habets 
39d48523cbSMartin Habets 	if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
40d48523cbSMartin Habets 	    MC_CMD_MDIO_STATUS_GOOD)
41d48523cbSMartin Habets 		return -EIO;
42d48523cbSMartin Habets 
43d48523cbSMartin Habets 	return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
44d48523cbSMartin Habets }
45d48523cbSMartin Habets 
efx_mcdi_mdio_write(struct net_device * net_dev,int prtad,int devad,u16 addr,u16 value)46d48523cbSMartin Habets static int efx_mcdi_mdio_write(struct net_device *net_dev,
47d48523cbSMartin Habets 			       int prtad, int devad, u16 addr, u16 value)
48d48523cbSMartin Habets {
49d48523cbSMartin Habets 	struct efx_nic *efx = netdev_priv(net_dev);
50d48523cbSMartin Habets 	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
51d48523cbSMartin Habets 	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
52d48523cbSMartin Habets 	size_t outlen;
53d48523cbSMartin Habets 	int rc;
54d48523cbSMartin Habets 
55d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
56d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
57d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
58d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
59d48523cbSMartin Habets 	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
60d48523cbSMartin Habets 
61*4d49e5cdSMartin Habets 	rc = efx_siena_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
62d48523cbSMartin Habets 				outbuf, sizeof(outbuf), &outlen);
63d48523cbSMartin Habets 	if (rc)
64d48523cbSMartin Habets 		return rc;
65d48523cbSMartin Habets 
66d48523cbSMartin Habets 	if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
67d48523cbSMartin Habets 	    MC_CMD_MDIO_STATUS_GOOD)
68d48523cbSMartin Habets 		return -EIO;
69d48523cbSMartin Habets 
70d48523cbSMartin Habets 	return 0;
71d48523cbSMartin Habets }
72d48523cbSMartin Habets 
efx_siena_mcdi_mac_check_fault(struct efx_nic * efx)73*4d49e5cdSMartin Habets bool efx_siena_mcdi_mac_check_fault(struct efx_nic *efx)
74d48523cbSMartin Habets {
75d48523cbSMartin Habets 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
76d48523cbSMartin Habets 	size_t outlength;
77d48523cbSMartin Habets 	int rc;
78d48523cbSMartin Habets 
79d48523cbSMartin Habets 	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
80d48523cbSMartin Habets 
81*4d49e5cdSMartin Habets 	rc = efx_siena_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
82d48523cbSMartin Habets 				outbuf, sizeof(outbuf), &outlength);
83d48523cbSMartin Habets 	if (rc)
84d48523cbSMartin Habets 		return true;
85d48523cbSMartin Habets 
86d48523cbSMartin Habets 	return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
87d48523cbSMartin Habets }
88d48523cbSMartin Habets 
efx_siena_mcdi_port_probe(struct efx_nic * efx)89*4d49e5cdSMartin Habets int efx_siena_mcdi_port_probe(struct efx_nic *efx)
90d48523cbSMartin Habets {
91d48523cbSMartin Habets 	int rc;
92d48523cbSMartin Habets 
93d48523cbSMartin Habets 	/* Set up MDIO structure for PHY */
94d48523cbSMartin Habets 	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
95d48523cbSMartin Habets 	efx->mdio.mdio_read = efx_mcdi_mdio_read;
96d48523cbSMartin Habets 	efx->mdio.mdio_write = efx_mcdi_mdio_write;
97d48523cbSMartin Habets 
98d48523cbSMartin Habets 	/* Fill out MDIO structure, loopback modes, and initial link state */
99*4d49e5cdSMartin Habets 	rc = efx_siena_mcdi_phy_probe(efx);
100d48523cbSMartin Habets 	if (rc != 0)
101d48523cbSMartin Habets 		return rc;
102d48523cbSMartin Habets 
103*4d49e5cdSMartin Habets 	return efx_siena_mcdi_mac_init_stats(efx);
104d48523cbSMartin Habets }
105d48523cbSMartin Habets 
efx_siena_mcdi_port_remove(struct efx_nic * efx)106*4d49e5cdSMartin Habets void efx_siena_mcdi_port_remove(struct efx_nic *efx)
107d48523cbSMartin Habets {
108*4d49e5cdSMartin Habets 	efx_siena_mcdi_phy_remove(efx);
109*4d49e5cdSMartin Habets 	efx_siena_mcdi_mac_fini_stats(efx);
110d48523cbSMartin Habets }
111