2 *******************************************************************************
3 Copyright (C) 2015 Annapurna Labs Ltd.
5 This file may be licensed under the terms of the Annapurna Labs Commercial
8 Alternatively, this file can be distributed under the terms of the GNU General
9 Public License V2 as published by the Free Software Foundation and can be
10 found at http://www.gnu.org/licenses/gpl-2.0.html
12 Alternatively, redistribution and use in source and binary forms, with or
13 without modification, are permitted provided that the following conditions are
16 * Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer.
19 * Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in
21 the documentation and/or other materials provided with the
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *******************************************************************************/
38 * @defgroup group_serdes_api API
39 * SerDes HAL driver API
40 * @ingroup group_serdes SerDes
43 * @file al_hal_serdes.h
45 * @brief Header file for the SerDes HAL driver
49 #ifndef __AL_HAL_SERDES_H__
50 #define __AL_HAL_SERDES_H__
52 #include "al_hal_common.h"
62 enum al_serdes_group {
71 struct al_serdes_group_info {
73 * Group parent object - filled automatically by al_serdes_handle_init
75 struct al_serdes_obj *pobj;
78 * Group specific register base - filled automatically by
79 * al_sedres_handle_init
81 struct al_serdes_regs __iomem *regs_base;
84 struct al_serdes_obj {
85 struct al_serdes_group_info grp_info[AL_SRDS_NUM_GROUPS];
88 enum al_serdes_reg_page {
89 AL_SRDS_REG_PAGE_0_LANE_0 = 0,
90 AL_SRDS_REG_PAGE_1_LANE_1,
91 AL_SRDS_REG_PAGE_2_LANE_2,
92 AL_SRDS_REG_PAGE_3_LANE_3,
93 AL_SRDS_REG_PAGE_4_COMMON,
94 AL_SRDS_REG_PAGE_0123_LANES_0123 = 7,
97 enum al_serdes_reg_type {
98 AL_SRDS_REG_TYPE_PMA = 0,
102 enum al_serdes_lane {
103 AL_SRDS_LANE_0 = AL_SRDS_REG_PAGE_0_LANE_0,
104 AL_SRDS_LANE_1 = AL_SRDS_REG_PAGE_1_LANE_1,
105 AL_SRDS_LANE_2 = AL_SRDS_REG_PAGE_2_LANE_2,
106 AL_SRDS_LANE_3 = AL_SRDS_REG_PAGE_3_LANE_3,
109 AL_SRDS_LANES_0123 = AL_SRDS_REG_PAGE_0123_LANES_0123,
112 /** Serdes loopback mode */
113 enum al_serdes_lb_mode {
118 * Transmits the untimed, partial equalized RX signal out the transmit
120 * No clock used (untimed)
122 AL_SRDS_LB_MODE_PMA_IO_UN_TIMED_RX_TO_TX,
125 * Loops back the TX serializer output into the CDR.
126 * CDR recovered bit clock used (without attenuation)
128 AL_SRDS_LB_MODE_PMA_INTERNALLY_BUFFERED_SERIAL_TX_TO_RX,
131 * Loops back the TX driver IO signal to the RX IO pins
132 * CDR recovered bit clock used (only through IO)
134 AL_SRDS_LB_MODE_PMA_SERIAL_TX_IO_TO_RX_IO,
137 * Parallel loopback from the PMA receive lane data ports, to the
138 * transmit lane data ports
139 * CDR recovered bit clock used
141 AL_SRDS_LB_MODE_PMA_PARALLEL_RX_TO_TX,
143 /** Loops received data after elastic buffer to transmit path */
144 AL_SRDS_LB_MODE_PCS_PIPE,
146 /** Loops TX data (to PMA) to RX path (instead of PMA data) */
147 AL_SRDS_LB_MODE_PCS_NEAR_END,
149 /** Loops receive data prior to interface block to transmit path */
150 AL_SRDS_LB_MODE_PCS_FAR_END,
153 /** Serdes BIST pattern */
154 enum al_serdes_bist_pattern {
155 AL_SRDS_BIST_PATTERN_USER,
156 AL_SRDS_BIST_PATTERN_PRBS7,
157 AL_SRDS_BIST_PATTERN_PRBS23,
158 AL_SRDS_BIST_PATTERN_PRBS31,
159 AL_SRDS_BIST_PATTERN_CLK1010,
162 /** SerDes group rate */
163 enum al_serdes_rate {
170 /** SerDes power mode */
179 /** SerDes PCIe Rate - values are important for proper behavior */
180 enum al_serdes_pcie_rate {
181 AL_SRDS_PCIE_RATE_GEN1 = 0,
182 AL_SRDS_PCIE_RATE_GEN2,
183 AL_SRDS_PCIE_RATE_GEN3,
187 * Initializes a SERDES object
189 * @param serdes_regs_base
190 * The SERDES register file base pointer
193 * An allocated, non initialized object context
196 * @return 0 if no error found.
199 int al_serdes_handle_init(
200 void __iomem *serdes_regs_base,
201 struct al_serdes_obj *obj);
204 * SERDES register read
206 * Reads a SERDES register
215 * The SERDES register page within the group
218 * The SERDES register type (PMA /PCS)
221 * The SERDES register offset (0 - 4095)
227 * @return 0 if no error found.
230 int al_serdes_reg_read(
231 struct al_serdes_obj *obj,
232 enum al_serdes_group grp,
233 enum al_serdes_reg_page page,
234 enum al_serdes_reg_type type,
239 * SERDES register write
241 * Writes a SERDES register
250 * The SERDES register page within the group
253 * The SERDES register type (PMA /PCS)
256 * The SERDES register offset (0 - 4095)
262 * @return 0 if no error found.
265 int al_serdes_reg_write(
266 struct al_serdes_obj *obj,
267 enum al_serdes_group grp,
268 enum al_serdes_reg_page page,
269 enum al_serdes_reg_type type,
274 * Enable BIST required overrides
281 * The required speed rate
283 void al_serdes_bist_overrides_enable(
284 struct al_serdes_obj *obj,
285 enum al_serdes_group grp,
286 enum al_serdes_rate rate);
289 * Disable BIST required overrides
296 * The required speed rate
298 void al_serdes_bist_overrides_disable(
299 struct al_serdes_obj *obj,
300 enum al_serdes_group grp);
310 * The Rx required rate
312 void al_serdes_rx_rate_change(
313 struct al_serdes_obj *obj,
314 enum al_serdes_group grp,
315 enum al_serdes_rate rate);
318 * SERDES lane Rx rate change software flow enable
325 * The SERDES lane within the group
327 void al_serdes_lane_rx_rate_change_sw_flow_en(
328 struct al_serdes_obj *obj,
329 enum al_serdes_group grp,
330 enum al_serdes_lane lane);
333 * SERDES lane Rx rate change software flow disable
340 * The SERDES lane within the group
342 void al_serdes_lane_rx_rate_change_sw_flow_dis(
343 struct al_serdes_obj *obj,
344 enum al_serdes_group grp,
345 enum al_serdes_lane lane);
348 * PCIe lane rate override check
355 * The SERDES lane within the group
356 * @returns AL_TRUE if the override is enabled
358 al_bool al_serdes_lane_pcie_rate_override_is_enabled(
359 struct al_serdes_obj *obj,
360 enum al_serdes_group grp,
361 enum al_serdes_lane lane);
364 * PCIe lane rate override control
371 * The SERDES lane within the group
375 void al_serdes_lane_pcie_rate_override_enable_set(
376 struct al_serdes_obj *obj,
377 enum al_serdes_group grp,
378 enum al_serdes_lane lane,
389 * The SERDES lane within the group
391 enum al_serdes_pcie_rate al_serdes_lane_pcie_rate_get(
392 struct al_serdes_obj *obj,
393 enum al_serdes_group grp,
394 enum al_serdes_lane lane);
404 * The SERDES lane within the group
408 void al_serdes_lane_pcie_rate_set(
409 struct al_serdes_obj *obj,
410 enum al_serdes_group grp,
411 enum al_serdes_lane lane,
412 enum al_serdes_pcie_rate rate);
415 * SERDES group power mode control
422 * The required power mode
424 void al_serdes_group_pm_set(
425 struct al_serdes_obj *obj,
426 enum al_serdes_group grp,
427 enum al_serdes_pm pm);
430 * SERDES lane power mode control
437 * The SERDES lane within the group
439 * The required RX power mode
441 * The required TX power mode
443 void al_serdes_lane_pm_set(
444 struct al_serdes_obj *obj,
445 enum al_serdes_group grp,
446 enum al_serdes_lane lane,
447 enum al_serdes_pm rx_pm,
448 enum al_serdes_pm tx_pm);
451 * SERDES group PMA hard reset
453 * Controls Serdes group PMA hard reset
462 * Enable/disable hard reset
464 void al_serdes_pma_hard_reset_group(
465 struct al_serdes_obj *obj,
466 enum al_serdes_group grp,
470 * SERDES lane PMA hard reset
472 * Controls Serdes lane PMA hard reset
481 * The SERDES lane within the group
484 * Enable/disable hard reset
486 void al_serdes_pma_hard_reset_lane(
487 struct al_serdes_obj *obj,
488 enum al_serdes_group grp,
489 enum al_serdes_lane lane,
493 * SERDES loopback control
495 * Controls the loopback
504 * The SERDES lane within the group
507 * The requested loopback mode
510 void al_serdes_loopback_control(
511 struct al_serdes_obj *obj,
512 enum al_serdes_group grp,
513 enum al_serdes_lane lane,
514 enum al_serdes_lb_mode mode);
517 * SERDES BIST pattern selection
519 * Selects the BIST pattern to be used
531 * The pattern user data (when pattern == AL_SRDS_BIST_PATTERN_USER)
532 * 80 bits (8 bytes array)
535 void al_serdes_bist_pattern_select(
536 struct al_serdes_obj *obj,
537 enum al_serdes_group grp,
538 enum al_serdes_bist_pattern pattern,
542 * SERDES BIST TX Enable
544 * Enables/disables TX BIST per lane
553 * The SERDES lane within the group
556 * Enable or disable TX BIST
558 void al_serdes_bist_tx_enable(
559 struct al_serdes_obj *obj,
560 enum al_serdes_group grp,
561 enum al_serdes_lane lane,
565 * SERDES BIST TX single bit error injection
567 * Injects single bit error during a TX BIST
575 void al_serdes_bist_tx_err_inject(
576 struct al_serdes_obj *obj,
577 enum al_serdes_group grp);
580 * SERDES BIST RX Enable
582 * Enables/disables RX BIST per lane
591 * The SERDES lane within the group
594 * Enable or disable TX BIST
596 void al_serdes_bist_rx_enable(
597 struct al_serdes_obj *obj,
598 enum al_serdes_group grp,
599 enum al_serdes_lane lane,
603 * SERDES BIST RX status
605 * Checks the RX BIST status for a specific SERDES lane
614 * The SERDES lane within the group
617 * An indication whether RX BIST is locked
619 * @param err_cnt_overflow
620 * An indication whether error count overflow occured
623 * Current bit error count
625 void al_serdes_bist_rx_status(
626 struct al_serdes_obj *obj,
627 enum al_serdes_group grp,
628 enum al_serdes_lane lane,
630 al_bool *err_cnt_overflow,
634 * SERDES Digital Test Bus
636 * Samples the digital test bus of a specific SERDES lane
645 * The SERDES lane within the group
648 * The selected sampling group (0 - 31)
650 * @param sampled_data
651 * The sampled data (5 bytes array)
654 * @return 0 if no error found.
657 int al_serdes_digital_test_bus(
658 struct al_serdes_obj *obj,
659 enum al_serdes_group grp,
660 enum al_serdes_lane lane,
662 uint8_t *sampled_data);
665 /* KR link training */
667 * Set the tx de-emphasis to preset values
669 * @param obj The object context
671 * @param grp The SERDES group
673 * @param lane The SERDES lane within the group
676 void al_serdes_tx_deemph_preset(
677 struct al_serdes_obj *obj,
678 enum al_serdes_group grp,
679 enum al_serdes_lane lane);
682 * Tx de-emphasis parameters
684 enum al_serdes_tx_deemph_param {
685 AL_SERDES_TX_DEEMP_C_ZERO, /*< c(0) */
686 AL_SERDES_TX_DEEMP_C_PLUS, /*< c(1) */
687 AL_SERDES_TX_DEEMP_C_MINUS, /*< c(-1) */
691 * Increase tx de-emphasis param.
693 * @param obj The object context
695 * @param grp The SERDES group
697 * @param lane The SERDES lane within the group
699 * @param param which tx de-emphasis to change
701 * @return false in case max is reached. true otherwise.
703 al_bool al_serdes_tx_deemph_inc(
704 struct al_serdes_obj *obj,
705 enum al_serdes_group grp,
706 enum al_serdes_lane lane,
707 enum al_serdes_tx_deemph_param param);
710 * Decrease tx de-emphasis param.
712 * @param obj The object context
714 * @param grp The SERDES group
716 * @param lane The SERDES lane within the group
718 * @param param which tx de-emphasis to change
720 * @return false in case min is reached. true otherwise.
722 al_bool al_serdes_tx_deemph_dec(
723 struct al_serdes_obj *obj,
724 enum al_serdes_group grp,
725 enum al_serdes_lane lane,
726 enum al_serdes_tx_deemph_param param);
729 * run Rx eye measurement.
731 * @param obj The object context
733 * @param grp The SERDES group
735 * @param lane The SERDES lane within the group
737 * @param timeout timeout in uSec
739 * @param value Rx eye measurement value
740 * (0 - completely closed eye, 0xffff - completely open eye).
742 * @return 0 if no error found.
744 int al_serdes_eye_measure_run(
745 struct al_serdes_obj *obj,
746 enum al_serdes_group grp,
747 enum al_serdes_lane lane,
749 unsigned int *value);
752 * Eye diagram single sampling
754 * @param obj The object context
756 * @param grp The SERDES group
758 * @param lane The SERDES lane within the group
760 * @param x Sampling X position (0 - 63 --> -1.00 UI ... 1.00 UI)
762 * @param y Sampling Y position (0 - 62 --> 500mV ... -500mV)
764 * @param timeout timeout in uSec
766 * @param value Eye diagram sample value (BER - 0x0000 - 0xffff)
768 * @return 0 if no error found.
770 int al_serdes_eye_diag_sample(
771 struct al_serdes_obj *obj,
772 enum al_serdes_group grp,
773 enum al_serdes_lane lane,
776 unsigned int timeout,
777 unsigned int *value);
780 * Check if signal is detected
782 * @param obj The object context
784 * @param grp The SERDES group
786 * @param lane The SERDES lane within the group
788 * @return true if signal is detected. false otherwise.
790 al_bool al_serdes_signal_is_detected(
791 struct al_serdes_obj *obj,
792 enum al_serdes_group grp,
793 enum al_serdes_lane lane);
796 struct al_serdes_adv_tx_params {
798 * select the input values location.
799 * When set to true the values will be taken from the internal registers
800 * that will be override with the next following parameters.
801 * When set to false the values will be taken from external pins (the
802 * other parameters in this case is not needed)
806 * Transmit Amplitude control signal. Used to define the full-scale
807 * maximum swing of the driver.
808 * 000 - Not Supported
809 * 001 - 952mVdiff-pkpk
810 * 010 - 1024mVdiff-pkpk
811 * 011 - 1094mVdiff-pkpk
812 * 100 - 1163mVdiff-pkpk
813 * 101 - 1227mVdiff-pkpk
814 * 110 - 1283mVdiff-pkpk
815 * 111 - 1331mVdiff-pkpk
818 /* Defines the total number of driver units allocated in the driver */
819 uint8_t total_driver_units;
820 /* Defines the total number of driver units allocated to the
821 * first post-cursor (C+1) tap. */
823 /* Defines the total number of driver units allocated to the
824 * second post-cursor (C+2) tap. */
826 /* Defines the total number of driver units allocated to the
827 * first pre-cursor (C-1) tap. */
829 /* TX driver Slew Rate control:
838 struct al_serdes_adv_rx_params {
840 * select the input values location.
841 * When set to true the values will be taken from the internal registers
842 * that will be override with the next following parameters.
843 * When set to false the values will be taken based in the equalization
844 * results (the other parameters in this case is not needed)
847 /* RX agc high frequency dc gain:
858 /* DFE post-shaping tap 3dB frequency
868 uint8_t dfe_3db_freq;
869 /* DFE post-shaping tap gain
870 * 0: no pulse shaping tap
880 /* DFE first tap gain control
882 * -4'b0001: +10mVpeak
884 * -4'b0110: +55mVpeak
885 * -4'b0111: +64mVpeak
887 * -4'b1001: -10mVpeak
889 * -4'b1110: -55mVpeak
890 * -4'b1111: -64mVpeak
892 uint8_t dfe_first_tap_ctrl;
893 /* DFE second tap gain control
897 * -4'b0110: +46mVpeak
898 * -4'b0111: +53mVpeak
902 * -4'b1110: -46mVpeak
903 * -4'b1111: -53mVpeak
905 uint8_t dfe_secound_tap_ctrl;
906 /* DFE third tap gain control
910 * -4'b0110: +38mVpeak
911 * -4'b0111: +44mVpeak
915 * -4'b1110: -38mVpeak
916 * -4'b1111: -44mVpeak
918 uint8_t dfe_third_tap_ctrl;
919 /* DFE fourth tap gain control
923 * -4'b0110: +29mVpeak
924 * -4'b0111: +33mVpeak
928 * -4'b1110: -29mVpeak
929 * -4'b1111: -33mVpeak
931 uint8_t dfe_fourth_tap_ctrl;
932 /* Low frequency agc gain (att) select
933 * -3'b000: Disconnected
942 uint8_t low_freq_agc_gain;
943 /* Provides a RX Equalizer pre-hint, prior to beginning
944 * adaptive equalization */
945 uint8_t precal_code_sel;
946 /* High frequency agc boost control
948 * Max d31: Boost ~20dB
950 uint8_t high_freq_agc_boost;
954 * configure tx advanced parameters
956 * @param obj The object context
958 * @param grp The SERDES group
960 * @param lane The SERDES lane within the group
962 * @param params pointer to the tx parameters
964 void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj,
965 enum al_serdes_group grp,
966 enum al_serdes_lane lane,
967 struct al_serdes_adv_tx_params *params);
970 * read tx advanced parameters
972 * @param obj The object context
974 * @param grp The SERDES group
976 * @param lane The SERDES lane within the group
978 * @param params pointer to the tx parameters
980 void al_serdes_tx_advanced_params_get(struct al_serdes_obj *obj,
981 enum al_serdes_group grp,
982 enum al_serdes_lane lane,
983 struct al_serdes_adv_tx_params *params);
986 * configure rx advanced parameters
988 * @param obj The object context
990 * @param grp The SERDES group
992 * @param lane The SERDES lane within the group
994 * @param params pointer to the rx parameters
996 void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj,
997 enum al_serdes_group grp,
998 enum al_serdes_lane lane,
999 struct al_serdes_adv_rx_params *params);
1002 * read rx advanced parameters
1004 * @param obj The object context
1006 * @param grp The SERDES group
1008 * @param lane The SERDES lane within the group
1010 * @param params pointer to the rx parameters
1012 void al_serdes_rx_advanced_params_get(struct al_serdes_obj *obj,
1013 enum al_serdes_group grp,
1014 enum al_serdes_lane lane,
1015 struct al_serdes_adv_rx_params* params);
1018 * Switch entire SerDes group to SGMII mode based on 156.25 Mhz reference clock
1020 * @param obj The object context
1022 * @param grp The SERDES group
1024 void al_serdes_mode_set_sgmii(
1025 struct al_serdes_obj *obj,
1026 enum al_serdes_group grp);
1029 * Switch entire SerDes group to KR mode based on 156.25 Mhz reference clock
1031 * @param obj The object context
1033 * @param grp The SERDES group
1035 void al_serdes_mode_set_kr(
1036 struct al_serdes_obj *obj,
1037 enum al_serdes_group grp);
1040 * performs SerDes HW equalization test and update equalization parameters
1042 * @param obj the object context
1044 * @param grp the SERDES group
1046 * @param lane The SERDES lane within the group
1048 int al_serdes_rx_equalization(
1049 struct al_serdes_obj *obj,
1050 enum al_serdes_group grp,
1051 enum al_serdes_lane lane);
1054 * performs Rx equalization and compute the width and height of the eye
1056 * @param obj the object context
1058 * @param grp the SERDES group
1060 * @param lane The SERDES lane within the group
1062 * @param width the output width of the eye
1064 * @param height the output height of the eye
1066 int al_serdes_calc_eye_size(
1067 struct al_serdes_obj *obj,
1068 enum al_serdes_group grp,
1069 enum al_serdes_lane lane,
1076 struct al_serdes_sris_params {
1077 /* Controls the frequency accuracy threshold (ppm) for lock detection CDR */
1078 uint16_t ppm_drift_count;
1079 /* Controls the frequency accuracy threshold (ppm) for lock detection in the CDR */
1080 uint16_t ppm_drift_max;
1081 /* Controls the frequency accuracy threshold (ppm) for lock detection in PLL */
1082 uint16_t synth_ppm_drift_max;
1083 /* Elastic buffer full threshold for PCIE modes: GEN1/GEN2 */
1085 /* Elastic buffer full threshold for PCIE modes: GEN3 */
1086 uint8_t full_pcie_g3;
1087 /* Elastic buffer midpoint threshold.
1088 * Sets the depth of the buffer while in PCIE mode, GEN1/GEN2
1090 uint8_t rd_threshold_d2r1;
1091 /* Elastic buffer midpoint threshold.
1092 * Sets the depth of the buffer while in PCIE mode, GEN3
1094 uint8_t rd_threshold_pcie_g3;
1098 * SRIS: Separate Refclk Independent SSC (Spread Spectrum Clocking)
1099 * Currently available only for PCIe interfaces.
1100 * When working with local Refclk, same SRIS configuration in both serdes sides
1101 * (EP and RC in PCIe interface) is required.
1103 * performs SRIS configuration according to params
1105 * @param obj the object context
1107 * @param grp the SERDES group
1109 * @param params the SRIS parameters
1111 void al_serdes_sris_config(
1112 struct al_serdes_obj *obj,
1113 enum al_serdes_group grp,
1114 struct al_serdes_sris_params *params);
1122 #endif /* __AL_SRDS__ */
1124 /** @} end of SERDES group */