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