xref: /freebsd/sys/dev/al_eth/al_init_eth_lm.h (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
1 /*-
2  * Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates
3  * All rights reserved.
4  *
5  * Developed by Semihalf.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 /**
32  *  Ethernet
33  *  @{
34  * @file   al_init_eth_lm.h
35  *
36  * @brief ethernet link management common utilities
37  *
38  * Common operation example:
39  * @code
40  *      int main()
41  *      {
42  *		struct al_eth_lm_context lm_context;
43  *		struct al_eth_lm_init_params lm_params;
44  *		enum al_eth_lm_link_mode old_mode;
45  *		enum al_eth_lm_link_mode new_mode;
46  *		al_bool	fault;
47  *		al_bool				link_up;
48  *		int rc = 0;
49  *
50  *		lm_params.adapter = hal_adapter;
51  *		lm_params.serdes_obj = serdes;
52  *		lm_params.grp = grp;
53  *		lm_params.lane = lane;
54  *		lm_params.sfp_detection = true;
55  *		lm_params.link_training = true;
56  *		lm_params.rx_equal = true
57  *		lm_params.static_values = true;
58  *		lm_params.kr_fec_enable = false;
59  *		lm_params.eeprom_read = &my_eeprom_read;
60  *		lm_params.eeprom_context = context;
61  *		lm_params.get_random_byte = &my_rand_byte;
62  *		lm_params.default_mode = AL_ETH_LM_MODE_10G_DA;
63  *
64  *		al_eth_lm_init(&lm_context, &lm_params);
65  *
66  *		rc = al_eth_lm_link_detection(&lm_context, &fault, &old_mode, &new_mode);
67  *		if (fault == false)
68  *			return; // in this case the link is still up
69  *
70  *		if (rc) {
71  *			printf("link detection failed on error\n");
72  *			return;
73  *		}
74  *
75  *		if (old_mode != new_mode) {
76  *			 // perform serdes configuration if needed
77  *
78  *			 // mac stop / start / config if needed
79  *		}
80  *
81  *		spin_lock(lock);
82  *		rc = al_eth_lm_link_establish($lm_context, &link_up);
83  *		spin_unlock(lock);
84  *		if (rc) {
85  *			printf("establish link failed\n");
86  *			return;
87  *		}
88  *
89  *		if (link_up)
90  *			printf("Link established successfully\n");
91  *		else
92  *			printf("No signal found. probably the link partner is disconnected\n");
93  *      }
94  * @endcode
95  *
96  */
97 
98 #ifndef __AL_INIT_ETH_LM_H__
99 #define __AL_INIT_ETH_LM_H__
100 
101 #include <al_serdes.h>
102 #include <al_hal_eth.h>
103 #include "al_init_eth_kr.h"
104 
105 enum al_eth_lm_link_mode {
106 	AL_ETH_LM_MODE_DISCONNECTED,
107 	AL_ETH_LM_MODE_10G_OPTIC,
108 	AL_ETH_LM_MODE_10G_DA,
109 	AL_ETH_LM_MODE_1G,
110 	AL_ETH_LM_MODE_25G,
111 };
112 
113 enum al_eth_lm_max_speed {
114 	AL_ETH_LM_MAX_SPEED_MAX,
115 	AL_ETH_LM_MAX_SPEED_25G,
116 	AL_ETH_LM_MAX_SPEED_10G,
117 	AL_ETH_LM_MAX_SPEED_1G,
118 };
119 
120 enum al_eth_lm_link_state {
121 	AL_ETH_LM_LINK_DOWN,
122 	AL_ETH_LM_LINK_DOWN_RF,
123 	AL_ETH_LM_LINK_UP,
124 };
125 
126 enum al_eth_lm_led_config_speed {
127 	AL_ETH_LM_LED_CONFIG_1G,
128 	AL_ETH_LM_LED_CONFIG_10G,
129 	AL_ETH_LM_LED_CONFIG_25G,
130 };
131 
132 struct al_eth_lm_led_config_data {
133 	enum al_eth_lm_led_config_speed	speed;
134 };
135 
136 struct al_eth_lm_context {
137 	struct al_hal_eth_adapter	*adapter;
138 	struct al_serdes_grp_obj	*serdes_obj;
139 	enum al_serdes_lane		lane;
140 
141 	uint32_t			link_training_failures;
142 
143 	boolean_t			tx_param_dirty;
144 	boolean_t			serdes_tx_params_valid;
145 	struct al_serdes_adv_tx_params	tx_params_override;
146 	boolean_t			rx_param_dirty;
147 	boolean_t			serdes_rx_params_valid;
148 	struct al_serdes_adv_rx_params	rx_params_override;
149 
150 	struct al_eth_an_adv		local_adv;
151 	struct al_eth_an_adv		partner_adv;
152 
153 	enum al_eth_lm_link_mode	mode;
154 	uint8_t				da_len;
155 	boolean_t			debug;
156 
157 	/* configurations */
158 	boolean_t			sfp_detection;
159 	uint8_t				sfp_bus_id;
160 	uint8_t				sfp_i2c_addr;
161 
162 	enum al_eth_lm_link_mode	default_mode;
163 	uint8_t				default_dac_len;
164 	boolean_t			link_training;
165 	boolean_t			rx_equal;
166 	boolean_t			static_values;
167 
168 	boolean_t			retimer_exist;
169 	enum al_eth_retimer_type	retimer_type;
170 	uint8_t				retimer_bus_id;
171 	uint8_t				retimer_i2c_addr;
172 	enum al_eth_retimer_channel	retimer_channel;
173 
174 	/* services */
175 	int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
176 	    uint8_t reg_addr, uint8_t *val);
177 	int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
178 	    uint8_t reg_addr, uint8_t val);
179 	void *i2c_context;
180 	uint8_t (*get_random_byte)(void);
181 
182 	int (*gpio_get)(unsigned int gpio);
183 	uint32_t			gpio_present;
184 
185 	enum al_eth_retimer_channel	retimer_tx_channel;
186 	boolean_t			retimer_configured;
187 
188 	enum al_eth_lm_max_speed	max_speed;
189 
190 	boolean_t			sfp_detect_force_mode;
191 
192 	enum al_eth_lm_link_state	link_state;
193 	boolean_t			new_port;
194 
195 	boolean_t (*lm_pause)(void *handle);
196 
197 	void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);
198 };
199 
200 struct al_eth_lm_init_params {
201 	/* pointer to HAL context */
202 	struct al_hal_eth_adapter	*adapter;
203 	/* pointer to serdes object */
204 	struct al_serdes_grp_obj	*serdes_obj;
205 	/* serdes lane for this port */
206 	enum al_serdes_lane		lane;
207 
208 	/*
209 	 * set to true to perform sfp detection if the link is down.
210 	 * when set to true, eeprom_read below should NOT be NULL.
211 	 */
212 	boolean_t			sfp_detection;
213 	/* i2c bus id of the SFP for this port */
214 	uint8_t				sfp_bus_id;
215 	/* i2c addr of the SFP for this port */
216 	uint8_t				sfp_i2c_addr;
217 	/*
218 	 * default mode, and dac length will be used in case sfp_detection
219 	 * is not set or in case the detection failed.
220 	 */
221 	enum al_eth_lm_link_mode	default_mode;
222 	uint8_t				default_dac_len;
223 
224 	/* the i2c bus id and addr of the retimer in case it exist */
225 	uint8_t				retimer_bus_id;
226 	uint8_t				retimer_i2c_addr;
227 	/* retimer channel connected to this port */
228 	enum al_eth_retimer_channel	retimer_channel;
229 	enum al_eth_retimer_channel	retimer_tx_channel;
230 	/* retimer type if exist */
231 	enum al_eth_retimer_type	retimer_type;
232 
233 	/*
234 	 * the following parameters control what mechanisms to run
235 	 * on link_establish with the following steps:
236 	 * - if retimer_exist is set, the retimer will be configured based on DA len.
237 	 * - if link_training is set and DA detected run link training. if succeed return 0
238 	 * - if rx_equal is set serdes equalization will be run to configure the rx parameters.
239 	 * - if static_values is set, tx and rx values will be set based on static values.
240 	 */
241 	boolean_t			retimer_exist;
242 	boolean_t			link_training;
243 	boolean_t			rx_equal;
244 	boolean_t			static_values;
245 
246 	/* enable / disable fec capabilities in AN */
247 	boolean_t			kr_fec_enable;
248 
249 	/*
250 	 * pointer to function that's read 1 byte from eeprom
251 	 * in case no eeprom is connected should return -ETIMEDOUT
252 	 */
253 	int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
254 	    uint8_t reg_addr, uint8_t *val);
255 	int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
256 	    uint8_t reg_addr, uint8_t val);
257 	void *i2c_context;
258 	/* pointer to function that return 1 rand byte */
259 	uint8_t (*get_random_byte)(void);
260 
261 	/* pointer to function that gets GPIO value - if NULL gpio present won't be used */
262 	int (*gpio_get)(unsigned int gpio);
263 	/* gpio number connected to the SFP present pin */
264 	uint32_t			gpio_present;
265 
266 	enum al_eth_lm_max_speed	max_speed;
267 
268 	/* in case force mode is true - the default mode will be set regardless to
269 	 * the SFP EEPROM content */
270 	boolean_t			sfp_detect_force_mode;
271 
272 	/* lm pause callback - in case it return true the LM will try to preserve
273 	 * the current link status and will not try to establish new link (and will not
274 	 * access to i2c bus) */
275 	boolean_t (*lm_pause)(void *handle);
276 
277 	/* config ethernet LEDs according to data. can be NULL if no configuration needed */
278 	void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);
279 };
280 
281 /**
282  * initialize link management context and set configuration
283  *
284  * @param  lm_context pointer to link management context
285  * @param  params  parameters passed from upper layer
286  *
287  * @return 0 in case of success. otherwise on failure.
288  */
289 int al_eth_lm_init(struct al_eth_lm_context *lm_context,
290     struct al_eth_lm_init_params *params);
291 
292 /**
293  * perform link status check. in case link is down perform sfp detection
294  *
295  * @param lm_context pointer to link management context
296  * @param link_fault indicate if the link is down
297  * @param old_mode the last working mode
298  * @param new_mode the new mode detected in this call
299  *
300  * @return  0 in case of success. otherwise on failure.
301  */
302 int al_eth_lm_link_detection(struct al_eth_lm_context *lm_context,
303     boolean_t *link_fault, enum al_eth_lm_link_mode *old_mode,
304     enum al_eth_lm_link_mode *new_mode);
305 
306 /**
307  * run LT, rx equalization and static values override according to configuration
308  * This function MUST be called inside a lock as it using common serdes registers
309  *
310  * @param lm_context pointer to link management context
311  * @param link_up set to true in case link is establish successfully
312  *
313  * @return < 0 in case link was failed to be established
314  */
315 int al_eth_lm_link_establish(struct al_eth_lm_context *lm_context,
316     boolean_t *link_up);
317 
318 /**
319  * override the default static parameters
320  *
321  * @param lm_context pointer to link management context
322  * @param tx_params pointer to new tx params
323  * @param rx_params pointer to new rx params
324  *
325  * @return  0 in case of success. otherwise on failure.
326  **/
327 int al_eth_lm_static_parameters_override(struct al_eth_lm_context *lm_context,
328     struct al_serdes_adv_tx_params *tx_params,
329     struct al_serdes_adv_rx_params *rx_params);
330 
331 /**
332  * disable serdes parameters override
333  *
334  * @param lm_context pointer to link management context
335  * @param tx_params set to true to disable override of tx params
336  * @param rx_params set to true to disable override of rx params
337  *
338  * @return  0 in case of success. otherwise on failure.
339  **/
340 int al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context *lm_context,
341    boolean_t tx_params, boolean_t rx_params);
342 
343 /**
344  * get the static parameters that are being used
345  * if the parameters was override - return the override values
346  * else return the current values of the parameters
347  *
348  * @param  lm_context pointer to link management context
349  * @param  tx_params  pointer to new tx params
350  * @param  rx_params  pointer to new rx params
351  *
352  * @return  0 in case of success. otherwise on failure.
353  */
354 int al_eth_lm_static_parameters_get(struct al_eth_lm_context *lm_context,
355     struct al_serdes_adv_tx_params *tx_params,
356     struct al_serdes_adv_rx_params *rx_params);
357 
358 /**
359  * convert link management mode to string
360  *
361  * @param  val link management mode
362  *
363  * @return     string of the mode
364  */
365 const char *al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val);
366 
367 /**
368  * print all debug messages
369  *
370  * @param lm_context pointer to link management context
371  * @param enable     set to true to enable debug mode
372  */
373 void al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,
374     boolean_t enable);
375 #endif
376