@@ -719,14 +719,17 @@ typedef struct {
719719
720720/* This array should be expandable for new freq grids in the future */
721721static freq_grid_info_t freq_grid_info [] = {
722- {"100GHz" , 100.0 , 1 , 5 , 5 * 4 , 5 << 4 ,},
723- {"75GHz" , 75.0 , 3 , 7 , 7 * 4 , 7 << 4 ,},
724- {"50GHz" , 50.0 , 1 , 4 , 4 * 4 , 4 << 4 ,},
725- {"33GHz" , 100.0 / 3 , 1 , 6 , 6 * 4 , 6 << 4 ,},
726- {"25GHz" , 25.0 , 1 , 3 , 3 * 4 , 3 << 4 ,},
727- {"12.5GHz" , 12.5 , 1 , 2 , 2 * 4 , 2 << 4 ,},
728- {"6.25GHz" , 6.25 , 1 , 1 , 1 * 4 , 1 << 4 ,},
729- {"3.125GHz" , 3.125 , 1 , 0 , 0 * 4 , 0 << 4 ,},
722+ // freq_grid_desc freq_increment ch_increment freq_grid_bit freq_grid_off freq_grid_spac
723+ {"100GHz" , 100.0 , 1 , 0b0101 , 5 * 4 , 5 << 4 ,},
724+ {"75GHz" , 75.0 , 3 , 0b0111 , 7 * 4 , 7 << 4 ,},
725+ {"50GHz" , 50.0 , 1 , 0b0100 , 4 * 4 , 4 << 4 ,},
726+ {"33GHz" , 100.0 / 3 , 1 , 0b0110 , 6 * 4 , 6 << 4 ,},
727+ {"25GHz" , 25.0 , 1 , 0b0011 , 3 * 4 , 3 << 4 ,},
728+ {"12.5GHz" , 12.5 , 1 , 0b0010 , 2 * 4 , 2 << 4 ,},
729+ {"6.25GHz" , 6.25 , 1 , 0b0001 , 1 * 4 , 1 << 4 ,},
730+ {"3.125GHz" , 3.125 , 1 , 0b0000 , 0 * 4 , 0 << 4 ,},
731+ /* 0b1000 - 0b1110 Reserved */
732+ /* 0b1111 Not available */
730733};
731734
732735// For reference: CMIS 5.1 8.16.1.2
@@ -7462,6 +7465,228 @@ const char* bf_cmis_get_datapath_config_state_str(int port,
74627465 return qsfp_dp_config_str [state % asize ];
74637466}
74647467
7468+ /* By SunZheng, 2025/02/10. */
7469+ int bf_cmis_module_frequency_set (int port ,
7470+ uint8_t grid_spac ,
7471+ double frequency ) {
7472+ int rc ;
7473+ bool ctrl_flag , tune_flag ;
7474+ uint8_t readval [2 ];
7475+ uint8_t freq_grids [60 ]; // data of supported frequency grids
7476+ uint8_t fine_tuning_data [6 ]; // fine-tuning resolution, low/high offset
7477+ uint8_t freq_grid_bit , // bit offset of frequency grid support flag
7478+ freq_grid_off , // byte offset of laser capability
7479+ freq_grid_spac ; // frequency grid spacing value to apply
7480+ int16_t ch_increment , // channel increment for each frequency grid
7481+ freq_grid_ch ; // frequency grid channel value to apply
7482+ int16_t freq_grid_ch_low , // lowest channel value for each frequency grid
7483+ freq_grid_ch_high ; // highest channel value for each frequency grid
7484+ int16_t fine_tuning_off_low , // lowest offset value for fine-tuning
7485+ fine_tuning_off_high , // highest offset value for fine-tuning
7486+ fine_tuning_res , // fine-tuning resolution *how to use this? TBD*
7487+ fine_tuning_off ; // fine-tuning offset value to apply
7488+
7489+ /* Frequency: Unit in THz
7490+ Convert frequency from THz to GHz first.
7491+ */
7492+ frequency *= 1000.0 ;
7493+
7494+ if (!bf_qsfp_is_cmis (port )) {
7495+ LOG_ERROR ("QSFP %2d : wavelength setting unsupported for this module" ,
7496+ port );
7497+ return -1 ;
7498+ }
7499+
7500+ bf_qsfp_get_wavelength_flags (port , & ctrl_flag , & tune_flag );
7501+ if (!tune_flag ) {
7502+ LOG_ERROR ("QSFP %2d : wavelength setting unsupported for this module" ,
7503+ port );
7504+ return -1 ;
7505+ }
7506+
7507+ // Frequency tuning support
7508+ rc = bf_qsfp_field_read_onebank (port ,
7509+ LASER_FREQ_SUPPORT ,
7510+ 0 ,
7511+ 0 ,
7512+ 1 ,
7513+ & readval [0 ]);
7514+ if (rc ) {
7515+ LOG_ERROR ("QSFP %2d : rc=%d wavelength setting failed for this module" ,
7516+ port , rc );
7517+ return -1 ;
7518+ }
7519+
7520+ // Fine-tuning support
7521+ rc = bf_qsfp_field_read_onebank (port ,
7522+ FINE_TUNING_SUPPORT ,
7523+ 0 ,
7524+ 0 ,
7525+ 1 ,
7526+ & readval [1 ]);
7527+ if (rc ) {
7528+ LOG_ERROR ("QSFP %2d : rc=%d wavelength setting failed for this module" ,
7529+ port , rc );
7530+ return -1 ;
7531+ }
7532+
7533+ // Frequency grids
7534+ rc = bf_qsfp_field_read_onebank (port ,
7535+ LASER_FREQ_GRIDS ,
7536+ 0 ,
7537+ 0 ,
7538+ 60 ,
7539+ freq_grids );
7540+ if (rc ) {
7541+ LOG_ERROR ("QSFP %2d : rc=%d wavelength setting failed for this module" ,
7542+ port , rc );
7543+ return -1 ;
7544+ }
7545+
7546+ // Fine-tuning resolution
7547+ rc = bf_qsfp_field_read_onebank (port ,
7548+ FINE_TUNING_RESOLUTION ,
7549+ 0 ,
7550+ 0 ,
7551+ 2 ,
7552+ & fine_tuning_data [0 ]);
7553+ if (rc ) {
7554+ LOG_ERROR ("QSFP %2d : rc=%d wavelength setting failed for this module" ,
7555+ port , rc );
7556+ return -1 ;
7557+ }
7558+
7559+ // Fine-tuning resolution
7560+ rc = bf_qsfp_field_read_onebank (port ,
7561+ FINE_TUNING_OFFSETS ,
7562+ 0 ,
7563+ 0 ,
7564+ 4 ,
7565+ & fine_tuning_data [2 ]);
7566+ if (rc ) {
7567+ LOG_ERROR ("QSFP %2d : rc=%d wavelength setting failed for this module" ,
7568+ port , rc );
7569+ return -1 ;
7570+ }
7571+
7572+ /* Check if there're any supported grids.
7573+ This should be modified if the supported grids
7574+ Get expanded in the future. */
7575+ if (!(readval [0 ] & 0xff )) {
7576+ LOG_ERROR ("QSFP %2d : wavelength setting unsupported for this module" ,
7577+ port );
7578+ return -1 ;
7579+ }
7580+
7581+ double freq_increment , ch_frequency ;
7582+ double fine_tuning_freq ;
7583+ char * freq_grid_desc ;
7584+ bool found = false;
7585+ for (int i = 0 ; i < ARRAY_LENGTH (freq_grid_info ); i ++ ) {
7586+ freq_grid_desc = freq_grid_info [i ].freq_grid_desc ;
7587+ ch_increment = freq_grid_info [i ].ch_increment ;
7588+ freq_increment = freq_grid_info [i ].freq_increment / ch_increment ;
7589+ freq_grid_bit = freq_grid_info [i ].freq_grid_bit ;
7590+ freq_grid_off = freq_grid_info [i ].freq_grid_off ;
7591+ freq_grid_spac = freq_grid_info [i ].freq_grid_spac ;
7592+
7593+ /* Check if this spacing grid matches. */
7594+ if (freq_grid_bit != grid_spac ) {
7595+ continue ;
7596+ }
7597+ /* Check if this spacing grid is supported. */
7598+ if (!((readval [0 ] >> freq_grid_bit ) & 0x1 )) {
7599+ LOG_ERROR ("QSFP %2d : unsupported frequency grid %s" ,
7600+ port , freq_grid_desc );
7601+ goto done ;
7602+ }
7603+
7604+ freq_grid_ch_low = (freq_grids [freq_grid_off + 0 ] << 8 ) |
7605+ freq_grids [freq_grid_off + 1 ];
7606+ freq_grid_ch_high = (freq_grids [freq_grid_off + 2 ] << 8 ) |
7607+ freq_grids [freq_grid_off + 3 ];
7608+ freq_grid_ch = (int16_t )((frequency - LASER_BASE_FREQ ) / freq_increment );
7609+ if ((freq_grid_ch_low <= freq_grid_ch ) && (freq_grid_ch <= freq_grid_ch_high )) {
7610+ ch_frequency = LASER_BASE_FREQ + freq_grid_ch * freq_increment ;
7611+ found = true;
7612+ goto done ;
7613+ }
7614+ }
7615+
7616+ done :
7617+ if (!found ) {
7618+ LOG_ERROR ("QSFP %2d : unsupported frequency %.3f" ,
7619+ port , frequency );
7620+ return -1 ;
7621+ }
7622+
7623+ LOG_DEBUG ("QSFP %2d : "
7624+ "found supported frequency %.3f GHz, "
7625+ "channel num %d of %s grid spacing" ,
7626+ port , ch_frequency ,
7627+ freq_grid_ch , freq_grid_desc );
7628+ bf_qsfp_info_arr [port ].laser_info .tuning_set = true;
7629+
7630+ bf_qsfp_info_arr [port ].laser_info .freq_grid_spac = freq_grid_spac ;
7631+ bf_qsfp_info_arr [port ].laser_info .freq_grid_ch = freq_grid_ch ;
7632+
7633+ // Check if fine-tuning support
7634+ if ((readval [1 ] >> 7 ) & 0x1 ) {
7635+ fine_tuning_res = (fine_tuning_data [0 ] << 8 ) | fine_tuning_data [1 ];
7636+ fine_tuning_off_low = (fine_tuning_data [2 ] << 8 ) | fine_tuning_data [3 ];
7637+ fine_tuning_off_high = (fine_tuning_data [4 ] << 8 ) | fine_tuning_data [5 ];
7638+ if (fine_tuning_res != 0 ) {
7639+ fine_tuning_freq = frequency - ch_frequency ;
7640+ fine_tuning_off = (int16_t )(fine_tuning_freq * (1000 / fine_tuning_res ));
7641+ if ((fine_tuning_off_low <= fine_tuning_off ) && (fine_tuning_off <= fine_tuning_off_high )) {
7642+ LOG_DEBUG ("QSFP %2d : fine-tuning supported, "
7643+ "frequency %.3f GHz matching offset %d" ,
7644+ port , fine_tuning_freq , fine_tuning_off );
7645+ bf_qsfp_info_arr [port ].laser_info .fine_tuning_off = fine_tuning_off ;
7646+ } else {
7647+ LOG_DEBUG ("QSFP %2d : skip fine-tuning due to offset out of range" ,
7648+ port );
7649+ }
7650+ } else {
7651+ LOG_DEBUG ("QSFP %2d : skip fine-tuning due to invalid resolution" ,
7652+ port );
7653+ }
7654+ }
7655+
7656+ return 0 ;
7657+ }
7658+
7659+ /* By SunZheng, 2025/02/10. */
7660+ bool bf_cmis_module_is_grid_spac_support (int port ,
7661+ uint8_t grid_spac ) {
7662+ /* Freq Grid Bit:
7663+ 1. 0b0000 <=> 3.125GHz
7664+ 2. 0b0001 <=> 6.25GHz
7665+ 3. 0b0010 <=> 12.5GHz
7666+ 4. 0b0011 <=> 25GHz
7667+ 5. 0b0100 <=> 50GHz
7668+ 6. 0b0101 <=> 100GHz
7669+ 7. 0b0110 <=> 33GHz
7670+ 8. 0b0111 <=> 75GHz
7671+ */
7672+ int rc ;
7673+ uint8_t readval ;
7674+ // Frequency tuning support
7675+ rc = bf_qsfp_field_read_onebank (port ,
7676+ LASER_FREQ_SUPPORT ,
7677+ 0 ,
7678+ 0 ,
7679+ 1 ,
7680+ & readval );
7681+ if (rc ) {
7682+ LOG_ERROR ("QSFP %2d : rc=%d supported grid spacing reading failed for this module" ,
7683+ port , rc );
7684+ return false;
7685+ }
7686+
7687+ return (bool )((readval >> grid_spac ) & 0b1 );
7688+ }
7689+
74657690/* By SunZheng, 2024/10/09. */
74667691int bf_cmis_module_wavelength_get (int port ,
74677692 int ch ,
@@ -7506,7 +7731,9 @@ int bf_cmis_module_wavelength_set (int port,
75067731 freq_grid_ch ; // frequency grid channel value to apply
75077732 int16_t freq_grid_ch_low , // lowest channel value for each frequency grid
75087733 freq_grid_ch_high ; // highest channel value for each frequency grid
7509- int16_t // fine_tuning_res, // fine-tuning resolution *how to use this? TBD*
7734+ int16_t fine_tuning_off_low , // lowest offset value for fine-tuning
7735+ fine_tuning_off_high , // highest offset value for fine-tuning
7736+ fine_tuning_res , // fine-tuning resolution *how to use this? TBD*
75107737 fine_tuning_off ; // fine-tuning offset value to apply
75117738
75127739 if (!bf_qsfp_is_cmis (port )) {
@@ -7619,7 +7846,7 @@ int bf_cmis_module_wavelength_set (int port,
76197846 freq_low = LASER_BASE_FREQ + freq_grid_ch_low * freq_increment ;
76207847 freq_high = LASER_BASE_FREQ + freq_grid_ch_high * freq_increment ;
76217848
7622- if ((frequency > freq_low ) && (frequency < freq_high )) {
7849+ if ((freq_low <= frequency ) && (frequency <= freq_high )) {
76237850 for (int16_t ch = freq_grid_ch_low ;
76247851 ch <= freq_grid_ch_high ;
76257852 ch += ch_increment ) {
@@ -7655,13 +7882,25 @@ int bf_cmis_module_wavelength_set (int port,
76557882
76567883 // Check if fine-tuning support
76577884 if ((readval [1 ] >> 7 ) & 0x1 ) {
7658- fine_tuning_freq = frequency - ch_frequency ;
7659- // fine_tuning_res = (fine_tuning_data[0] << 8) | fine_tuning_data[1];
7660- fine_tuning_off = (int16_t )(fine_tuning_freq * 1000 );
7661- LOG_DEBUG ("QSFP %2d : fine-tuning supported, "
7662- "frequency %.3f GHz matching offset %d" ,
7663- port , fine_tuning_freq , fine_tuning_off );
7664- bf_qsfp_info_arr [port ].laser_info .fine_tuning_off = fine_tuning_off ;
7885+ fine_tuning_res = (fine_tuning_data [0 ] << 8 ) | fine_tuning_data [1 ];
7886+ fine_tuning_off_low = (fine_tuning_data [2 ] << 8 ) | fine_tuning_data [3 ];
7887+ fine_tuning_off_high = (fine_tuning_data [4 ] << 8 ) | fine_tuning_data [5 ];
7888+ if (fine_tuning_res != 0 ) {
7889+ fine_tuning_freq = frequency - ch_frequency ;
7890+ fine_tuning_off = (int16_t )(fine_tuning_freq * (1000 / fine_tuning_res ));
7891+ if ((fine_tuning_off_low <= fine_tuning_off ) && (fine_tuning_off <= fine_tuning_off_high )) {
7892+ LOG_DEBUG ("QSFP %2d : fine-tuning supported, "
7893+ "frequency %.3f GHz matching offset %d" ,
7894+ port , fine_tuning_freq , fine_tuning_off );
7895+ bf_qsfp_info_arr [port ].laser_info .fine_tuning_off = fine_tuning_off ;
7896+ } else {
7897+ LOG_DEBUG ("QSFP %2d : skip fine-tuning due to offset out of range" ,
7898+ port );
7899+ }
7900+ } else {
7901+ LOG_DEBUG ("QSFP %2d : skip fine-tuning due to invalid resolution" ,
7902+ port );
7903+ }
76657904 }
76667905
76677906 return 0 ;
0 commit comments