FreeBSD kernel CXGB device code
cxgb_tn1010.c
Go to the documentation of this file.
1/**************************************************************************
2SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
4Copyright (c) 2008, Chelsio Inc.
5All rights reserved.
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12
13 2. Neither the name of the Chelsio Corporation nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27POSSIBILITY OF SUCH DAMAGE.
28
29***************************************************************************/
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34#include <cxgb_include.h>
35
36#undef msleep
37#define msleep t3_os_sleep
38
39/* TN1010 PHY specific registers. */
40enum {
42};
43
44/* IEEE auto-negotiation 10GBASE-T registers */
45enum {
49 ANEG_10G_STAT = 33
50};
51
52#define ADVERTISE_ENPAGE (1 << 12)
53#define ADVERTISE_10000FULL (1 << 12)
54#define ADVERTISE_LOOP_TIMING (1 << 0)
55
56/* vendor specific status register fields */
57#define F_XS_LANE_ALIGN_STAT (1 << 0)
58#define F_PCS_BLK_LOCK (1 << 1)
59#define F_PMD_SIGNAL_OK (1 << 2)
60#define F_LINK_STAT (1 << 3)
61#define F_ANEG_SPEED_1G (1 << 4)
62#define F_ANEG_MASTER (1 << 5)
63
64#define S_ANEG_STAT 6
65#define M_ANEG_STAT 0x3
66#define G_ANEG_STAT(x) (((x) >> S_ANEG_STAT) & M_ANEG_STAT)
67
68enum { /* autonegotiation status */
71 ANEG_FAILED = 3
72};
73
74/*
75 * Reset the PHY. May take up to 500ms to complete.
76 */
77static int tn1010_reset(struct cphy *phy, int wait)
78{
79 int err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
80 msleep(500);
81 return err;
82}
83
84static int tn1010_power_down(struct cphy *phy, int enable)
85{
87 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
88}
89
90static int tn1010_autoneg_enable(struct cphy *phy)
91{
92 int err;
93
94 err = tn1010_power_down(phy, 0);
95 if (!err)
96 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR, 0,
98 return err;
99}
100
101static int tn1010_autoneg_restart(struct cphy *phy)
102{
103 int err;
104
105 err = tn1010_power_down(phy, 0);
106 if (!err)
107 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR, 0,
109 return err;
110}
111
112static int tn1010_advertise(struct cphy *phy, unsigned int advert)
113{
114 int err, val;
115
116 if (!(advert & ADVERTISED_1000baseT_Full))
117 return -EINVAL; /* PHY can't disable 1000BASE-T */
118
120 if (advert & ADVERTISED_Pause)
121 val |= ADVERTISE_PAUSE_CAP;
122 if (advert & ADVERTISED_Asym_Pause)
125 if (err)
126 return err;
127
128 val = (advert & ADVERTISED_10000baseT_Full) ? ADVERTISE_10000FULL : 0;
131}
132
133static int tn1010_get_link_status(struct cphy *phy, int *link_state,
134 int *speed, int *duplex, int *fc)
135{
136 unsigned int status, lpa, adv;
137 int err, sp = -1, pause = 0;
138
140 if (err)
141 return err;
142
143 if (link_state)
144 *link_state = status & F_LINK_STAT ? PHY_LINK_UP :
146
147 if (G_ANEG_STAT(status) == ANEG_COMPLETE) {
148 sp = (status & F_ANEG_SPEED_1G) ? SPEED_1000 : SPEED_10000;
149
150 if (fc) {
151 err = mdio_read(phy, MDIO_DEV_ANEG, ANEG_LPA, &lpa);
152 if (!err)
154 &adv);
155 if (err)
156 return err;
157
158 if (lpa & adv & ADVERTISE_PAUSE_CAP)
159 pause = PAUSE_RX | PAUSE_TX;
160 else if ((lpa & ADVERTISE_PAUSE_CAP) &&
161 (lpa & ADVERTISE_PAUSE_ASYM) &&
162 (adv & ADVERTISE_PAUSE_ASYM))
163 pause = PAUSE_TX;
164 else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
165 (adv & ADVERTISE_PAUSE_CAP))
166 pause = PAUSE_RX;
167 }
168 }
169 if (speed)
170 *speed = sp;
171 if (duplex)
172 *duplex = DUPLEX_FULL;
173 if (fc)
174 *fc = pause;
175 return 0;
176}
177
178static int tn1010_set_speed_duplex(struct cphy *phy, int speed, int duplex)
179{
180 return -EINVAL; /* require autoneg */
181}
182
183#ifdef C99_NOT_SUPPORTED
184static struct cphy_ops tn1010_ops = {
193 NULL,
197};
198#else
199static struct cphy_ops tn1010_ops = {
201 .intr_enable = t3_phy_lasi_intr_enable,
202 .intr_disable = t3_phy_lasi_intr_disable,
203 .intr_clear = t3_phy_lasi_intr_clear,
204 .intr_handler = t3_phy_lasi_intr_handler,
205 .autoneg_enable = tn1010_autoneg_enable,
206 .autoneg_restart = tn1010_autoneg_restart,
207 .advertise = tn1010_advertise,
208 .set_speed_duplex = tn1010_set_speed_duplex,
209 .get_link_status = tn1010_get_link_status,
210 .power_down = tn1010_power_down,
211};
212#endif
213
214int t3_tn1010_phy_prep(pinfo_t *pinfo, int phy_addr,
215 const struct mdio_ops *mdio_ops)
216{
217 cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &tn1010_ops, mdio_ops,
220 "1000/10GBASE-T");
221 msleep(500); /* PHY needs up to 500ms to start responding to MDIO */
222 return 0;
223}
struct cphy phy
Definition: cxgb_adapter.h:5
static int mdio_read(struct cphy *phy, int mmd, int reg, unsigned int *valp)
Definition: cxgb_common.h:592
@ PAUSE_TX
Definition: cxgb_common.h:55
@ PAUSE_RX
Definition: cxgb_common.h:54
int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, unsigned int set)
Definition: cxgb_t3_hw.c:372
int t3_phy_reset(struct cphy *phy, int mmd, int wait)
Definition: cxgb_t3_hw.c:396
@ PHY_LINK_DOWN
Definition: cxgb_common.h:548
@ PHY_LINK_UP
Definition: cxgb_common.h:549
int t3_phy_lasi_intr_handler(struct cphy *phy)
Definition: cxgb_t3_hw.c:535
int t3_phy_lasi_intr_clear(struct cphy *phy)
Definition: cxgb_t3_hw.c:528
@ MDIO_DEV_VEND1
Definition: cxgb_common.h:508
@ MDIO_DEV_ANEG
Definition: cxgb_common.h:507
@ MDIO_DEV_PMA_PMD
Definition: cxgb_common.h:503
static int mdio_write(struct cphy *phy, int mmd, int reg, unsigned int val)
Definition: cxgb_common.h:598
int t3_phy_lasi_intr_enable(struct cphy *phy)
Definition: cxgb_t3_hw.c:518
int t3_phy_lasi_intr_disable(struct cphy *phy)
Definition: cxgb_t3_hw.c:523
static void cphy_init(struct cphy *phy, adapter_t *adapter, pinfo_t *pinfo, int phy_addr, struct cphy_ops *phy_ops, const struct mdio_ops *mdio_ops, unsigned int caps, const char *desc)
Definition: cxgb_common.h:605
#define ADVERTISED_1000baseT_Full
Definition: cxgb_osdep.h:246
#define ADVERTISED_Pause
Definition: cxgb_osdep.h:254
#define ADVERTISED_10000baseT_Full
Definition: cxgb_osdep.h:253
#define ADVERTISE_PAUSE_ASYM
Definition: cxgb_osdep.h:150
#define SUPPORTED_AUI
Definition: cxgb_osdep.h:232
#define SPEED_1000
Definition: cxgb_osdep.h:265
#define ADVERTISE_NPAGE
Definition: cxgb_osdep.h:166
#define SUPPORTED_TP
Definition: cxgb_osdep.h:231
#define SUPPORTED_10000baseT_Full
Definition: cxgb_osdep.h:236
#define DUPLEX_FULL
Definition: cxgb_osdep.h:268
#define SUPPORTED_Autoneg
Definition: cxgb_osdep.h:230
#define SPEED_10000
Definition: cxgb_osdep.h:266
#define SUPPORTED_1000baseT_Full
Definition: cxgb_osdep.h:229
#define BMCR_ANRESTART
Definition: cxgb_osdep.h:140
#define ADVERTISE_CSMA
Definition: cxgb_osdep.h:165
#define BMCR_ANENABLE
Definition: cxgb_osdep.h:137
#define ADVERTISED_Asym_Pause
Definition: cxgb_osdep.h:255
#define ADVERTISE_PAUSE_CAP
Definition: cxgb_osdep.h:149
#define ADVERTISE_10000FULL
Definition: cxgb_tn1010.c:53
static int tn1010_get_link_status(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc)
Definition: cxgb_tn1010.c:133
static int tn1010_autoneg_enable(struct cphy *phy)
Definition: cxgb_tn1010.c:90
#define ADVERTISE_ENPAGE
Definition: cxgb_tn1010.c:52
#define G_ANEG_STAT(x)
Definition: cxgb_tn1010.c:66
#define F_ANEG_SPEED_1G
Definition: cxgb_tn1010.c:61
#define ADVERTISE_LOOP_TIMING
Definition: cxgb_tn1010.c:54
static int tn1010_autoneg_restart(struct cphy *phy)
Definition: cxgb_tn1010.c:101
#define F_LINK_STAT
Definition: cxgb_tn1010.c:60
static int tn1010_reset(struct cphy *phy, int wait)
Definition: cxgb_tn1010.c:77
@ TN1010_VEND1_STAT
Definition: cxgb_tn1010.c:41
__FBSDID("$FreeBSD$")
static int tn1010_advertise(struct cphy *phy, unsigned int advert)
Definition: cxgb_tn1010.c:112
#define msleep
Definition: cxgb_tn1010.c:37
static int tn1010_power_down(struct cphy *phy, int enable)
Definition: cxgb_tn1010.c:84
static struct cphy_ops tn1010_ops
Definition: cxgb_tn1010.c:199
static int tn1010_set_speed_duplex(struct cphy *phy, int speed, int duplex)
Definition: cxgb_tn1010.c:178
@ ANEG_IN_PROGR
Definition: cxgb_tn1010.c:69
@ ANEG_COMPLETE
Definition: cxgb_tn1010.c:70
@ ANEG_FAILED
Definition: cxgb_tn1010.c:71
int t3_tn1010_phy_prep(pinfo_t *pinfo, int phy_addr, const struct mdio_ops *mdio_ops)
Definition: cxgb_tn1010.c:214
@ ANEG_10G_CTRL
Definition: cxgb_tn1010.c:48
@ ANEG_10G_STAT
Definition: cxgb_tn1010.c:49
@ ANEG_ADVER
Definition: cxgb_tn1010.c:46
@ ANEG_LPA
Definition: cxgb_tn1010.c:47
int(* reset)(struct cphy *phy, int wait)
Definition: cxgb_common.h:555
struct cphy phy
Definition: cxgb_adapter.h:97
struct adapter * adapter
Definition: cxgb_adapter.h:92